MM-33903 rename slash commands & permission (#17494)
- rename slash commands
- "remote" -> "secure-connection"
- "share" -> "share-channel"
- change status icons to text (translated)
- remove channel invite "Description" field
- rename permission "manage_remote_clusters" -> "manage_secure_connections"
Этот коммит содержится в:
@@ -182,7 +182,7 @@ func TestDoAdvancedPermissionsMigration(t *testing.T) {
|
|||||||
"system_admin": allPermissionIDs,
|
"system_admin": allPermissionIDs,
|
||||||
}
|
}
|
||||||
assert.Contains(t, allPermissionIDs, model.PERMISSION_MANAGE_SHARED_CHANNELS.Id, "manage_shared_channels permission not found")
|
assert.Contains(t, allPermissionIDs, model.PERMISSION_MANAGE_SHARED_CHANNELS.Id, "manage_shared_channels permission not found")
|
||||||
assert.Contains(t, allPermissionIDs, model.PERMISSION_MANAGE_REMOTE_CLUSTERS.Id, "manage_remote_clusters permission not found")
|
assert.Contains(t, allPermissionIDs, model.PERMISSION_MANAGE_SECURE_CONNECTIONS.Id, "manage_secure_connections permission not found")
|
||||||
|
|
||||||
// Check the migration matches what's expected.
|
// Check the migration matches what's expected.
|
||||||
for name, permissions := range expected1 {
|
for name, permissions := range expected1 {
|
||||||
|
|||||||
@@ -70,7 +70,8 @@ const (
|
|||||||
PermissionReadPrivateChannelGroups = "read_private_channel_groups"
|
PermissionReadPrivateChannelGroups = "read_private_channel_groups"
|
||||||
PermissionEditBrand = "edit_brand"
|
PermissionEditBrand = "edit_brand"
|
||||||
PermissionManageSharedChannels = "manage_shared_channels"
|
PermissionManageSharedChannels = "manage_shared_channels"
|
||||||
PermissionManageRemoteClusters = "manage_remote_clusters"
|
PermissionManageSecureConnections = "manage_secure_connections"
|
||||||
|
PermissionManageRemoteClusters = "manage_remote_clusters" // deprecated; use `manage_secure_connections`
|
||||||
)
|
)
|
||||||
|
|
||||||
func isRole(roleName string) func(*model.Role, map[string]map[string]bool) bool {
|
func isRole(roleName string) func(*model.Role, map[string]map[string]bool) bool {
|
||||||
@@ -525,13 +526,24 @@ func (a *App) getBillingPermissionsMigration() (permissionsMap, error) {
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) getAddManageRemoteClustersPermissionsMigration() (permissionsMap, error) {
|
func (a *App) getAddManageSecureConnectionsPermissionsMigration() (permissionsMap, error) {
|
||||||
return permissionsMap{
|
transformations := []permissionTransformation{}
|
||||||
|
|
||||||
|
// add the new permission to system admin
|
||||||
|
transformations = append(transformations,
|
||||||
permissionTransformation{
|
permissionTransformation{
|
||||||
On: isRole(model.SYSTEM_ADMIN_ROLE_ID),
|
On: isRole(model.SYSTEM_ADMIN_ROLE_ID),
|
||||||
Add: []string{PermissionManageRemoteClusters},
|
Add: []string{PermissionManageSecureConnections},
|
||||||
},
|
})
|
||||||
}, nil
|
|
||||||
|
// remote the decprecated permission from system admin
|
||||||
|
transformations = append(transformations,
|
||||||
|
permissionTransformation{
|
||||||
|
On: isRole(model.SYSTEM_ADMIN_ROLE_ID),
|
||||||
|
Remove: []string{PermissionManageRemoteClusters},
|
||||||
|
})
|
||||||
|
|
||||||
|
return transformations, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) getAddDownloadComplianceExportResult() (permissionsMap, error) {
|
func (a *App) getAddDownloadComplianceExportResult() (permissionsMap, error) {
|
||||||
@@ -910,7 +922,7 @@ func (a *App) DoPermissionsMigrations() error {
|
|||||||
{Key: model.MIGRATION_KEY_ADD_SYSTEM_CONSOLE_PERMISSIONS, Migration: a.getAddSystemConsolePermissionsMigration},
|
{Key: model.MIGRATION_KEY_ADD_SYSTEM_CONSOLE_PERMISSIONS, Migration: a.getAddSystemConsolePermissionsMigration},
|
||||||
{Key: model.MIGRATION_KEY_ADD_CONVERT_CHANNEL_PERMISSIONS, Migration: a.getAddConvertChannelPermissionsMigration},
|
{Key: model.MIGRATION_KEY_ADD_CONVERT_CHANNEL_PERMISSIONS, Migration: a.getAddConvertChannelPermissionsMigration},
|
||||||
{Key: model.MIGRATION_KEY_ADD_MANAGE_SHARED_CHANNEL_PERMISSIONS, Migration: a.getAddManageSharedChannelsPermissionsMigration},
|
{Key: model.MIGRATION_KEY_ADD_MANAGE_SHARED_CHANNEL_PERMISSIONS, Migration: a.getAddManageSharedChannelsPermissionsMigration},
|
||||||
{Key: model.MIGRATION_KEY_ADD_MANAGE_REMOTE_CLUSTERS_PERMISSIONS, Migration: a.getAddManageRemoteClustersPermissionsMigration},
|
{Key: model.MIGRATION_KEY_ADD_MANAGE_SECURE_CONNECTIONS_PERMISSIONS, Migration: a.getAddManageSecureConnectionsPermissionsMigration},
|
||||||
{Key: model.MIGRATION_KEY_ADD_SYSTEM_ROLES_PERMISSIONS, Migration: a.getSystemRolesPermissionsMigration},
|
{Key: model.MIGRATION_KEY_ADD_SYSTEM_ROLES_PERMISSIONS, Migration: a.getSystemRolesPermissionsMigration},
|
||||||
{Key: model.MIGRATION_KEY_ADD_BILLING_PERMISSIONS, Migration: a.getBillingPermissionsMigration},
|
{Key: model.MIGRATION_KEY_ADD_BILLING_PERMISSIONS, Migration: a.getBillingPermissionsMigration},
|
||||||
{Key: model.MIGRATION_KEY_ADD_DOWNLOAD_COMPLIANCE_EXPORT_RESULTS, Migration: a.getAddDownloadComplianceExportResult},
|
{Key: model.MIGRATION_KEY_ADD_DOWNLOAD_COMPLIANCE_EXPORT_RESULTS, Migration: a.getAddDownloadComplianceExportResult},
|
||||||
|
|||||||
@@ -10,19 +10,20 @@ import (
|
|||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/mattermost/mattermost-server/v5/model"
|
"github.com/mattermost/mattermost-server/v5/model"
|
||||||
|
"github.com/mattermost/mattermost-server/v5/shared/i18n"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestAddRemoteCluster(t *testing.T) {
|
func TestAddRemoteCluster(t *testing.T) {
|
||||||
t.Run("adding remote cluster with duplicate site url and remote team id", func(t *testing.T) {
|
th := Setup(t).InitBasic()
|
||||||
th := Setup(t).InitBasic()
|
defer th.TearDown()
|
||||||
defer th.TearDown()
|
|
||||||
|
|
||||||
|
t.Run("adding remote cluster with duplicate site url and remote team id", func(t *testing.T) {
|
||||||
remoteCluster := &model.RemoteCluster{
|
remoteCluster := &model.RemoteCluster{
|
||||||
RemoteTeamId: model.NewId(),
|
RemoteTeamId: model.NewId(),
|
||||||
Name: "test",
|
Name: "test1",
|
||||||
SiteURL: "http://localhost:8065",
|
SiteURL: "http://www1.example.com:8065",
|
||||||
Token: "test",
|
Token: model.NewId(),
|
||||||
RemoteToken: "test",
|
RemoteToken: model.NewId(),
|
||||||
Topics: "",
|
Topics: "",
|
||||||
CreatorId: th.BasicUser.Id,
|
CreatorId: th.BasicUser.Id,
|
||||||
}
|
}
|
||||||
@@ -33,19 +34,16 @@ func TestAddRemoteCluster(t *testing.T) {
|
|||||||
remoteCluster.RemoteId = model.NewId()
|
remoteCluster.RemoteId = model.NewId()
|
||||||
_, err = th.App.AddRemoteCluster(remoteCluster)
|
_, err = th.App.AddRemoteCluster(remoteCluster)
|
||||||
require.NotNil(t, err, "Adding a duplicate remote cluster should error")
|
require.NotNil(t, err, "Adding a duplicate remote cluster should error")
|
||||||
assert.Contains(t, err.Error(), "Remote cluster has already been added.")
|
assert.Contains(t, err.Error(), i18n.T("api.remote_cluster.save_not_unique.app_error"))
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("adding remote cluster with duplicate site url or remote team id is allowed", func(t *testing.T) {
|
t.Run("adding remote cluster with duplicate site url or remote team id is allowed", func(t *testing.T) {
|
||||||
th := Setup(t).InitBasic()
|
|
||||||
defer th.TearDown()
|
|
||||||
|
|
||||||
remoteCluster := &model.RemoteCluster{
|
remoteCluster := &model.RemoteCluster{
|
||||||
RemoteTeamId: model.NewId(),
|
RemoteTeamId: model.NewId(),
|
||||||
Name: "test",
|
Name: "test2",
|
||||||
SiteURL: "http://localhost:8065",
|
SiteURL: "http://www2.exmaple.com:8065",
|
||||||
Token: "test",
|
Token: model.NewId(),
|
||||||
RemoteToken: "test",
|
RemoteToken: model.NewId(),
|
||||||
Topics: "",
|
Topics: "",
|
||||||
CreatorId: th.BasicUser.Id,
|
CreatorId: th.BasicUser.Id,
|
||||||
}
|
}
|
||||||
@@ -70,26 +68,26 @@ func TestAddRemoteCluster(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestUpdateRemoteCluster(t *testing.T) {
|
func TestUpdateRemoteCluster(t *testing.T) {
|
||||||
t.Run("update remote cluster with an already existing site url and team id", func(t *testing.T) {
|
th := Setup(t).InitBasic()
|
||||||
th := Setup(t).InitBasic()
|
defer th.TearDown()
|
||||||
defer th.TearDown()
|
|
||||||
|
|
||||||
|
t.Run("update remote cluster with an already existing site url and team id", func(t *testing.T) {
|
||||||
remoteCluster := &model.RemoteCluster{
|
remoteCluster := &model.RemoteCluster{
|
||||||
RemoteTeamId: model.NewId(),
|
RemoteTeamId: model.NewId(),
|
||||||
Name: "test",
|
Name: "test3",
|
||||||
SiteURL: "http://localhost:8065",
|
SiteURL: "http://www3.exmaple.com:8065",
|
||||||
Token: "test",
|
Token: model.NewId(),
|
||||||
RemoteToken: "test",
|
RemoteToken: model.NewId(),
|
||||||
Topics: "",
|
Topics: "",
|
||||||
CreatorId: th.BasicUser.Id,
|
CreatorId: th.BasicUser.Id,
|
||||||
}
|
}
|
||||||
|
|
||||||
otherRemoteCluster := &model.RemoteCluster{
|
otherRemoteCluster := &model.RemoteCluster{
|
||||||
RemoteTeamId: model.NewId(),
|
RemoteTeamId: model.NewId(),
|
||||||
Name: "test",
|
Name: "test4",
|
||||||
SiteURL: "http://localhost:8066",
|
SiteURL: "http://www4.example.com:8066",
|
||||||
Token: "test",
|
Token: model.NewId(),
|
||||||
RemoteToken: "test",
|
RemoteToken: model.NewId(),
|
||||||
Topics: "",
|
Topics: "",
|
||||||
CreatorId: th.BasicUser.Id,
|
CreatorId: th.BasicUser.Id,
|
||||||
}
|
}
|
||||||
@@ -104,29 +102,26 @@ func TestUpdateRemoteCluster(t *testing.T) {
|
|||||||
savedRemoteClustered.RemoteTeamId = remoteCluster.RemoteTeamId
|
savedRemoteClustered.RemoteTeamId = remoteCluster.RemoteTeamId
|
||||||
_, err = th.App.UpdateRemoteCluster(savedRemoteClustered)
|
_, err = th.App.UpdateRemoteCluster(savedRemoteClustered)
|
||||||
require.NotNil(t, err, "Updating remote cluster with duplicate site url should error")
|
require.NotNil(t, err, "Updating remote cluster with duplicate site url should error")
|
||||||
assert.Contains(t, err.Error(), "Remote cluster with the same url already exists.")
|
assert.Contains(t, err.Error(), i18n.T("api.remote_cluster.update_not_unique.app_error"))
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("update remote cluster with an already existing site url or team id, is allowed", func(t *testing.T) {
|
t.Run("update remote cluster with an already existing site url or team id, is allowed", func(t *testing.T) {
|
||||||
th := Setup(t).InitBasic()
|
|
||||||
defer th.TearDown()
|
|
||||||
|
|
||||||
remoteCluster := &model.RemoteCluster{
|
remoteCluster := &model.RemoteCluster{
|
||||||
RemoteTeamId: model.NewId(),
|
RemoteTeamId: model.NewId(),
|
||||||
Name: "test",
|
Name: "test5",
|
||||||
SiteURL: "http://localhost:8065",
|
SiteURL: "http://www5.example.com:8065",
|
||||||
Token: "test",
|
Token: model.NewId(),
|
||||||
RemoteToken: "test",
|
RemoteToken: model.NewId(),
|
||||||
Topics: "",
|
Topics: "",
|
||||||
CreatorId: th.BasicUser.Id,
|
CreatorId: th.BasicUser.Id,
|
||||||
}
|
}
|
||||||
|
|
||||||
otherRemoteCluster := &model.RemoteCluster{
|
otherRemoteCluster := &model.RemoteCluster{
|
||||||
RemoteTeamId: model.NewId(),
|
RemoteTeamId: model.NewId(),
|
||||||
Name: "test",
|
Name: "test6",
|
||||||
SiteURL: "http://localhost:8066",
|
SiteURL: "http://www6.example.com:8065",
|
||||||
Token: "test",
|
Token: model.NewId(),
|
||||||
RemoteToken: "test",
|
RemoteToken: model.NewId(),
|
||||||
Topics: "",
|
Topics: "",
|
||||||
CreatorId: th.BasicUser.Id,
|
CreatorId: th.BasicUser.Id,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ func handleInvitation(s *Server, syncService SharedChannelServiceIFace, event *m
|
|||||||
return errors.Wrap(err, fmt.Sprintf("couldn't find remote cluster %s, for creating shared channel invitation for a DM", *participant.RemoteId))
|
return errors.Wrap(err, fmt.Sprintf("couldn't find remote cluster %s, for creating shared channel invitation for a DM", *participant.RemoteId))
|
||||||
}
|
}
|
||||||
|
|
||||||
return syncService.SendChannelInvite(channel, creator.Id, "", rc, sharedchannel.WithDirectParticipantID(creator.Id), sharedchannel.WithDirectParticipantID(participant.Id))
|
return syncService.SendChannelInvite(channel, creator.Id, rc, sharedchannel.WithDirectParticipantID(creator.Id), sharedchannel.WithDirectParticipantID(participant.Id))
|
||||||
}
|
}
|
||||||
|
|
||||||
func getUserFromEvent(s *Server, event *model.WebSocketEvent, key string) (*model.User, error) {
|
func getUserFromEvent(s *Server, event *model.WebSocketEvent, key string) (*model.User, error) {
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ type SharedChannelServiceIFace interface {
|
|||||||
Shutdown() error
|
Shutdown() error
|
||||||
Start() error
|
Start() error
|
||||||
NotifyChannelChanged(channelId string)
|
NotifyChannelChanged(channelId string)
|
||||||
SendChannelInvite(channel *model.Channel, userId string, description string, rc *model.RemoteCluster, options ...sharedchannel.InviteOption) error
|
SendChannelInvite(channel *model.Channel, userId string, rc *model.RemoteCluster, options ...sharedchannel.InviteOption) error
|
||||||
Active() bool
|
Active() bool
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,7 +56,7 @@ func (mrcs *mockSharedChannelService) Active() bool {
|
|||||||
return mrcs.active
|
return mrcs.active
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mrcs *mockSharedChannelService) SendChannelInvite(channel *model.Channel, userId string, description string, rc *model.RemoteCluster, options ...sharedchannel.InviteOption) error {
|
func (mrcs *mockSharedChannelService) SendChannelInvite(channel *model.Channel, userId string, rc *model.RemoteCluster, options ...sharedchannel.InviteOption) error {
|
||||||
mrcs.numInvitations += 1
|
mrcs.numInvitations += 1
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,14 +15,14 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
AvailableRemoteActions = "invite, accept, remove, status"
|
AvailableRemoteActions = "create, accept, remove, status"
|
||||||
)
|
)
|
||||||
|
|
||||||
type RemoteProvider struct {
|
type RemoteProvider struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
CommandTriggerRemote = "remote"
|
CommandTriggerRemote = "secure-connection"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@@ -37,23 +37,23 @@ func (rp *RemoteProvider) GetCommand(a *app.App, T i18n.TranslateFunc) *model.Co
|
|||||||
|
|
||||||
remote := model.NewAutocompleteData(rp.GetTrigger(), "[action]", T("api.command_remote.remote_add_remove.help", map[string]interface{}{"Actions": AvailableRemoteActions}))
|
remote := model.NewAutocompleteData(rp.GetTrigger(), "[action]", T("api.command_remote.remote_add_remove.help", map[string]interface{}{"Actions": AvailableRemoteActions}))
|
||||||
|
|
||||||
invite := model.NewAutocompleteData("invite", "", T("api.command_remote.invite.help"))
|
create := model.NewAutocompleteData("create", "", T("api.command_remote.invite.help"))
|
||||||
invite.AddNamedTextArgument("password", T("api.command_remote.invite_password.help"), T("api.command_remote.invite_password.hint"), "", true)
|
create.AddNamedTextArgument("name", T("api.command_remote.name.help"), T("api.command_remote.name.hint"), "", true)
|
||||||
invite.AddNamedTextArgument("name", T("api.command_remote.name.help"), T("api.command_remote.name.hint"), "", true)
|
create.AddNamedTextArgument("displayname", T("api.command_remote.displayname.help"), T("api.command_remote.displayname.hint"), "", false)
|
||||||
invite.AddNamedTextArgument("displayname", T("api.command_remote.displayname.help"), T("api.command_remote.displayname.hint"), "", false)
|
create.AddNamedTextArgument("password", T("api.command_remote.invite_password.help"), T("api.command_remote.invite_password.hint"), "", true)
|
||||||
|
|
||||||
accept := model.NewAutocompleteData("accept", "", T("api.command_remote.accept.help"))
|
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("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("displayname", T("api.command_remote.displayname.help"), T("api.command_remote.displayname.hint"), "", false)
|
||||||
|
accept.AddNamedTextArgument("password", T("api.command_remote.invite_password.help"), T("api.command_remote.invite_password.hint"), "", true)
|
||||||
accept.AddNamedTextArgument("invite", T("api.command_remote.invitation.help"), T("api.command_remote.invitation.hint"), "", true)
|
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"))
|
remove := model.NewAutocompleteData("remove", "", T("api.command_remote.remove.help"))
|
||||||
remove.AddNamedDynamicListArgument("remoteId", T("api.command_remote.remove_remote_id.help"), "builtin:remote", true)
|
remove.AddNamedDynamicListArgument("connectionID", T("api.command_remote.remove_remote_id.help"), "builtin:"+CommandTriggerRemote, true)
|
||||||
|
|
||||||
status := model.NewAutocompleteData("status", "", T("api.command_remote.status.help"))
|
status := model.NewAutocompleteData("status", "", T("api.command_remote.status.help"))
|
||||||
|
|
||||||
remote.AddCommand(invite)
|
remote.AddCommand(create)
|
||||||
remote.AddCommand(accept)
|
remote.AddCommand(accept)
|
||||||
remote.AddCommand(remove)
|
remote.AddCommand(remove)
|
||||||
remote.AddCommand(status)
|
remote.AddCommand(status)
|
||||||
@@ -69,8 +69,8 @@ func (rp *RemoteProvider) GetCommand(a *app.App, T i18n.TranslateFunc) *model.Co
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (rp *RemoteProvider) DoCommand(a *app.App, args *model.CommandArgs, message string) *model.CommandResponse {
|
func (rp *RemoteProvider) DoCommand(a *app.App, args *model.CommandArgs, message string) *model.CommandResponse {
|
||||||
if !a.HasPermissionTo(args.UserId, model.PERMISSION_MANAGE_SHARED_CHANNELS) {
|
if !a.HasPermissionTo(args.UserId, model.PERMISSION_MANAGE_SECURE_CONNECTIONS) {
|
||||||
return responsef(args.T("api.command_remote.permission_required", map[string]interface{}{"Permission": "manage_shared_channels"}))
|
return responsef(args.T("api.command_remote.permission_required", map[string]interface{}{"Permission": "manage_secure_connections"}))
|
||||||
}
|
}
|
||||||
|
|
||||||
margs := parseNamedArgs(args.Command)
|
margs := parseNamedArgs(args.Command)
|
||||||
@@ -80,8 +80,8 @@ func (rp *RemoteProvider) DoCommand(a *app.App, args *model.CommandArgs, message
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch action {
|
switch action {
|
||||||
case "invite":
|
case "create":
|
||||||
return rp.doInvite(a, args, margs)
|
return rp.doCreate(a, args, margs)
|
||||||
case "accept":
|
case "accept":
|
||||||
return rp.doAccept(a, args, margs)
|
return rp.doAccept(a, args, margs)
|
||||||
case "remove":
|
case "remove":
|
||||||
@@ -94,19 +94,19 @@ func (rp *RemoteProvider) DoCommand(a *app.App, args *model.CommandArgs, message
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (rp *RemoteProvider) GetAutoCompleteListItems(a *app.App, commandArgs *model.CommandArgs, arg *model.AutocompleteArg, parsed, toBeParsed string) ([]model.AutocompleteListItem, error) {
|
func (rp *RemoteProvider) GetAutoCompleteListItems(a *app.App, commandArgs *model.CommandArgs, arg *model.AutocompleteArg, parsed, toBeParsed string) ([]model.AutocompleteListItem, error) {
|
||||||
if !a.HasPermissionTo(commandArgs.UserId, model.PERMISSION_MANAGE_SHARED_CHANNELS) {
|
if !a.HasPermissionTo(commandArgs.UserId, model.PERMISSION_MANAGE_SECURE_CONNECTIONS) {
|
||||||
return nil, errors.New("You require `manage_shared_channels` permission to manage remote clusters.")
|
return nil, errors.New("You require `manage_secure_connections` permission to manage secure connections.")
|
||||||
}
|
}
|
||||||
|
|
||||||
if arg.Name == "remoteId" && strings.Contains(parsed, " remove ") {
|
if arg.Name == "connectionID" && strings.Contains(parsed, " remove ") {
|
||||||
return getRemoteClusterAutocompleteListItems(a, true)
|
return getRemoteClusterAutocompleteListItems(a, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, fmt.Errorf("`%s` is not a dynamic argument", arg.Name)
|
return nil, fmt.Errorf("`%s` is not a dynamic argument", arg.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// doInvite creates and displays an encrypted invite that can be used by a remote site to establish a simple trust.
|
// doCreate creates and displays an encrypted invite that can be used by a remote site to establish a simple trust.
|
||||||
func (rp *RemoteProvider) doInvite(a *app.App, args *model.CommandArgs, margs map[string]string) *model.CommandResponse {
|
func (rp *RemoteProvider) doCreate(a *app.App, args *model.CommandArgs, margs map[string]string) *model.CommandResponse {
|
||||||
password := margs["password"]
|
password := margs["password"]
|
||||||
if password == "" {
|
if password == "" {
|
||||||
return responsef(args.T("api.command_remote.missing_empty", map[string]interface{}{"Arg": "password"}))
|
return responsef(args.T("api.command_remote.missing_empty", map[string]interface{}{"Arg": "password"}))
|
||||||
@@ -153,7 +153,7 @@ func (rp *RemoteProvider) doInvite(a *app.App, args *model.CommandArgs, margs ma
|
|||||||
encoded := base64.URLEncoding.EncodeToString(encrypted)
|
encoded := base64.URLEncoding.EncodeToString(encrypted)
|
||||||
|
|
||||||
return responsef("##### " + args.T("api.command_remote.invitation_created") + "\n" +
|
return responsef("##### " + args.T("api.command_remote.invitation_created") + "\n" +
|
||||||
args.T("api.command_remote.invite_summary", map[string]interface{}{"Command": "/remote accept", "Invitation": encoded, "SiteURL": invite.SiteURL}))
|
args.T("api.command_remote.invite_summary", map[string]interface{}{"Command": "/secure-connection accept", "Invitation": encoded, "SiteURL": invite.SiteURL}))
|
||||||
}
|
}
|
||||||
|
|
||||||
// doAccept accepts an invitation generated by a remote site.
|
// doAccept accepts an invitation generated by a remote site.
|
||||||
@@ -209,7 +209,7 @@ func (rp *RemoteProvider) doAccept(a *app.App, args *model.CommandArgs, margs ma
|
|||||||
|
|
||||||
// doRemove removes a remote cluster from the database, effectively revoking the trust relationship.
|
// doRemove removes a remote cluster from the database, effectively revoking the trust relationship.
|
||||||
func (rp *RemoteProvider) doRemove(a *app.App, args *model.CommandArgs, margs map[string]string) *model.CommandResponse {
|
func (rp *RemoteProvider) doRemove(a *app.App, args *model.CommandArgs, margs map[string]string) *model.CommandResponse {
|
||||||
id, ok := margs["remoteId"]
|
id, ok := margs["connectionID"]
|
||||||
if !ok {
|
if !ok {
|
||||||
return responsef(args.T("api.command_remote.missing_empty", map[string]interface{}{"Arg": "remoteId"}))
|
return responsef(args.T("api.command_remote.missing_empty", map[string]interface{}{"Arg": "remoteId"}))
|
||||||
}
|
}
|
||||||
@@ -238,23 +238,16 @@ func (rp *RemoteProvider) doStatus(a *app.App, args *model.CommandArgs, _ map[st
|
|||||||
}
|
}
|
||||||
|
|
||||||
var sb strings.Builder
|
var sb strings.Builder
|
||||||
fmt.Fprintf(&sb, args.T("api.command_remote.remote_table_header")+"| \n")
|
fmt.Fprintf(&sb, args.T("api.command_remote.remote_table_header")+" \n")
|
||||||
fmt.Fprintf(&sb, "| ---- | -------- | ---------- | :-------------: | :----: | ---------- |\n")
|
// | Secure Connection | Display name | ConnectionID | Site URL | Invite accepted | Online | Last ping |
|
||||||
|
fmt.Fprintf(&sb, "| :---- | :---- | :---- | :---- | :---- | :---- | :---- | \n")
|
||||||
|
|
||||||
for _, rc := range list {
|
for _, rc := range list {
|
||||||
accepted := ":white_check_mark:"
|
accepted := formatBool(args.T, rc.SiteURL != "")
|
||||||
if rc.SiteURL == "" {
|
online := formatBool(args.T, isOnline(rc.LastPingAt))
|
||||||
accepted = ":x:"
|
lastPing := formatTimestamp(rc.LastPingAt)
|
||||||
}
|
|
||||||
|
|
||||||
online := ":white_check_mark:"
|
fmt.Fprintf(&sb, "| %s | %s | %s | %s | %s | %s | %s |\n", rc.Name, rc.DisplayName, rc.RemoteId, rc.SiteURL, accepted, online, lastPing)
|
||||||
if !isOnline(rc.LastPingAt) {
|
|
||||||
online = ":skull_and_crossbones:"
|
|
||||||
}
|
|
||||||
|
|
||||||
lastPing := formatTimestamp(model.GetTimeForMillis(rc.LastPingAt))
|
|
||||||
|
|
||||||
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())
|
return responsef(sb.String())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,8 +17,8 @@ type ShareProvider struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
CommandTriggerShare = "share"
|
CommandTriggerShare = "share-channel"
|
||||||
AvailableShareActions = "share_channel, unshare_channel, invite_remove, uninvite_remote, status"
|
AvailableShareActions = "invite, uninvite, unshare, status"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@@ -32,29 +32,20 @@ func (sp *ShareProvider) GetTrigger() string {
|
|||||||
func (sp *ShareProvider) GetCommand(a *app.App, T i18n.TranslateFunc) *model.Command {
|
func (sp *ShareProvider) GetCommand(a *app.App, T i18n.TranslateFunc) *model.Command {
|
||||||
share := model.NewAutocompleteData(CommandTriggerShare, "[action]", T("api.command_share.available_actions", map[string]interface{}{"Actions": AvailableShareActions}))
|
share := model.NewAutocompleteData(CommandTriggerShare, "[action]", T("api.command_share.available_actions", map[string]interface{}{"Actions": AvailableShareActions}))
|
||||||
|
|
||||||
shareChannel := model.NewAutocompleteData("share_channel", "", T("api.command_share.share_current"))
|
inviteRemote := model.NewAutocompleteData("invite", "", T("api.command_share.invite_remote.help"))
|
||||||
shareChannel.AddNamedTextArgument("readonly", T("api.command_share.share_read_only.help"), T("api.command_share.share_read_only.hint"), "Y|N|y|n", false)
|
inviteRemote.AddNamedDynamicListArgument("connectionID", T("api.command_share.remote_id.help"), "builtin:"+CommandTriggerShare, true)
|
||||||
shareChannel.AddNamedTextArgument("name", T("api.command_share.channel_name.help"), T("api.command_share.channel_name.hint"), "", false)
|
inviteRemote.AddNamedTextArgument("readonly", T("api.command_share.share_read_only.help"), T("api.command_share.share_read_only.hint"), "Y|N|y|n", false)
|
||||||
shareChannel.AddNamedTextArgument("displayname", T("api.command_share.channel_display_name.help"), T("api.command_share.channel_display_name.hint"), "", false)
|
|
||||||
shareChannel.AddNamedTextArgument("purpose", T("api.command_share.channel_purpose.help"), T("api.command_share.channel_purpose.hint"), "", false)
|
|
||||||
shareChannel.AddNamedTextArgument("header", T("api.command_share.channel_header.help"), T("api.command_share.channel_header.hint"), "", false)
|
|
||||||
|
|
||||||
unshareChannel := model.NewAutocompleteData("unshare_channel", "", T("api.command_share.unshare_channel.help"))
|
unInviteRemote := model.NewAutocompleteData("uninvite", "", T("api.command_share.uninvite_remote.help"))
|
||||||
unshareChannel.AddNamedTextArgument("are_you_sure", T("api.command_share.unshare_confirmation.help"), T("api.command_share.unshare_confirmation.hint"), "Y|N|y|n", true)
|
unInviteRemote.AddNamedDynamicListArgument("connectionID", T("api.command_share.uninvite_remote_id.help"), "builtin:"+CommandTriggerShare, true)
|
||||||
|
|
||||||
inviteRemote := model.NewAutocompleteData("invite_remote", "", T("api.command_share.invite_remote.help"))
|
unshareChannel := model.NewAutocompleteData("unshare", "", T("api.command_share.unshare_channel.help"))
|
||||||
inviteRemote.AddNamedDynamicListArgument("remoteId", T("api.command_share.remote_id.help"), "builtin:share", true)
|
|
||||||
inviteRemote.AddNamedTextArgument("description", T("api.command_share.description_invite.help"), T("api.command_share.description_invite.hint"), "", false)
|
|
||||||
|
|
||||||
unInviteRemote := model.NewAutocompleteData("uninvite_remote", "", T("api.command_share.uninvite_remote.help"))
|
|
||||||
unInviteRemote.AddNamedDynamicListArgument("remoteId", T("api.command_share.uninvite_remote_id.help"), "builtin:share", true)
|
|
||||||
|
|
||||||
status := model.NewAutocompleteData("status", "", T("api.command_share.channel_status.help"))
|
status := model.NewAutocompleteData("status", "", T("api.command_share.channel_status.help"))
|
||||||
|
|
||||||
share.AddCommand(shareChannel)
|
|
||||||
share.AddCommand(unshareChannel)
|
|
||||||
share.AddCommand(inviteRemote)
|
share.AddCommand(inviteRemote)
|
||||||
share.AddCommand(unInviteRemote)
|
share.AddCommand(unInviteRemote)
|
||||||
|
share.AddCommand(unshareChannel)
|
||||||
share.AddCommand(status)
|
share.AddCommand(status)
|
||||||
|
|
||||||
return &model.Command{
|
return &model.Command{
|
||||||
@@ -69,15 +60,15 @@ func (sp *ShareProvider) GetCommand(a *app.App, T i18n.TranslateFunc) *model.Com
|
|||||||
|
|
||||||
func (sp *ShareProvider) GetAutoCompleteListItems(a *app.App, commandArgs *model.CommandArgs, arg *model.AutocompleteArg, parsed, toBeParsed string) ([]model.AutocompleteListItem, error) {
|
func (sp *ShareProvider) GetAutoCompleteListItems(a *app.App, commandArgs *model.CommandArgs, arg *model.AutocompleteArg, parsed, toBeParsed string) ([]model.AutocompleteListItem, error) {
|
||||||
switch {
|
switch {
|
||||||
case strings.Contains(parsed, " share_channel "):
|
case strings.Contains(parsed, " share "):
|
||||||
|
|
||||||
return sp.getAutoCompleteShareChannel(a, commandArgs, arg)
|
return sp.getAutoCompleteShareChannel(a, commandArgs, arg)
|
||||||
|
|
||||||
case strings.Contains(parsed, " invite_remote "):
|
case strings.Contains(parsed, " invite "):
|
||||||
|
|
||||||
return sp.getAutoCompleteInviteRemote(a, commandArgs, arg)
|
return sp.getAutoCompleteInviteRemote(a, commandArgs, arg)
|
||||||
|
|
||||||
case strings.Contains(parsed, " uninvite_remote "):
|
case strings.Contains(parsed, " uninvite "):
|
||||||
|
|
||||||
return sp.getAutoCompleteUnInviteRemote(a, commandArgs, arg)
|
return sp.getAutoCompleteUnInviteRemote(a, commandArgs, arg)
|
||||||
|
|
||||||
@@ -112,7 +103,7 @@ func (sp *ShareProvider) getAutoCompleteShareChannel(a *app.App, commandArgs *mo
|
|||||||
|
|
||||||
func (sp *ShareProvider) getAutoCompleteInviteRemote(a *app.App, commandArgs *model.CommandArgs, arg *model.AutocompleteArg) ([]model.AutocompleteListItem, error) {
|
func (sp *ShareProvider) getAutoCompleteInviteRemote(a *app.App, commandArgs *model.CommandArgs, arg *model.AutocompleteArg) ([]model.AutocompleteListItem, error) {
|
||||||
switch arg.Name {
|
switch arg.Name {
|
||||||
case "remoteId":
|
case "connectionID":
|
||||||
return getRemoteClusterAutocompleteListItemsNotInChannel(a, commandArgs.ChannelId, true)
|
return getRemoteClusterAutocompleteListItemsNotInChannel(a, commandArgs.ChannelId, true)
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("%s not a dynamic argument", arg.Name)
|
return nil, fmt.Errorf("%s not a dynamic argument", arg.Name)
|
||||||
@@ -121,7 +112,7 @@ func (sp *ShareProvider) getAutoCompleteInviteRemote(a *app.App, commandArgs *mo
|
|||||||
|
|
||||||
func (sp *ShareProvider) getAutoCompleteUnInviteRemote(a *app.App, _ *model.CommandArgs, arg *model.AutocompleteArg) ([]model.AutocompleteListItem, error) {
|
func (sp *ShareProvider) getAutoCompleteUnInviteRemote(a *app.App, _ *model.CommandArgs, arg *model.AutocompleteArg) ([]model.AutocompleteListItem, error) {
|
||||||
switch arg.Name {
|
switch arg.Name {
|
||||||
case "remoteId":
|
case "connectionID":
|
||||||
return getRemoteClusterAutocompleteListItems(a, true)
|
return getRemoteClusterAutocompleteListItems(a, true)
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("%s not a dynamic argument", arg.Name)
|
return nil, fmt.Errorf("%s not a dynamic argument", arg.Name)
|
||||||
@@ -148,13 +139,13 @@ func (sp *ShareProvider) DoCommand(a *app.App, args *model.CommandArgs, message
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch action {
|
switch action {
|
||||||
case "share_channel":
|
case "share":
|
||||||
return sp.doShareChannel(a, args, margs)
|
return sp.doShareChannel(a, args, margs)
|
||||||
case "unshare_channel":
|
case "unshare":
|
||||||
return sp.doUnshareChannel(a, args, margs)
|
return sp.doUnshareChannel(a, args, margs)
|
||||||
case "invite_remote":
|
case "invite":
|
||||||
return sp.doInviteRemote(a, args, margs)
|
return sp.doInviteRemote(a, args, margs)
|
||||||
case "uninvite_remote":
|
case "uninvite":
|
||||||
return sp.doUninviteRemote(a, args, margs)
|
return sp.doUninviteRemote(a, args, margs)
|
||||||
case "status":
|
case "status":
|
||||||
return sp.doStatus(a, args, margs)
|
return sp.doStatus(a, args, margs)
|
||||||
@@ -212,15 +203,6 @@ func (sp *ShareProvider) doShareChannel(a *app.App, args *model.CommandArgs, mar
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (sp *ShareProvider) doUnshareChannel(a *app.App, args *model.CommandArgs, margs map[string]string) *model.CommandResponse {
|
func (sp *ShareProvider) doUnshareChannel(a *app.App, args *model.CommandArgs, margs map[string]string) *model.CommandResponse {
|
||||||
if _, ok := margs["are_you_sure"]; !ok {
|
|
||||||
margs["are_you_sure"] = "N"
|
|
||||||
}
|
|
||||||
|
|
||||||
sure, err := parseBool(margs["are_you_sure"])
|
|
||||||
if err != nil || !sure {
|
|
||||||
return responsef(args.T("api.command_share.shared_channel_not_deleted", map[string]interface{}{"Arg": "are_you_sure", "Expected": "Y"}))
|
|
||||||
}
|
|
||||||
|
|
||||||
sc, appErr := a.GetSharedChannel(args.ChannelId)
|
sc, appErr := a.GetSharedChannel(args.ChannelId)
|
||||||
if appErr != nil {
|
if appErr != nil {
|
||||||
return responsef(args.T("api.command_share.shared_channel_unshare.error", map[string]interface{}{"Error": appErr.Error()}))
|
return responsef(args.T("api.command_share.shared_channel_unshare.error", map[string]interface{}{"Error": appErr.Error()}))
|
||||||
@@ -240,7 +222,7 @@ func (sp *ShareProvider) doUnshareChannel(a *app.App, args *model.CommandArgs, m
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (sp *ShareProvider) doInviteRemote(a *app.App, args *model.CommandArgs, margs map[string]string) (resp *model.CommandResponse) {
|
func (sp *ShareProvider) doInviteRemote(a *app.App, args *model.CommandArgs, margs map[string]string) (resp *model.CommandResponse) {
|
||||||
remoteId, ok := margs["remoteId"]
|
remoteId, ok := margs["connectionID"]
|
||||||
if !ok || remoteId == "" {
|
if !ok || remoteId == "" {
|
||||||
return responsef(args.T("api.command_share.must_specify_valid_remote"))
|
return responsef(args.T("api.command_share.must_specify_valid_remote"))
|
||||||
}
|
}
|
||||||
@@ -284,7 +266,7 @@ func (sp *ShareProvider) doInviteRemote(a *app.App, args *model.CommandArgs, mar
|
|||||||
return responsef(args.T("api.command_share.channel_invite.error", map[string]interface{}{"Name": rc.DisplayName, "Error": errApp.Error()}))
|
return responsef(args.T("api.command_share.channel_invite.error", map[string]interface{}{"Name": rc.DisplayName, "Error": errApp.Error()}))
|
||||||
}
|
}
|
||||||
// send channel invite to remote cluster
|
// send channel invite to remote cluster
|
||||||
if err := a.Srv().GetSharedChannelSyncService().SendChannelInvite(channel, args.UserId, margs["description"], rc); err != nil {
|
if err := a.Srv().GetSharedChannelSyncService().SendChannelInvite(channel, args.UserId, rc); err != nil {
|
||||||
return responsef(args.T("api.command_share.channel_invite.error", map[string]interface{}{"Name": rc.DisplayName, "Error": err.Error()}))
|
return responsef(args.T("api.command_share.channel_invite.error", map[string]interface{}{"Name": rc.DisplayName, "Error": err.Error()}))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -292,7 +274,7 @@ func (sp *ShareProvider) doInviteRemote(a *app.App, args *model.CommandArgs, mar
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (sp *ShareProvider) doUninviteRemote(a *app.App, args *model.CommandArgs, margs map[string]string) *model.CommandResponse {
|
func (sp *ShareProvider) doUninviteRemote(a *app.App, args *model.CommandArgs, margs map[string]string) *model.CommandResponse {
|
||||||
remoteId, ok := margs["remoteId"]
|
remoteId, ok := margs["connectionID"]
|
||||||
if !ok || remoteId == "" {
|
if !ok || remoteId == "" {
|
||||||
return responsef(args.T("api.command_share.remote_not_valid"))
|
return responsef(args.T("api.command_share.remote_not_valid"))
|
||||||
}
|
}
|
||||||
@@ -323,19 +305,18 @@ func (sp *ShareProvider) doStatus(a *app.App, args *model.CommandArgs, _ map[str
|
|||||||
fmt.Fprintf(&sb, args.T("api.command_share.channel_status_id", map[string]interface{}{"ChannelId": statuses[0].ChannelId})+"\n\n")
|
fmt.Fprintf(&sb, args.T("api.command_share.channel_status_id", map[string]interface{}{"ChannelId": statuses[0].ChannelId})+"\n\n")
|
||||||
|
|
||||||
fmt.Fprintf(&sb, args.T("api.command_share.remote_table_header")+" \n")
|
fmt.Fprintf(&sb, args.T("api.command_share.remote_table_header")+" \n")
|
||||||
fmt.Fprintf(&sb, "| ------ | ------- | ----------- | -------- | -------------- | ------ | --------- | \n")
|
// "| Secure Connection | SiteURL | ReadOnly | InviteAccepted | Online | Last Sync |"
|
||||||
|
fmt.Fprintf(&sb, "| ---- | ---- | ---- | ---- | ---- | ---- | \n")
|
||||||
|
|
||||||
for _, status := range statuses {
|
for _, status := range statuses {
|
||||||
online := ":white_check_mark:"
|
readonly := formatBool(args.T, status.ReadOnly)
|
||||||
if !isOnline(status.LastPingAt) {
|
accepted := formatBool(args.T, status.IsInviteAccepted)
|
||||||
online = ":skull_and_crossbones:"
|
online := formatBool(args.T, isOnline(status.LastPingAt))
|
||||||
}
|
|
||||||
|
|
||||||
lastSync := formatTimestamp(model.GetTimeForMillis(status.NextSyncAt))
|
lastSync := formatTimestamp(status.NextSyncAt)
|
||||||
|
|
||||||
fmt.Fprintf(&sb, "| %s | %s | %s | %t | %t | %s | %s |\n",
|
fmt.Fprintf(&sb, "| %s | %s | %s | %s | %s | %s |\n",
|
||||||
status.DisplayName, status.SiteURL, status.Description,
|
status.DisplayName, status.SiteURL, readonly, accepted, online, lastSync)
|
||||||
status.ReadOnly, status.IsInviteAccepted, online, lastSync)
|
|
||||||
}
|
}
|
||||||
return responsef(sb.String())
|
return responsef(sb.String())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,12 +37,13 @@ func TestShareProviderDoCommand(t *testing.T) {
|
|||||||
|
|
||||||
commandProvider := ShareProvider{}
|
commandProvider := ShareProvider{}
|
||||||
channel := th.CreateChannel(th.BasicTeam, WithShared(false))
|
channel := th.CreateChannel(th.BasicTeam, WithShared(false))
|
||||||
|
|
||||||
args := &model.CommandArgs{
|
args := &model.CommandArgs{
|
||||||
T: func(s string, args ...interface{}) string { return s },
|
T: func(s string, args ...interface{}) string { return s },
|
||||||
ChannelId: channel.Id,
|
ChannelId: channel.Id,
|
||||||
UserId: th.BasicUser.Id,
|
UserId: th.BasicUser.Id,
|
||||||
TeamId: th.BasicTeam.Id,
|
TeamId: th.BasicTeam.Id,
|
||||||
Command: "/share share_channel",
|
Command: "/share-channel share",
|
||||||
}
|
}
|
||||||
|
|
||||||
response := commandProvider.DoCommand(th.App, args, "")
|
response := commandProvider.DoCommand(th.App, args, "")
|
||||||
@@ -77,7 +78,7 @@ func TestShareProviderDoCommand(t *testing.T) {
|
|||||||
ChannelId: channel.Id,
|
ChannelId: channel.Id,
|
||||||
UserId: th.BasicUser.Id,
|
UserId: th.BasicUser.Id,
|
||||||
TeamId: th.BasicTeam.Id,
|
TeamId: th.BasicTeam.Id,
|
||||||
Command: "/share unshare_channel --are_you_sure Y",
|
Command: "/share-channel unshare",
|
||||||
}
|
}
|
||||||
|
|
||||||
response := commandProvider.DoCommand(th.App, args, "")
|
response := commandProvider.DoCommand(th.App, args, "")
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/mattermost/mattermost-server/v5/model"
|
"github.com/mattermost/mattermost-server/v5/model"
|
||||||
|
"github.com/mattermost/mattermost-server/v5/shared/i18n"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -72,12 +73,25 @@ func parseBool(s string) (bool, error) {
|
|||||||
return false, fmt.Errorf("cannot parse '%s' as a boolean", s)
|
return false, fmt.Errorf("cannot parse '%s' as a boolean", s)
|
||||||
}
|
}
|
||||||
|
|
||||||
func formatTimestamp(ts time.Time) string {
|
func formatBool(fn i18n.TranslateFunc, b bool) string {
|
||||||
|
if b {
|
||||||
|
return fn("True")
|
||||||
|
}
|
||||||
|
return fn("False")
|
||||||
|
}
|
||||||
|
|
||||||
|
func formatTimestamp(timestamp int64) string {
|
||||||
|
if timestamp == 0 {
|
||||||
|
return "--"
|
||||||
|
}
|
||||||
|
|
||||||
|
ts := model.GetTimeForMillis(timestamp)
|
||||||
|
|
||||||
if !isToday(ts) {
|
if !isToday(ts) {
|
||||||
return ts.Format("Jan 2 15:04:05 MST 2006")
|
return ts.Format("Jan 2 15:04:05 MST 2006")
|
||||||
}
|
}
|
||||||
date := ts.Format("15:04:05 MST 2006")
|
date := ts.Format("15:04:05 MST 2006")
|
||||||
return fmt.Sprintf("today %s", date)
|
return fmt.Sprintf("Today %s", date)
|
||||||
}
|
}
|
||||||
|
|
||||||
func isToday(ts time.Time) bool {
|
func isToday(ts time.Time) bool {
|
||||||
|
|||||||
146
i18n/en.json
146
i18n/en.json
@@ -1104,11 +1104,11 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api.command_remote.add_remote.error",
|
"id": "api.command_remote.add_remote.error",
|
||||||
"translation": "Could not add remote cluster: {{.Error}}"
|
"translation": "Could not add secure connection: {{.Error}}"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api.command_remote.cluster_removed",
|
"id": "api.command_remote.cluster_removed",
|
||||||
"translation": "Remote cluster {{.RemoteId}} {{.Result}}."
|
"translation": "Secure connection {{.RemoteId}} {{.Result}}."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api.command_remote.decode_invitation.error",
|
"id": "api.command_remote.decode_invitation.error",
|
||||||
@@ -1120,11 +1120,11 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api.command_remote.displayname.help",
|
"id": "api.command_remote.displayname.help",
|
||||||
"translation": "Remote cluster display name"
|
"translation": "Secure connection display name"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api.command_remote.displayname.hint",
|
"id": "api.command_remote.displayname.hint",
|
||||||
"translation": "A display name for the remote cluster"
|
"translation": "A display name for the secure connection"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api.command_remote.encrypt_invitation.error",
|
"id": "api.command_remote.encrypt_invitation.error",
|
||||||
@@ -1132,7 +1132,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api.command_remote.fetch_status.error",
|
"id": "api.command_remote.fetch_status.error",
|
||||||
"translation": "Could not fetch remote clusters: {{.Error}}"
|
"translation": "Could not fetch secure connections: {{.Error}}"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api.command_remote.hint",
|
"id": "api.command_remote.hint",
|
||||||
@@ -1144,11 +1144,11 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api.command_remote.invitation.help",
|
"id": "api.command_remote.invitation.help",
|
||||||
"translation": "Invitation from remote cluster"
|
"translation": "Invitation from secure connection"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api.command_remote.invitation.hint",
|
"id": "api.command_remote.invitation.hint",
|
||||||
"translation": "The encrypted invitation from a remote cluster"
|
"translation": "The encrypted invitation from a secure connection"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api.command_remote.invitation_created",
|
"id": "api.command_remote.invitation_created",
|
||||||
@@ -1156,7 +1156,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api.command_remote.invite.help",
|
"id": "api.command_remote.invite.help",
|
||||||
"translation": "Invite a remote cluster"
|
"translation": "Create a secure connection"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api.command_remote.invite_password.help",
|
"id": "api.command_remote.invite_password.help",
|
||||||
@@ -1180,43 +1180,43 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api.command_remote.name",
|
"id": "api.command_remote.name",
|
||||||
"translation": "remote"
|
"translation": "secure-connection"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api.command_remote.name.help",
|
"id": "api.command_remote.name.help",
|
||||||
"translation": "Remote cluster name"
|
"translation": "Secure connection name"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api.command_remote.name.hint",
|
"id": "api.command_remote.name.hint",
|
||||||
"translation": "A unique name for the remote cluster"
|
"translation": "A unique name for the secure connection"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api.command_remote.permission_required",
|
"id": "api.command_remote.permission_required",
|
||||||
"translation": "You require `{{.Permission}}` permission to manage remote clusters."
|
"translation": "You require `{{.Permission}}` permission to manage secure connections."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api.command_remote.remote_add_remove.help",
|
"id": "api.command_remote.remote_add_remove.help",
|
||||||
"translation": "Add/remove remote clusters. Available actions: {{.Actions}}"
|
"translation": "Add/remove secure connections. Available actions: {{.Actions}}"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api.command_remote.remote_table_header",
|
"id": "api.command_remote.remote_table_header",
|
||||||
"translation": "| Name | SiteURL | RemoteId | Invite Accepted | Online | Last Ping |"
|
"translation": "| Secure Connection | Display name | ConnectionID | Site URL | Invite accepted | Online | Last ping |"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api.command_remote.remotes_not_found",
|
"id": "api.command_remote.remotes_not_found",
|
||||||
"translation": "No remote clusters found."
|
"translation": "No secure connections found."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api.command_remote.remove.help",
|
"id": "api.command_remote.remove.help",
|
||||||
"translation": "Removes a remote cluster"
|
"translation": "Removes a secure connection"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api.command_remote.remove_remote.error",
|
"id": "api.command_remote.remove_remote.error",
|
||||||
"translation": "Could not remove remote cluster: {{.Error}}"
|
"translation": "Could not remove secure connection: {{.Error}}"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api.command_remote.remove_remote_id.help",
|
"id": "api.command_remote.remove_remote_id.help",
|
||||||
"translation": "Id of remote cluster remove"
|
"translation": "Id of secure connection remove"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api.command_remote.service_disabled",
|
"id": "api.command_remote.service_disabled",
|
||||||
@@ -1232,7 +1232,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api.command_remote.status.help",
|
"id": "api.command_remote.status.help",
|
||||||
"translation": "Displays status for all remote clusters"
|
"translation": "Displays status for all secure connections"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api.command_remote.unknown_action",
|
"id": "api.command_remote.unknown_action",
|
||||||
@@ -1306,49 +1306,17 @@
|
|||||||
"id": "api.command_share.available_actions",
|
"id": "api.command_share.available_actions",
|
||||||
"translation": "Available actions: {{.Actions}}"
|
"translation": "Available actions: {{.Actions}}"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"id": "api.command_share.channel_display_name.help",
|
|
||||||
"translation": "Channel display name provided to remote instances"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "api.command_share.channel_display_name.hint",
|
|
||||||
"translation": "[displayname] - defaults to channel displayname"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "api.command_share.channel_header.help",
|
|
||||||
"translation": "Channel header provided to remote instances"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "api.command_share.channel_header.hint",
|
|
||||||
"translation": "[header] - defaults to channels header"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"id": "api.command_share.channel_invite.error",
|
"id": "api.command_share.channel_invite.error",
|
||||||
"translation": "Error inviting `{{.Name}}` to this channel: {{.Error}}"
|
"translation": "Error inviting `{{.Name}}` to this channel: {{.Error}}"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api.command_share.channel_invite_not_home.error",
|
"id": "api.command_share.channel_invite_not_home.error",
|
||||||
"translation": "Cannot invite remote cluster to a shared channel originating somewhere else."
|
"translation": "Cannot invite secure connection to a shared channel originating somewhere else."
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "api.command_share.channel_name.help",
|
|
||||||
"translation": "Channel name provided to remote instances"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "api.command_share.channel_name.hint",
|
|
||||||
"translation": "[name] - defaults to channel name"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "api.command_share.channel_purpose.help",
|
|
||||||
"translation": "Channel purpose provided to remote instances"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "api.command_share.channel_purpose.hint",
|
|
||||||
"translation": "[purpose] - defaults to channel purpose"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api.command_share.channel_remote_id_not_exists",
|
"id": "api.command_share.channel_remote_id_not_exists",
|
||||||
"translation": "Shared channel remote id `{{.RemoteId}}` does not exist for this channel."
|
"translation": "Shared channel secure connection `{{.RemoteId}}` does not exist for this channel."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api.command_share.channel_shared",
|
"id": "api.command_share.channel_shared",
|
||||||
@@ -1374,21 +1342,13 @@
|
|||||||
"id": "api.command_share.desc",
|
"id": "api.command_share.desc",
|
||||||
"translation": "Shares the current channel with a remote Mattermost instance."
|
"translation": "Shares the current channel with a remote Mattermost instance."
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"id": "api.command_share.description_invite.help",
|
|
||||||
"translation": "Description for invite"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "api.command_share.description_invite.hint",
|
|
||||||
"translation": "[description] - optional"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"id": "api.command_share.fetch_remote.error",
|
"id": "api.command_share.fetch_remote.error",
|
||||||
"translation": "Error fetching remote clusters: {{.Error}}"
|
"translation": "Error fetching shared connections: {{.Error}}"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api.command_share.fetch_remote_status.error",
|
"id": "api.command_share.fetch_remote_status.error",
|
||||||
"translation": "Could not fetch status for remotes: {{.Error}}."
|
"translation": "Could not fetch status for secure connections: {{.Error}}."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api.command_share.hint",
|
"id": "api.command_share.hint",
|
||||||
@@ -1412,15 +1372,15 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api.command_share.must_specify_valid_remote",
|
"id": "api.command_share.must_specify_valid_remote",
|
||||||
"translation": "Must specify a valid remote cluster id to invite."
|
"translation": "Must specify a valid secure connection id to invite."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api.command_share.name",
|
"id": "api.command_share.name",
|
||||||
"translation": "share"
|
"translation": "share-channel"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api.command_share.no_remote_invited",
|
"id": "api.command_share.no_remote_invited",
|
||||||
"translation": "No remotes have been invited to this shared channel."
|
"translation": "No secure connections have been invited to this shared channel."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api.command_share.not_shared_channel_unshare",
|
"id": "api.command_share.not_shared_channel_unshare",
|
||||||
@@ -1432,27 +1392,27 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api.command_share.remote_already_invited",
|
"id": "api.command_share.remote_already_invited",
|
||||||
"translation": "The remote cluster has already been invited."
|
"translation": "The secure connection has already been invited."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api.command_share.remote_id.help",
|
"id": "api.command_share.remote_id.help",
|
||||||
"translation": "Id of an existing remote instance. See `remote` command to add a remote instance."
|
"translation": "Id of an existing secure connection. See `secure-connection` command to add a secure connection."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api.command_share.remote_id_invalid.error",
|
"id": "api.command_share.remote_id_invalid.error",
|
||||||
"translation": "Remote cluster id is invalid: {{.Error}}"
|
"translation": "Secure connection id is invalid: {{.Error}}"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api.command_share.remote_not_valid",
|
"id": "api.command_share.remote_not_valid",
|
||||||
"translation": "Must specify a valid remote cluster to uninvite"
|
"translation": "Must specify a valid secure connection id to uninvite"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api.command_share.remote_table_header",
|
"id": "api.command_share.remote_table_header",
|
||||||
"translation": "| Remote | SiteURL | Description | ReadOnly | InviteAccepted | Online | Last Sync |"
|
"translation": "| Secure Connection | SiteURL | ReadOnly | InviteAccepted | Online | Last Sync |"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api.command_share.remote_uninvited",
|
"id": "api.command_share.remote_uninvited",
|
||||||
"translation": "Remote `{{.RemoteId}}` uninvited."
|
"translation": "Secure connection `{{.RemoteId}}` uninvited."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api.command_share.service_disabled",
|
"id": "api.command_share.service_disabled",
|
||||||
@@ -1462,10 +1422,6 @@
|
|||||||
"id": "api.command_share.share_channel.error",
|
"id": "api.command_share.share_channel.error",
|
||||||
"translation": "Cannot share this channel: {{.Error}}"
|
"translation": "Cannot share this channel: {{.Error}}"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"id": "api.command_share.share_current",
|
|
||||||
"translation": "Share the current channel"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"id": "api.command_share.share_read_only.help",
|
"id": "api.command_share.share_read_only.help",
|
||||||
"translation": "Channel will be shared in read-only mode"
|
"translation": "Channel will be shared in read-only mode"
|
||||||
@@ -1474,10 +1430,6 @@
|
|||||||
"id": "api.command_share.share_read_only.hint",
|
"id": "api.command_share.share_read_only.hint",
|
||||||
"translation": "[readonly] - 'Y' or 'N'. Defaults to 'N'"
|
"translation": "[readonly] - 'Y' or 'N'. Defaults to 'N'"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"id": "api.command_share.shared_channel_not_deleted",
|
|
||||||
"translation": "Shared channel was not deleted: `{{.Arg}}` must be `{{.Expected}}`."
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"id": "api.command_share.shared_channel_unavailable",
|
"id": "api.command_share.shared_channel_unavailable",
|
||||||
"translation": "This channel is no longer shared."
|
"translation": "This channel is no longer shared."
|
||||||
@@ -1488,11 +1440,11 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api.command_share.uninvite_remote.help",
|
"id": "api.command_share.uninvite_remote.help",
|
||||||
"translation": "Uninvites a remote instance from this shared channel"
|
"translation": "Uninvites a secure connection from this shared channel"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api.command_share.uninvite_remote_id.help",
|
"id": "api.command_share.uninvite_remote_id.help",
|
||||||
"translation": "Id of remote instance to uninvite."
|
"translation": "Id of secure connection to uninvite."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api.command_share.unknown_action",
|
"id": "api.command_share.unknown_action",
|
||||||
@@ -1502,14 +1454,6 @@
|
|||||||
"id": "api.command_share.unshare_channel.help",
|
"id": "api.command_share.unshare_channel.help",
|
||||||
"translation": "Unshares the current channel"
|
"translation": "Unshares the current channel"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"id": "api.command_share.unshare_confirmation.help",
|
|
||||||
"translation": "Are you sure? This channel will be unshared and all remote instances will be uninvited"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "api.command_share.unshare_confirmation.hint",
|
|
||||||
"translation": "'Y' or 'N'"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"id": "api.command_shortcuts.desc",
|
"id": "api.command_shortcuts.desc",
|
||||||
"translation": "Displays a list of keyboard shortcuts"
|
"translation": "Displays a list of keyboard shortcuts"
|
||||||
@@ -1608,15 +1552,15 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api.context.remote_id_invalid.app_error",
|
"id": "api.context.remote_id_invalid.app_error",
|
||||||
"translation": "Unable to find remote cluster id {{.RemoteId}}."
|
"translation": "Unable to find secure connectionID {{.RemoteId}}."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api.context.remote_id_mismatch.app_error",
|
"id": "api.context.remote_id_mismatch.app_error",
|
||||||
"translation": "Remote cluster id mismatch."
|
"translation": "Secure connection ID mismatch."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api.context.remote_id_missing.app_error",
|
"id": "api.context.remote_id_missing.app_error",
|
||||||
"translation": "Remote cluster id missing."
|
"translation": "Secure connection ID missing."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api.context.server_busy.app_error",
|
"id": "api.context.server_busy.app_error",
|
||||||
@@ -2432,11 +2376,11 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api.remote_cluster.delete.app_error",
|
"id": "api.remote_cluster.delete.app_error",
|
||||||
"translation": "We encountered an error deleting the remote cluster."
|
"translation": "We encountered an error deleting the secure connection."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api.remote_cluster.get.app_error",
|
"id": "api.remote_cluster.get.app_error",
|
||||||
"translation": "We encountered an error retrieving a remote cluster."
|
"translation": "We encountered an error retrieving a secure connection."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api.remote_cluster.invalid_id.app_error",
|
"id": "api.remote_cluster.invalid_id.app_error",
|
||||||
@@ -2448,11 +2392,11 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api.remote_cluster.save.app_error",
|
"id": "api.remote_cluster.save.app_error",
|
||||||
"translation": "We encountered an error saving the remote cluster."
|
"translation": "We encountered an error saving the secure connection."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api.remote_cluster.save_not_unique.app_error",
|
"id": "api.remote_cluster.save_not_unique.app_error",
|
||||||
"translation": "Remote cluster has already been added."
|
"translation": "Secure connection has already been added."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api.remote_cluster.service_not_enabled.app_error",
|
"id": "api.remote_cluster.service_not_enabled.app_error",
|
||||||
@@ -2460,11 +2404,11 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api.remote_cluster.update.app_error",
|
"id": "api.remote_cluster.update.app_error",
|
||||||
"translation": "We encountered an error updating the remote cluster."
|
"translation": "We encountered an error updating the secure connection."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api.remote_cluster.update_not_unique.app_error",
|
"id": "api.remote_cluster.update_not_unique.app_error",
|
||||||
"translation": "Remote cluster with the same url already exists."
|
"translation": "Secure connection with the same url already exists."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api.restricted_system_admin",
|
"id": "api.restricted_system_admin",
|
||||||
@@ -7734,10 +7678,6 @@
|
|||||||
"id": "model.channel.is_valid.creator_id.app_error",
|
"id": "model.channel.is_valid.creator_id.app_error",
|
||||||
"translation": "Invalid creator id."
|
"translation": "Invalid creator id."
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"id": "model.channel.is_valid.description.app_error",
|
|
||||||
"translation": "Invalid description."
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"id": "model.channel.is_valid.display_name.app_error",
|
"id": "model.channel.is_valid.display_name.app_error",
|
||||||
"translation": "Invalid display name."
|
"translation": "Invalid display name."
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ const (
|
|||||||
MIGRATION_KEY_ADD_SYSTEM_ROLES_PERMISSIONS = "add_system_roles_permissions"
|
MIGRATION_KEY_ADD_SYSTEM_ROLES_PERMISSIONS = "add_system_roles_permissions"
|
||||||
MIGRATION_KEY_ADD_BILLING_PERMISSIONS = "add_billing_permissions"
|
MIGRATION_KEY_ADD_BILLING_PERMISSIONS = "add_billing_permissions"
|
||||||
MIGRATION_KEY_ADD_MANAGE_SHARED_CHANNEL_PERMISSIONS = "manage_shared_channel_permissions"
|
MIGRATION_KEY_ADD_MANAGE_SHARED_CHANNEL_PERMISSIONS = "manage_shared_channel_permissions"
|
||||||
MIGRATION_KEY_ADD_MANAGE_REMOTE_CLUSTERS_PERMISSIONS = "manage_remote_clusters_permissions"
|
MIGRATION_KEY_ADD_MANAGE_SECURE_CONNECTIONS_PERMISSIONS = "manage_secure_connections_permissions"
|
||||||
MIGRATION_KEY_ADD_DOWNLOAD_COMPLIANCE_EXPORT_RESULTS = "download_compliance_export_results"
|
MIGRATION_KEY_ADD_DOWNLOAD_COMPLIANCE_EXPORT_RESULTS = "download_compliance_export_results"
|
||||||
MIGRATION_KEY_ADD_COMPLIANCE_SUBSECTION_PERMISSIONS = "compliance_subsection_permissions"
|
MIGRATION_KEY_ADD_COMPLIANCE_SUBSECTION_PERMISSIONS = "compliance_subsection_permissions"
|
||||||
MIGRATION_KEY_ADD_EXPERIMENTAL_SUBSECTION_PERMISSIONS = "experimental_subsection_permissions"
|
MIGRATION_KEY_ADD_EXPERIMENTAL_SUBSECTION_PERMISSIONS = "experimental_subsection_permissions"
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ var PERMISSION_USE_GROUP_MENTIONS *Permission
|
|||||||
var PERMISSION_READ_OTHER_USERS_TEAMS *Permission
|
var PERMISSION_READ_OTHER_USERS_TEAMS *Permission
|
||||||
var PERMISSION_EDIT_BRAND *Permission
|
var PERMISSION_EDIT_BRAND *Permission
|
||||||
var PERMISSION_MANAGE_SHARED_CHANNELS *Permission
|
var PERMISSION_MANAGE_SHARED_CHANNELS *Permission
|
||||||
var PERMISSION_MANAGE_REMOTE_CLUSTERS *Permission
|
var PERMISSION_MANAGE_SECURE_CONNECTIONS *Permission
|
||||||
var PERMISSION_DOWNLOAD_COMPLIANCE_EXPORT_RESULT *Permission
|
var PERMISSION_DOWNLOAD_COMPLIANCE_EXPORT_RESULT *Permission
|
||||||
var PERMISSION_CREATE_DATA_RETENTION_JOB *Permission
|
var PERMISSION_CREATE_DATA_RETENTION_JOB *Permission
|
||||||
var PERMISSION_READ_DATA_RETENTION_JOB *Permission
|
var PERMISSION_READ_DATA_RETENTION_JOB *Permission
|
||||||
@@ -711,10 +711,10 @@ func initializePermissions() {
|
|||||||
"authentication.permissions.manage_shared_channels.description",
|
"authentication.permissions.manage_shared_channels.description",
|
||||||
PermissionScopeSystem,
|
PermissionScopeSystem,
|
||||||
}
|
}
|
||||||
PERMISSION_MANAGE_REMOTE_CLUSTERS = &Permission{
|
PERMISSION_MANAGE_SECURE_CONNECTIONS = &Permission{
|
||||||
"manage_remote_clusters",
|
"manage_secure_connections",
|
||||||
"authentication.permissions.manage_remote_clusters.name",
|
"authentication.permissions.manage_secure_connections.name",
|
||||||
"authentication.permissions.manage_remote_clusters.description",
|
"authentication.permissions.manage_secure_connections.description",
|
||||||
PermissionScopeSystem,
|
PermissionScopeSystem,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2041,7 +2041,7 @@ func initializePermissions() {
|
|||||||
PERMISSION_DEMOTE_TO_GUEST,
|
PERMISSION_DEMOTE_TO_GUEST,
|
||||||
PERMISSION_EDIT_BRAND,
|
PERMISSION_EDIT_BRAND,
|
||||||
PERMISSION_MANAGE_SHARED_CHANNELS,
|
PERMISSION_MANAGE_SHARED_CHANNELS,
|
||||||
PERMISSION_MANAGE_REMOTE_CLUSTERS,
|
PERMISSION_MANAGE_SECURE_CONNECTIONS,
|
||||||
PERMISSION_DOWNLOAD_COMPLIANCE_EXPORT_RESULT,
|
PERMISSION_DOWNLOAD_COMPLIANCE_EXPORT_RESULT,
|
||||||
PERMISSION_CREATE_DATA_RETENTION_JOB,
|
PERMISSION_CREATE_DATA_RETENTION_JOB,
|
||||||
PERMISSION_READ_DATA_RETENTION_JOB,
|
PERMISSION_READ_DATA_RETENTION_JOB,
|
||||||
|
|||||||
@@ -106,7 +106,6 @@ func (sc *SharedChannel) PreUpdate() {
|
|||||||
type SharedChannelRemote struct {
|
type SharedChannelRemote struct {
|
||||||
Id string `json:"id"`
|
Id string `json:"id"`
|
||||||
ChannelId string `json:"channel_id"`
|
ChannelId string `json:"channel_id"`
|
||||||
Description string `json:"description"`
|
|
||||||
CreatorId string `json:"creator_id"`
|
CreatorId string `json:"creator_id"`
|
||||||
CreateAt int64 `json:"create_at"`
|
CreateAt int64 `json:"create_at"`
|
||||||
UpdateAt int64 `json:"update_at"`
|
UpdateAt int64 `json:"update_at"`
|
||||||
@@ -136,10 +135,6 @@ func (sc *SharedChannelRemote) IsValid() *AppError {
|
|||||||
return NewAppError("SharedChannelRemote.IsValid", "model.channel.is_valid.id.app_error", nil, "ChannelId="+sc.ChannelId, http.StatusBadRequest)
|
return NewAppError("SharedChannelRemote.IsValid", "model.channel.is_valid.id.app_error", nil, "ChannelId="+sc.ChannelId, http.StatusBadRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(sc.Description) > 64 {
|
|
||||||
return NewAppError("SharedChannelRemote.IsValid", "model.channel.is_valid.description.app_error", nil, "description="+sc.Description, http.StatusBadRequest)
|
|
||||||
}
|
|
||||||
|
|
||||||
if sc.CreateAt == 0 {
|
if sc.CreateAt == 0 {
|
||||||
return NewAppError("SharedChannelRemote.IsValid", "model.channel.is_valid.create_at.app_error", nil, "id="+sc.ChannelId, http.StatusBadRequest)
|
return NewAppError("SharedChannelRemote.IsValid", "model.channel.is_valid.create_at.app_error", nil, "id="+sc.ChannelId, http.StatusBadRequest)
|
||||||
}
|
}
|
||||||
@@ -172,7 +167,6 @@ type SharedChannelRemoteStatus struct {
|
|||||||
SiteURL string `json:"site_url"`
|
SiteURL string `json:"site_url"`
|
||||||
LastPingAt int64 `json:"last_ping_at"`
|
LastPingAt int64 `json:"last_ping_at"`
|
||||||
NextSyncAt int64 `json:"next_sync_at"`
|
NextSyncAt int64 `json:"next_sync_at"`
|
||||||
Description string `json:"description"`
|
|
||||||
ReadOnly bool `json:"readonly"`
|
ReadOnly bool `json:"readonly"`
|
||||||
IsInviteAccepted bool `json:"is_invite_accepted"`
|
IsInviteAccepted bool `json:"is_invite_accepted"`
|
||||||
Token string `json:"token"`
|
Token string `json:"token"`
|
||||||
|
|||||||
@@ -76,12 +76,11 @@ func TestSharedChannelPreUpdate(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSharedChannelRemoteJson(t *testing.T) {
|
func TestSharedChannelRemoteJson(t *testing.T) {
|
||||||
o := SharedChannelRemote{Id: NewId(), ChannelId: NewId(), Description: "Test"}
|
o := SharedChannelRemote{Id: NewId(), ChannelId: NewId()}
|
||||||
json := o.ToJson()
|
json := o.ToJson()
|
||||||
ro, err := SharedChannelRemoteFromJson(strings.NewReader(json))
|
ro, err := SharedChannelRemoteFromJson(strings.NewReader(json))
|
||||||
|
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, o.Id, ro.Id)
|
require.Equal(t, o.Id, ro.Id)
|
||||||
require.Equal(t, o.ChannelId, ro.ChannelId)
|
require.Equal(t, o.ChannelId, ro.ChannelId)
|
||||||
require.Equal(t, o.Description, ro.Description)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ type TopicListener func(msg model.RemoteClusterMsg, rc *model.RemoteCluster, res
|
|||||||
// ConnectionStateListener is used to listen to remote cluster connection state changes.
|
// ConnectionStateListener is used to listen to remote cluster connection state changes.
|
||||||
type ConnectionStateListener func(rc *model.RemoteCluster, online bool)
|
type ConnectionStateListener func(rc *model.RemoteCluster, online bool)
|
||||||
|
|
||||||
// Service provides inter-cluster communication via topic based messages.
|
// Service provides inter-cluster communication via topic based messages. In product these are called "Secured Connections".
|
||||||
type Service struct {
|
type Service struct {
|
||||||
server ServerIface
|
server ServerIface
|
||||||
httpClient *http.Client
|
httpClient *http.Client
|
||||||
@@ -90,7 +90,7 @@ type Service struct {
|
|||||||
done chan struct{}
|
done chan struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewRemoteClusterService creates a RemoteClusterService instance.
|
// NewRemoteClusterService creates a RemoteClusterService instance. In product this is called a "Secured Connection".
|
||||||
func NewRemoteClusterService(server ServerIface) (*Service, error) {
|
func NewRemoteClusterService(server ServerIface) (*Service, error) {
|
||||||
transport := &http.Transport{
|
transport := &http.Transport{
|
||||||
Proxy: http.ProxyFromEnvironment,
|
Proxy: http.ProxyFromEnvironment,
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ func WithDirectParticipantID(participantID string) InviteOption {
|
|||||||
// SendChannelInvite asynchronously sends a channel invite to a remote cluster. The remote cluster is
|
// SendChannelInvite asynchronously sends a channel invite to a remote cluster. The remote cluster is
|
||||||
// expected to create a new channel with the same channel id, and respond with status OK.
|
// expected to create a new channel with the same channel id, and respond with status OK.
|
||||||
// If an error occurs on the remote cluster then an ephemeral message is posted to in the channel for userId.
|
// If an error occurs on the remote cluster then an ephemeral message is posted to in the channel for userId.
|
||||||
func (scs *Service) SendChannelInvite(channel *model.Channel, userId string, description string, rc *model.RemoteCluster, options ...InviteOption) error {
|
func (scs *Service) SendChannelInvite(channel *model.Channel, userId string, rc *model.RemoteCluster, options ...InviteOption) error {
|
||||||
rcs := scs.server.GetRemoteClusterService()
|
rcs := scs.server.GetRemoteClusterService()
|
||||||
if rcs == nil {
|
if rcs == nil {
|
||||||
return fmt.Errorf("cannot invite remote cluster for channel id %s; Remote Cluster Service not enabled", channel.Id)
|
return fmt.Errorf("cannot invite remote cluster for channel id %s; Remote Cluster Service not enabled", channel.Id)
|
||||||
@@ -82,7 +82,6 @@ func (scs *Service) SendChannelInvite(channel *model.Channel, userId string, des
|
|||||||
|
|
||||||
scr := &model.SharedChannelRemote{
|
scr := &model.SharedChannelRemote{
|
||||||
ChannelId: sc.ChannelId,
|
ChannelId: sc.ChannelId,
|
||||||
Description: description,
|
|
||||||
CreatorId: userId,
|
CreatorId: userId,
|
||||||
RemoteId: rc.RemoteId,
|
RemoteId: rc.RemoteId,
|
||||||
IsInviteAccepted: true,
|
IsInviteAccepted: true,
|
||||||
@@ -165,7 +164,6 @@ func (scs *Service) onReceiveChannelInvite(msg model.RemoteClusterMsg, rc *model
|
|||||||
sharedChannelRemote := &model.SharedChannelRemote{
|
sharedChannelRemote := &model.SharedChannelRemote{
|
||||||
Id: model.NewId(),
|
Id: model.NewId(),
|
||||||
ChannelId: channel.Id,
|
ChannelId: channel.Id,
|
||||||
Description: invite.DisplayName,
|
|
||||||
CreatorId: channel.CreatorId,
|
CreatorId: channel.CreatorId,
|
||||||
IsInviteAccepted: true,
|
IsInviteAccepted: true,
|
||||||
IsInviteConfirmed: true,
|
IsInviteConfirmed: true,
|
||||||
|
|||||||
@@ -38,7 +38,6 @@ func newSqlSharedChannelStore(sqlStore *SqlStore) store.SharedChannelStore {
|
|||||||
tableSharedChannelRemotes := db.AddTableWithName(model.SharedChannelRemote{}, "SharedChannelRemotes").SetKeys(false, "Id", "ChannelId")
|
tableSharedChannelRemotes := db.AddTableWithName(model.SharedChannelRemote{}, "SharedChannelRemotes").SetKeys(false, "Id", "ChannelId")
|
||||||
tableSharedChannelRemotes.ColMap("Id").SetMaxSize(26)
|
tableSharedChannelRemotes.ColMap("Id").SetMaxSize(26)
|
||||||
tableSharedChannelRemotes.ColMap("ChannelId").SetMaxSize(26)
|
tableSharedChannelRemotes.ColMap("ChannelId").SetMaxSize(26)
|
||||||
tableSharedChannelRemotes.ColMap("Description").SetMaxSize(64)
|
|
||||||
tableSharedChannelRemotes.ColMap("CreatorId").SetMaxSize(26)
|
tableSharedChannelRemotes.ColMap("CreatorId").SetMaxSize(26)
|
||||||
tableSharedChannelRemotes.ColMap("RemoteId").SetMaxSize(26)
|
tableSharedChannelRemotes.ColMap("RemoteId").SetMaxSize(26)
|
||||||
tableSharedChannelRemotes.SetUniqueTogether("ChannelId", "RemoteId")
|
tableSharedChannelRemotes.SetUniqueTogether("ChannelId", "RemoteId")
|
||||||
@@ -524,7 +523,7 @@ func (s SqlSharedChannelStore) GetRemotesStatus(channelId string) ([]*model.Shar
|
|||||||
var status []*model.SharedChannelRemoteStatus
|
var status []*model.SharedChannelRemoteStatus
|
||||||
|
|
||||||
query := s.getQueryBuilder().
|
query := s.getQueryBuilder().
|
||||||
Select("scr.ChannelId, rc.DisplayName, rc.SiteURL, rc.LastPingAt, scr.NextSyncAt, scr.Description, sc.ReadOnly, scr.IsInviteAccepted").
|
Select("scr.ChannelId, rc.DisplayName, rc.SiteURL, rc.LastPingAt, scr.NextSyncAt, sc.ReadOnly, scr.IsInviteAccepted").
|
||||||
From("SharedChannelRemotes scr, RemoteClusters rc, SharedChannels sc").
|
From("SharedChannelRemotes scr, RemoteClusters rc, SharedChannels sc").
|
||||||
Where("scr.RemoteId = rc.RemoteId").
|
Where("scr.RemoteId = rc.RemoteId").
|
||||||
Where("scr.ChannelId = sc.ChannelId").
|
Where("scr.ChannelId = sc.ChannelId").
|
||||||
|
|||||||
@@ -253,11 +253,11 @@ func testRemoteClusterGetAllInChannel(t *testing.T, ss store.Store) {
|
|||||||
|
|
||||||
// Create some shared channel remotes
|
// Create some shared channel remotes
|
||||||
scrData := []*model.SharedChannelRemote{
|
scrData := []*model.SharedChannelRemote{
|
||||||
{ChannelId: channel1.Id, Description: "AAA Inc Share", RemoteId: rcData[0].RemoteId, CreatorId: model.NewId()},
|
{ChannelId: channel1.Id, RemoteId: rcData[0].RemoteId, CreatorId: model.NewId()},
|
||||||
{ChannelId: channel1.Id, Description: "BBB Inc Share", RemoteId: rcData[1].RemoteId, CreatorId: model.NewId()},
|
{ChannelId: channel1.Id, RemoteId: rcData[1].RemoteId, CreatorId: model.NewId()},
|
||||||
{ChannelId: channel2.Id, Description: "CCC Inc Share", RemoteId: rcData[2].RemoteId, CreatorId: model.NewId()},
|
{ChannelId: channel2.Id, RemoteId: rcData[2].RemoteId, CreatorId: model.NewId()},
|
||||||
{ChannelId: channel2.Id, Description: "DDD Inc Share", RemoteId: rcData[3].RemoteId, CreatorId: model.NewId()},
|
{ChannelId: channel2.Id, RemoteId: rcData[3].RemoteId, CreatorId: model.NewId()},
|
||||||
{ChannelId: channel2.Id, Description: "EEE Inc Share", RemoteId: rcData[4].RemoteId, CreatorId: model.NewId()},
|
{ChannelId: channel2.Id, RemoteId: rcData[4].RemoteId, CreatorId: model.NewId()},
|
||||||
}
|
}
|
||||||
for _, item := range scrData {
|
for _, item := range scrData {
|
||||||
_, err := ss.SharedChannel().SaveRemote(item)
|
_, err := ss.SharedChannel().SaveRemote(item)
|
||||||
@@ -360,11 +360,11 @@ func testRemoteClusterGetAllNotInChannel(t *testing.T, ss store.Store) {
|
|||||||
|
|
||||||
// Create some shared channel remotes
|
// Create some shared channel remotes
|
||||||
scrData := []*model.SharedChannelRemote{
|
scrData := []*model.SharedChannelRemote{
|
||||||
{ChannelId: channel1.Id, Description: "AAA Inc Share", RemoteId: rcData[0].RemoteId, CreatorId: model.NewId()},
|
{ChannelId: channel1.Id, RemoteId: rcData[0].RemoteId, CreatorId: model.NewId()},
|
||||||
{ChannelId: channel1.Id, Description: "BBB Inc Share", RemoteId: rcData[1].RemoteId, CreatorId: model.NewId()},
|
{ChannelId: channel1.Id, RemoteId: rcData[1].RemoteId, CreatorId: model.NewId()},
|
||||||
{ChannelId: channel2.Id, Description: "CCC Inc Share", RemoteId: rcData[2].RemoteId, CreatorId: model.NewId()},
|
{ChannelId: channel2.Id, RemoteId: rcData[2].RemoteId, CreatorId: model.NewId()},
|
||||||
{ChannelId: channel2.Id, Description: "DDD Inc Share", RemoteId: rcData[3].RemoteId, CreatorId: model.NewId()},
|
{ChannelId: channel2.Id, RemoteId: rcData[3].RemoteId, CreatorId: model.NewId()},
|
||||||
{ChannelId: channel3.Id, Description: "EEE Inc Share", RemoteId: rcData[4].RemoteId, CreatorId: model.NewId()},
|
{ChannelId: channel3.Id, RemoteId: rcData[4].RemoteId, CreatorId: model.NewId()},
|
||||||
}
|
}
|
||||||
for _, item := range scrData {
|
for _, item := range scrData {
|
||||||
_, err := ss.SharedChannel().SaveRemote(item)
|
_, err := ss.SharedChannel().SaveRemote(item)
|
||||||
|
|||||||
@@ -349,10 +349,9 @@ func testDeleteSharedChannel(t *testing.T, ss store.Store) {
|
|||||||
// add some remotes
|
// add some remotes
|
||||||
for i := 0; i < 10; i++ {
|
for i := 0; i < 10; i++ {
|
||||||
remote := &model.SharedChannelRemote{
|
remote := &model.SharedChannelRemote{
|
||||||
ChannelId: channel.Id,
|
ChannelId: channel.Id,
|
||||||
Description: "remote_" + strconv.Itoa(i),
|
CreatorId: model.NewId(),
|
||||||
CreatorId: model.NewId(),
|
RemoteId: model.NewId(),
|
||||||
RemoteId: model.NewId(),
|
|
||||||
}
|
}
|
||||||
_, err := ss.SharedChannel().SaveRemote(remote)
|
_, err := ss.SharedChannel().SaveRemote(remote)
|
||||||
require.NoError(t, err, "couldn't add remote", err)
|
require.NoError(t, err, "couldn't add remote", err)
|
||||||
@@ -391,10 +390,9 @@ func testSaveSharedChannelRemote(t *testing.T, ss store.Store) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
remote := &model.SharedChannelRemote{
|
remote := &model.SharedChannelRemote{
|
||||||
ChannelId: channel.Id,
|
ChannelId: channel.Id,
|
||||||
Description: "test_remote",
|
CreatorId: model.NewId(),
|
||||||
CreatorId: model.NewId(),
|
RemoteId: model.NewId(),
|
||||||
RemoteId: model.NewId(),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
remoteSaved, err := ss.SharedChannel().SaveRemote(remote)
|
remoteSaved, err := ss.SharedChannel().SaveRemote(remote)
|
||||||
@@ -406,10 +404,9 @@ func testSaveSharedChannelRemote(t *testing.T, ss store.Store) {
|
|||||||
|
|
||||||
t.Run("Save invalid shared channel remote", func(t *testing.T) {
|
t.Run("Save invalid shared channel remote", func(t *testing.T) {
|
||||||
remote := &model.SharedChannelRemote{
|
remote := &model.SharedChannelRemote{
|
||||||
ChannelId: "",
|
ChannelId: "",
|
||||||
Description: "test_remote",
|
CreatorId: model.NewId(),
|
||||||
CreatorId: model.NewId(),
|
RemoteId: model.NewId(),
|
||||||
RemoteId: model.NewId(),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := ss.SharedChannel().SaveRemote(remote)
|
_, err := ss.SharedChannel().SaveRemote(remote)
|
||||||
@@ -418,10 +415,9 @@ func testSaveSharedChannelRemote(t *testing.T, ss store.Store) {
|
|||||||
|
|
||||||
t.Run("Save shared channel remote with invalid channel id", func(t *testing.T) {
|
t.Run("Save shared channel remote with invalid channel id", func(t *testing.T) {
|
||||||
remote := &model.SharedChannelRemote{
|
remote := &model.SharedChannelRemote{
|
||||||
ChannelId: model.NewId(),
|
ChannelId: model.NewId(),
|
||||||
Description: "test_remote",
|
CreatorId: model.NewId(),
|
||||||
CreatorId: model.NewId(),
|
RemoteId: model.NewId(),
|
||||||
RemoteId: model.NewId(),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := ss.SharedChannel().SaveRemote(remote)
|
_, err := ss.SharedChannel().SaveRemote(remote)
|
||||||
@@ -435,10 +431,9 @@ func testUpdateSharedChannelRemote(t *testing.T, ss store.Store) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
remote := &model.SharedChannelRemote{
|
remote := &model.SharedChannelRemote{
|
||||||
ChannelId: channel.Id,
|
ChannelId: channel.Id,
|
||||||
Description: "test_remote_update",
|
CreatorId: model.NewId(),
|
||||||
CreatorId: model.NewId(),
|
RemoteId: model.NewId(),
|
||||||
RemoteId: model.NewId(),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
remoteSaved, err := ss.SharedChannel().SaveRemote(remote)
|
remoteSaved, err := ss.SharedChannel().SaveRemote(remote)
|
||||||
@@ -446,22 +441,19 @@ func testUpdateSharedChannelRemote(t *testing.T, ss store.Store) {
|
|||||||
|
|
||||||
remoteSaved.IsInviteAccepted = true
|
remoteSaved.IsInviteAccepted = true
|
||||||
remoteSaved.IsInviteConfirmed = true
|
remoteSaved.IsInviteConfirmed = true
|
||||||
remoteSaved.Description = "new_desc"
|
|
||||||
|
|
||||||
remoteUpdated, err := ss.SharedChannel().UpdateRemote(remoteSaved)
|
remoteUpdated, err := ss.SharedChannel().UpdateRemote(remoteSaved)
|
||||||
require.NoError(t, err, "couldn't update shared channel remote", err)
|
require.NoError(t, err, "couldn't update shared channel remote", err)
|
||||||
|
|
||||||
require.Equal(t, true, remoteUpdated.IsInviteAccepted)
|
require.Equal(t, true, remoteUpdated.IsInviteAccepted)
|
||||||
require.Equal(t, true, remoteUpdated.IsInviteConfirmed)
|
require.Equal(t, true, remoteUpdated.IsInviteConfirmed)
|
||||||
require.Equal(t, "new_desc", remoteUpdated.Description)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Update invalid shared channel remote", func(t *testing.T) {
|
t.Run("Update invalid shared channel remote", func(t *testing.T) {
|
||||||
remote := &model.SharedChannelRemote{
|
remote := &model.SharedChannelRemote{
|
||||||
ChannelId: "",
|
ChannelId: "",
|
||||||
Description: "test_remote",
|
CreatorId: model.NewId(),
|
||||||
CreatorId: model.NewId(),
|
RemoteId: model.NewId(),
|
||||||
RemoteId: model.NewId(),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := ss.SharedChannel().UpdateRemote(remote)
|
_, err := ss.SharedChannel().UpdateRemote(remote)
|
||||||
@@ -470,10 +462,9 @@ func testUpdateSharedChannelRemote(t *testing.T, ss store.Store) {
|
|||||||
|
|
||||||
t.Run("Update shared channel remote with invalid channel id", func(t *testing.T) {
|
t.Run("Update shared channel remote with invalid channel id", func(t *testing.T) {
|
||||||
remote := &model.SharedChannelRemote{
|
remote := &model.SharedChannelRemote{
|
||||||
ChannelId: model.NewId(),
|
ChannelId: model.NewId(),
|
||||||
Description: "test_remote",
|
CreatorId: model.NewId(),
|
||||||
CreatorId: model.NewId(),
|
RemoteId: model.NewId(),
|
||||||
RemoteId: model.NewId(),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := ss.SharedChannel().UpdateRemote(remote)
|
_, err := ss.SharedChannel().UpdateRemote(remote)
|
||||||
@@ -486,10 +477,9 @@ func testGetSharedChannelRemote(t *testing.T, ss store.Store) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
remote := &model.SharedChannelRemote{
|
remote := &model.SharedChannelRemote{
|
||||||
ChannelId: channel.Id,
|
ChannelId: channel.Id,
|
||||||
Description: "test_remote",
|
CreatorId: model.NewId(),
|
||||||
CreatorId: model.NewId(),
|
RemoteId: model.NewId(),
|
||||||
RemoteId: model.NewId(),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
remoteSaved, err := ss.SharedChannel().SaveRemote(remote)
|
remoteSaved, err := ss.SharedChannel().SaveRemote(remote)
|
||||||
@@ -501,7 +491,6 @@ func testGetSharedChannelRemote(t *testing.T, ss store.Store) {
|
|||||||
|
|
||||||
require.Equal(t, remoteSaved.Id, r.Id)
|
require.Equal(t, remoteSaved.Id, r.Id)
|
||||||
require.Equal(t, remoteSaved.ChannelId, r.ChannelId)
|
require.Equal(t, remoteSaved.ChannelId, r.ChannelId)
|
||||||
require.Equal(t, remoteSaved.Description, r.Description)
|
|
||||||
require.Equal(t, remoteSaved.CreatorId, r.CreatorId)
|
require.Equal(t, remoteSaved.CreatorId, r.CreatorId)
|
||||||
require.Equal(t, remoteSaved.RemoteId, r.RemoteId)
|
require.Equal(t, remoteSaved.RemoteId, r.RemoteId)
|
||||||
})
|
})
|
||||||
@@ -518,10 +507,9 @@ func testGetSharedChannelRemoteByIds(t *testing.T, ss store.Store) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
remote := &model.SharedChannelRemote{
|
remote := &model.SharedChannelRemote{
|
||||||
ChannelId: channel.Id,
|
ChannelId: channel.Id,
|
||||||
Description: "test_remote_by_ids",
|
CreatorId: model.NewId(),
|
||||||
CreatorId: model.NewId(),
|
RemoteId: model.NewId(),
|
||||||
RemoteId: model.NewId(),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
remoteSaved, err := ss.SharedChannel().SaveRemote(remote)
|
remoteSaved, err := ss.SharedChannel().SaveRemote(remote)
|
||||||
@@ -533,7 +521,6 @@ func testGetSharedChannelRemoteByIds(t *testing.T, ss store.Store) {
|
|||||||
|
|
||||||
require.Equal(t, remoteSaved.Id, r.Id)
|
require.Equal(t, remoteSaved.Id, r.Id)
|
||||||
require.Equal(t, remoteSaved.ChannelId, r.ChannelId)
|
require.Equal(t, remoteSaved.ChannelId, r.ChannelId)
|
||||||
require.Equal(t, remoteSaved.Description, r.Description)
|
|
||||||
require.Equal(t, remoteSaved.CreatorId, r.CreatorId)
|
require.Equal(t, remoteSaved.CreatorId, r.CreatorId)
|
||||||
require.Equal(t, remoteSaved.RemoteId, r.RemoteId)
|
require.Equal(t, remoteSaved.RemoteId, r.RemoteId)
|
||||||
})
|
})
|
||||||
@@ -553,12 +540,12 @@ func testGetSharedChannelRemotes(t *testing.T, ss store.Store) {
|
|||||||
remoteId := model.NewId()
|
remoteId := model.NewId()
|
||||||
|
|
||||||
data := []model.SharedChannelRemote{
|
data := []model.SharedChannelRemote{
|
||||||
{ChannelId: channel.Id, CreatorId: creator, Description: "r1", RemoteId: model.NewId(), IsInviteConfirmed: true},
|
{ChannelId: channel.Id, CreatorId: creator, RemoteId: model.NewId(), IsInviteConfirmed: true},
|
||||||
{ChannelId: channel.Id, CreatorId: creator, Description: "r2", RemoteId: model.NewId(), IsInviteConfirmed: true},
|
{ChannelId: channel.Id, CreatorId: creator, RemoteId: model.NewId(), IsInviteConfirmed: true},
|
||||||
{ChannelId: channel.Id, CreatorId: creator, Description: "r3", RemoteId: model.NewId(), IsInviteConfirmed: true},
|
{ChannelId: channel.Id, CreatorId: creator, RemoteId: model.NewId(), IsInviteConfirmed: true},
|
||||||
{CreatorId: creator, Description: "r4", RemoteId: remoteId, IsInviteConfirmed: true},
|
{CreatorId: creator, RemoteId: remoteId, IsInviteConfirmed: true},
|
||||||
{CreatorId: creator, Description: "r5", RemoteId: remoteId, IsInviteConfirmed: true},
|
{CreatorId: creator, RemoteId: remoteId, IsInviteConfirmed: true},
|
||||||
{CreatorId: creator, Description: "r6", RemoteId: remoteId},
|
{CreatorId: creator, RemoteId: remoteId},
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, r := range data {
|
for i, r := range data {
|
||||||
@@ -579,7 +566,7 @@ func testGetSharedChannelRemotes(t *testing.T, ss store.Store) {
|
|||||||
require.NoError(t, err, "should not error", err)
|
require.NoError(t, err, "should not error", err)
|
||||||
require.Len(t, remotes, 3)
|
require.Len(t, remotes, 3)
|
||||||
for _, r := range remotes {
|
for _, r := range remotes {
|
||||||
require.Contains(t, []string{"r1", "r2", "r3"}, r.Description)
|
require.Equal(t, channel.Id, r.ChannelId)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -600,7 +587,8 @@ func testGetSharedChannelRemotes(t *testing.T, ss store.Store) {
|
|||||||
require.NoError(t, err, "should not error", err)
|
require.NoError(t, err, "should not error", err)
|
||||||
require.Len(t, remotes, 2) // only confirmed invitations
|
require.Len(t, remotes, 2) // only confirmed invitations
|
||||||
for _, r := range remotes {
|
for _, r := range remotes {
|
||||||
require.Contains(t, []string{"r4", "r5"}, r.Description)
|
require.Equal(t, remoteId, r.RemoteId)
|
||||||
|
require.True(t, r.IsInviteConfirmed)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -620,9 +608,9 @@ func testGetSharedChannelRemotes(t *testing.T, ss store.Store) {
|
|||||||
}
|
}
|
||||||
remotes, err := ss.SharedChannel().GetRemotes(opts)
|
remotes, err := ss.SharedChannel().GetRemotes(opts)
|
||||||
require.NoError(t, err, "should not error", err)
|
require.NoError(t, err, "should not error", err)
|
||||||
require.Len(t, remotes, 3) // only confirmed invitations
|
require.Len(t, remotes, 3)
|
||||||
for _, r := range remotes {
|
for _, r := range remotes {
|
||||||
require.Contains(t, []string{"r4", "r5", "r6"}, r.Description)
|
require.Equal(t, remoteId, r.RemoteId)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -636,8 +624,8 @@ func testHasRemote(t *testing.T, ss store.Store) {
|
|||||||
|
|
||||||
creator := model.NewId()
|
creator := model.NewId()
|
||||||
data := []model.SharedChannelRemote{
|
data := []model.SharedChannelRemote{
|
||||||
{ChannelId: channel.Id, CreatorId: creator, Description: "r1", RemoteId: remote1},
|
{ChannelId: channel.Id, CreatorId: creator, RemoteId: remote1},
|
||||||
{ChannelId: channel.Id, CreatorId: creator, Description: "r2", RemoteId: remote2},
|
{ChannelId: channel.Id, CreatorId: creator, RemoteId: remote2},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, r := range data {
|
for _, r := range data {
|
||||||
@@ -731,10 +719,9 @@ func testUpdateSharedChannelRemoteNextSyncAt(t *testing.T, ss store.Store) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
remote := &model.SharedChannelRemote{
|
remote := &model.SharedChannelRemote{
|
||||||
ChannelId: channel.Id,
|
ChannelId: channel.Id,
|
||||||
Description: "test_remote",
|
CreatorId: model.NewId(),
|
||||||
CreatorId: model.NewId(),
|
RemoteId: model.NewId(),
|
||||||
RemoteId: model.NewId(),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
remoteSaved, err := ss.SharedChannel().SaveRemote(remote)
|
remoteSaved, err := ss.SharedChannel().SaveRemote(remote)
|
||||||
@@ -762,10 +749,9 @@ func testDeleteSharedChannelRemote(t *testing.T, ss store.Store) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
remote := &model.SharedChannelRemote{
|
remote := &model.SharedChannelRemote{
|
||||||
ChannelId: channel.Id,
|
ChannelId: channel.Id,
|
||||||
Description: "test_remote",
|
CreatorId: model.NewId(),
|
||||||
CreatorId: model.NewId(),
|
RemoteId: model.NewId(),
|
||||||
RemoteId: model.NewId(),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
remoteSaved, err := ss.SharedChannel().SaveRemote(remote)
|
remoteSaved, err := ss.SharedChannel().SaveRemote(remote)
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ func GetMockStoreForSetupFunctions() *mocks.Store {
|
|||||||
systemStore.On("GetByName", model.MIGRATION_KEY_ADD_ABOUT_SUBSECTION_PERMISSIONS).Return(&model.System{Name: model.MIGRATION_KEY_ADD_ABOUT_SUBSECTION_PERMISSIONS, Value: "true"}, nil)
|
systemStore.On("GetByName", model.MIGRATION_KEY_ADD_ABOUT_SUBSECTION_PERMISSIONS).Return(&model.System{Name: model.MIGRATION_KEY_ADD_ABOUT_SUBSECTION_PERMISSIONS, Value: "true"}, nil)
|
||||||
systemStore.On("GetByName", model.MIGRATION_KEY_ADD_INTEGRATIONS_SUBSECTION_PERMISSIONS).Return(&model.System{Name: model.MIGRATION_KEY_ADD_INTEGRATIONS_SUBSECTION_PERMISSIONS, Value: "true"}, nil)
|
systemStore.On("GetByName", model.MIGRATION_KEY_ADD_INTEGRATIONS_SUBSECTION_PERMISSIONS).Return(&model.System{Name: model.MIGRATION_KEY_ADD_INTEGRATIONS_SUBSECTION_PERMISSIONS, Value: "true"}, nil)
|
||||||
systemStore.On("GetByName", model.MIGRATION_KEY_ADD_MANAGE_SHARED_CHANNEL_PERMISSIONS).Return(&model.System{Name: model.MIGRATION_KEY_ADD_MANAGE_SHARED_CHANNEL_PERMISSIONS, Value: "true"}, nil)
|
systemStore.On("GetByName", model.MIGRATION_KEY_ADD_MANAGE_SHARED_CHANNEL_PERMISSIONS).Return(&model.System{Name: model.MIGRATION_KEY_ADD_MANAGE_SHARED_CHANNEL_PERMISSIONS, Value: "true"}, nil)
|
||||||
systemStore.On("GetByName", model.MIGRATION_KEY_ADD_MANAGE_REMOTE_CLUSTERS_PERMISSIONS).Return(&model.System{Name: model.MIGRATION_KEY_ADD_MANAGE_REMOTE_CLUSTERS_PERMISSIONS, Value: "true"}, nil)
|
systemStore.On("GetByName", model.MIGRATION_KEY_ADD_MANAGE_SECURE_CONNECTIONS_PERMISSIONS).Return(&model.System{Name: model.MIGRATION_KEY_ADD_MANAGE_SECURE_CONNECTIONS_PERMISSIONS, Value: "true"}, nil)
|
||||||
systemStore.On("Get").Return(make(model.StringMap), nil)
|
systemStore.On("Get").Return(make(model.StringMap), nil)
|
||||||
systemStore.On("Save", mock.AnythingOfType("*model.System")).Return(nil)
|
systemStore.On("Save", mock.AnythingOfType("*model.System")).Return(nil)
|
||||||
|
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user