[MM-56986] imports/import_validators: add valid guest role check (#28658)
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
424ce2b8db
Коммит
b59819da68
@@ -261,6 +261,10 @@ func ValidateUserImportData(data *UserImportData) *model.AppError {
|
||||
return model.NewAppError("BulkImport", "app.import.validate_user_import_data.roles_invalid.error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if !isValidGuestRoles(*data) {
|
||||
return model.NewAppError("BulkImport", "app.import.validate_user_import_data.guest_roles_conflict.error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if data.NotifyProps != nil {
|
||||
if data.NotifyProps.Desktop != nil && !isValidUserNotifyLevel(*data.NotifyProps.Desktop) {
|
||||
return model.NewAppError("BulkImport", "app.import.validate_user_import_data.notify_props_desktop_invalid.error", nil, "", http.StatusBadRequest)
|
||||
@@ -688,3 +692,47 @@ func isValidEmailBatchingInterval(emailInterval string) bool {
|
||||
emailInterval == model.PreferenceEmailIntervalFifteen ||
|
||||
emailInterval == model.PreferenceEmailIntervalHour
|
||||
}
|
||||
|
||||
// isValidGuestRoles checks if the user has both guest roles in the same team or channel.
|
||||
// at this point we assume that the user has a valid role scheme.
|
||||
func isValidGuestRoles(data UserImportData) bool {
|
||||
if data.Roles == nil {
|
||||
return true
|
||||
}
|
||||
isSystemGuest := model.IsInRole(*data.Roles, model.SystemGuestRoleId)
|
||||
|
||||
var isTeamGuest, isChannelGuest bool
|
||||
if data.Teams != nil {
|
||||
// counters for guest roles for teams and channels
|
||||
// we expect the total count of guest roles to be equal to the total count of teams and channels
|
||||
var gtc, ctc int
|
||||
for _, team := range *data.Teams {
|
||||
if team.Roles != nil && model.IsInRole(*team.Roles, model.TeamGuestRoleId) {
|
||||
gtc++
|
||||
}
|
||||
|
||||
if *team.Channels != nil {
|
||||
for _, channel := range *team.Channels {
|
||||
if channel.Roles != nil && model.IsInRole(*channel.Roles, model.ChannelGuestRoleId) {
|
||||
ctc++
|
||||
}
|
||||
}
|
||||
|
||||
if ctc == len(*team.Channels) {
|
||||
isChannelGuest = true
|
||||
}
|
||||
}
|
||||
}
|
||||
if gtc == len(*data.Teams) {
|
||||
isTeamGuest = true
|
||||
}
|
||||
}
|
||||
|
||||
// basically we want to be sure if the user either fully guest in all 3 places or not at all
|
||||
// (a | b | c) & !(a & b & c) -> 3-way XOR?
|
||||
if (isSystemGuest || isTeamGuest || isChannelGuest) && !(isSystemGuest && isTeamGuest && isChannelGuest) {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -1469,3 +1469,116 @@ func checkError(t *testing.T, err *model.AppError) {
|
||||
func checkNoError(t *testing.T, err *model.AppError) {
|
||||
require.Nil(t, err, "Unexpected Error: %v", err)
|
||||
}
|
||||
|
||||
func TestIsValidGuestRoles(t *testing.T) {
|
||||
var testCases = []struct {
|
||||
name string
|
||||
input UserImportData
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
name: "Valid case: User is a guest in all places",
|
||||
input: UserImportData{
|
||||
Roles: model.NewPointer(model.SystemGuestRoleId),
|
||||
Teams: &[]UserTeamImportData{
|
||||
{
|
||||
Roles: model.NewPointer(model.TeamGuestRoleId),
|
||||
Channels: &[]UserChannelImportData{
|
||||
{Roles: model.NewPointer(model.ChannelGuestRoleId)},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "Invalid case: User is a guest in a team but not in another team",
|
||||
input: UserImportData{
|
||||
Roles: model.NewPointer(model.SystemGuestRoleId),
|
||||
Teams: &[]UserTeamImportData{
|
||||
{
|
||||
Roles: model.NewPointer(model.TeamGuestRoleId),
|
||||
Channels: &[]UserChannelImportData{
|
||||
{Roles: model.NewPointer(model.ChannelGuestRoleId)},
|
||||
},
|
||||
},
|
||||
{
|
||||
Roles: model.NewPointer(model.TeamUserRoleId),
|
||||
Channels: &[]UserChannelImportData{
|
||||
{Roles: model.NewPointer(model.ChannelUserRoleId)},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "Invalid case: User is a guest in a team but not in another team and has no channel membership",
|
||||
input: UserImportData{
|
||||
Roles: model.NewPointer(model.SystemGuestRoleId),
|
||||
Teams: &[]UserTeamImportData{
|
||||
{
|
||||
Roles: model.NewPointer(model.TeamGuestRoleId),
|
||||
Channels: &[]UserChannelImportData{
|
||||
{Roles: model.NewPointer(model.ChannelGuestRoleId)},
|
||||
},
|
||||
},
|
||||
{
|
||||
Roles: model.NewPointer(model.TeamUserRoleId),
|
||||
Channels: &[]UserChannelImportData{},
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "Invalid case: User is system guest but not guest in team and channel",
|
||||
input: UserImportData{
|
||||
Roles: model.NewPointer(model.SystemGuestRoleId),
|
||||
},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "Invalid case: User has mixed roles",
|
||||
input: UserImportData{
|
||||
Roles: model.NewPointer(model.SystemGuestRoleId),
|
||||
Teams: &[]UserTeamImportData{
|
||||
{
|
||||
Roles: model.NewPointer(model.TeamUserRoleId),
|
||||
Channels: &[]UserChannelImportData{
|
||||
{Roles: model.NewPointer(model.ChannelGuestRoleId)},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "Valid case: User does not have any role defined in any place",
|
||||
input: UserImportData{},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "Valid case: User is not a guest in any place",
|
||||
input: UserImportData{
|
||||
Roles: model.NewPointer(model.SystemUserRoleId),
|
||||
Teams: &[]UserTeamImportData{
|
||||
{
|
||||
Roles: model.NewPointer(model.TeamAdminRoleId),
|
||||
Channels: &[]UserChannelImportData{
|
||||
{Roles: model.NewPointer(model.ChannelAdminRoleId)},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
result := isValidGuestRoles(tc.input)
|
||||
assert.Equal(t, tc.expected, result, tc.name)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Ссылка в новой задаче
Block a user