mirror of
https://github.com/mattermost/mattermost.git
synced 2025-02-25 18:55:24 -06:00
PLT-5365 Import of basic user properties. (#5231)
This commit is contained in:
175
app/import.go
175
app/import.go
@@ -15,6 +15,7 @@ import (
|
||||
l4g "github.com/alecthomas/log4go"
|
||||
"github.com/mattermost/platform/model"
|
||||
"github.com/mattermost/platform/utils"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// Import Data Models
|
||||
@@ -23,6 +24,7 @@ type LineImportData struct {
|
||||
Type string `json:"type"`
|
||||
Team *TeamImportData `json:"team"`
|
||||
Channel *ChannelImportData `json:"channel"`
|
||||
User *UserImportData `json:"user"`
|
||||
}
|
||||
|
||||
type TeamImportData struct {
|
||||
@@ -42,6 +44,19 @@ type ChannelImportData struct {
|
||||
Purpose *string `json:"purpose"`
|
||||
}
|
||||
|
||||
type UserImportData struct {
|
||||
Username *string `json:"username"`
|
||||
Email *string `json:"email"`
|
||||
AuthService *string `json:"auth_service"`
|
||||
AuthData *string `json:"auth_data"`
|
||||
Nickname *string `json:"nickname"`
|
||||
FirstName *string `json:"first_name"`
|
||||
LastName *string `json:"last_name"`
|
||||
Position *string `json:"position"`
|
||||
Roles *string `json:"roles"`
|
||||
Locale *string `json:"locale"`
|
||||
}
|
||||
|
||||
//
|
||||
// -- Bulk Import Functions --
|
||||
// These functions import data directly into the database. Security and permission checks are bypassed but validity is
|
||||
@@ -86,6 +101,12 @@ func ImportLine(line LineImportData, dryRun bool) *model.AppError {
|
||||
} else {
|
||||
return ImportChannel(line.Channel, dryRun)
|
||||
}
|
||||
case line.Type == "user":
|
||||
if line.User == nil {
|
||||
return model.NewAppError("BulkImport", "app.import.import_line.null_user.error", nil, "", http.StatusBadRequest)
|
||||
} else {
|
||||
return ImportUser(line.User, dryRun)
|
||||
}
|
||||
default:
|
||||
return model.NewLocAppError("BulkImport", "app.import.import_line.unknown_line_type.error", map[string]interface{}{"Type": line.Type}, "")
|
||||
}
|
||||
@@ -251,6 +272,158 @@ func validateChannelImportData(data *ChannelImportData) *model.AppError {
|
||||
return nil
|
||||
}
|
||||
|
||||
func ImportUser(data *UserImportData, dryRun bool) *model.AppError {
|
||||
if err := validateUserImportData(data); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// If this is a Dry Run, do not continue any further.
|
||||
if dryRun {
|
||||
return nil
|
||||
}
|
||||
|
||||
var user *model.User
|
||||
if result := <-Srv.Store.User().GetByUsername(*data.Username); result.Err == nil {
|
||||
user = result.Data.(*model.User)
|
||||
} else {
|
||||
user = &model.User{}
|
||||
}
|
||||
|
||||
user.Username = *data.Username
|
||||
user.Email = *data.Email
|
||||
|
||||
var password string
|
||||
var authService string
|
||||
var authData *string
|
||||
|
||||
if data.AuthService != nil {
|
||||
authService = *data.AuthService
|
||||
}
|
||||
|
||||
// AuthData and Password are mutually exclusive.
|
||||
if data.AuthData != nil {
|
||||
authData = data.AuthData
|
||||
password = ""
|
||||
} else {
|
||||
// If no Auth Data is specified, we must generate a password.
|
||||
password = model.NewId()
|
||||
authData = nil
|
||||
}
|
||||
|
||||
user.Password = password
|
||||
user.AuthService = authService
|
||||
user.AuthData = authData
|
||||
|
||||
// Automatically assume all emails are verified.
|
||||
emailVerified := true
|
||||
user.EmailVerified = emailVerified
|
||||
|
||||
if data.Nickname != nil {
|
||||
user.Nickname = *data.Nickname
|
||||
}
|
||||
|
||||
if data.FirstName != nil {
|
||||
user.FirstName = *data.FirstName
|
||||
}
|
||||
|
||||
if data.LastName != nil {
|
||||
user.LastName = *data.LastName
|
||||
}
|
||||
|
||||
if data.Position != nil {
|
||||
user.Position = *data.Position
|
||||
}
|
||||
|
||||
if data.Locale != nil {
|
||||
user.Locale = *data.Locale
|
||||
} else {
|
||||
user.Locale = *utils.Cfg.LocalizationSettings.DefaultClientLocale
|
||||
}
|
||||
|
||||
var roles string
|
||||
if data.Roles != nil {
|
||||
roles = *data.Roles
|
||||
} else if len(user.Roles) == 0 {
|
||||
// Set SYSTEM_USER roles on newly created users by default.
|
||||
roles = model.ROLE_SYSTEM_USER.Id
|
||||
}
|
||||
user.Roles = roles
|
||||
|
||||
if user.Id == "" {
|
||||
if _, err := createUser(user); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if _, err := UpdateUser(user, utils.GetSiteURL(), false); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := UpdateUserRoles(user.Id, roles); err != nil {
|
||||
return err
|
||||
}
|
||||
if len(password) > 0 {
|
||||
if err := UpdatePassword(user, password); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if res := <-Srv.Store.User().UpdateAuthData(user.Id, authService, authData, user.Email, false); res.Err != nil {
|
||||
return res.Err
|
||||
}
|
||||
}
|
||||
if emailVerified {
|
||||
if err := VerifyUserEmail(user.Id); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateUserImportData(data *UserImportData) *model.AppError {
|
||||
|
||||
if data.Username == nil {
|
||||
return model.NewAppError("BulkImport", "app.import.validate_user_import_data.username_missing.error", nil, "", http.StatusBadRequest)
|
||||
} else if !model.IsValidUsername(*data.Username) {
|
||||
return model.NewAppError("BulkImport", "app.import.validate_user_import_data.username_invalid.error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if data.Email == nil {
|
||||
return model.NewAppError("BulkImport", "app.import.validate_user_import_data.email_missing.error", nil, "", http.StatusBadRequest)
|
||||
} else if len(*data.Email) == 0 || len(*data.Email) > model.USER_EMAIL_MAX_LENGTH {
|
||||
return model.NewAppError("BulkImport", "app.import.validate_user_import_data.email_length.error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if data.AuthService != nil && len(*data.AuthService) == 0 {
|
||||
return model.NewAppError("BulkImport", "app.import.validate_user_import_data.auth_service_length.error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if data.AuthData != nil && len(*data.AuthData) > model.USER_AUTH_DATA_MAX_LENGTH {
|
||||
return model.NewAppError("BulkImport", "app.import.validate_user_import_data.auth_data_length.error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if data.Nickname != nil && utf8.RuneCountInString(*data.Nickname) > model.USER_NICKNAME_MAX_RUNES {
|
||||
return model.NewAppError("BulkImport", "app.import.validate_user_import_data.nickname_length.error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if data.FirstName != nil && utf8.RuneCountInString(*data.FirstName) > model.USER_FIRST_NAME_MAX_RUNES {
|
||||
return model.NewAppError("BulkImport", "app.import.validate_user_import_data.first_name_length.error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if data.LastName != nil && utf8.RuneCountInString(*data.LastName) > model.USER_LAST_NAME_MAX_RUNES {
|
||||
return model.NewAppError("BulkImport", "app.import.validate_user_import_data.last_name_length.error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if data.Position != nil && utf8.RuneCountInString(*data.Position) > model.USER_POSITION_MAX_RUNES {
|
||||
return model.NewAppError("BulkImport", "app.import.validate_user_import_data.position_length.error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if data.Roles != nil && !model.IsValidUserRoles(*data.Roles) {
|
||||
return model.NewAppError("BulkImport", "app.import.validate_user_import_data.roles_invalid.error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
//
|
||||
// -- Old SlackImport Functions --
|
||||
// Import functions are sutible for entering posts and users into the database without
|
||||
@@ -288,7 +461,7 @@ func ImportPost(post *model.Post) {
|
||||
}
|
||||
}
|
||||
|
||||
func ImportUser(team *model.Team, user *model.User) *model.User {
|
||||
func OldImportUser(team *model.Team, user *model.User) *model.User {
|
||||
user.MakeNonNil()
|
||||
|
||||
user.Roles = model.ROLE_SYSTEM_USER.Id
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"github.com/mattermost/platform/model"
|
||||
"strings"
|
||||
"testing"
|
||||
"github.com/mattermost/platform/utils"
|
||||
)
|
||||
|
||||
func ptrStr(s string) *string {
|
||||
@@ -236,6 +237,118 @@ func TestImportValidateChannelImportData(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestImportValidateUserImportData(t *testing.T) {
|
||||
|
||||
// Test with minimum required valid properties.
|
||||
data := UserImportData{
|
||||
Username: ptrStr("bob"),
|
||||
Email: ptrStr("bob@example.com"),
|
||||
}
|
||||
if err := validateUserImportData(&data); err != nil {
|
||||
t.Fatal("Validation failed but should have been valid.")
|
||||
}
|
||||
|
||||
// Invalid Usernames.
|
||||
data.Username = nil
|
||||
if err := validateUserImportData(&data); err == nil {
|
||||
t.Fatal("Validation should have failed due to nil Username.")
|
||||
}
|
||||
|
||||
data.Username = ptrStr("")
|
||||
if err := validateUserImportData(&data); err == nil {
|
||||
t.Fatal("Validation should have failed due to 0 length Username.")
|
||||
}
|
||||
|
||||
data.Username = ptrStr(strings.Repeat("abcdefghij", 7))
|
||||
if err := validateUserImportData(&data); err == nil {
|
||||
t.Fatal("Validation should have failed due to too long Username.")
|
||||
}
|
||||
|
||||
data.Username = ptrStr("i am a username with spaces and !!!")
|
||||
if err := validateUserImportData(&data); err == nil {
|
||||
t.Fatal("Validation should have failed due to invalid characters in Username.")
|
||||
}
|
||||
|
||||
data.Username = ptrStr("bob")
|
||||
|
||||
// Invalid Emails
|
||||
data.Email = nil
|
||||
if err := validateUserImportData(&data); err == nil {
|
||||
t.Fatal("Validation should have failed due to nil Email.")
|
||||
}
|
||||
|
||||
data.Email = ptrStr("")
|
||||
if err := validateUserImportData(&data); err == nil {
|
||||
t.Fatal("Validation should have failed due to 0 length Email.")
|
||||
}
|
||||
|
||||
data.Email = ptrStr(strings.Repeat("abcdefghij", 13))
|
||||
if err := validateUserImportData(&data); err == nil {
|
||||
t.Fatal("Validation should have failed due to too long Email.")
|
||||
}
|
||||
|
||||
data.Email = ptrStr("bob@example.com")
|
||||
|
||||
// TODO: Auth Service and Auth Data.
|
||||
|
||||
// Test a valid User with all fields populated.
|
||||
data = UserImportData{
|
||||
Username: ptrStr("bob"),
|
||||
Email: ptrStr("bob@example.com"),
|
||||
AuthService: ptrStr("ldap"),
|
||||
AuthData: ptrStr("bob"),
|
||||
Nickname: ptrStr("BobNick"),
|
||||
FirstName: ptrStr("Bob"),
|
||||
LastName: ptrStr("Blob"),
|
||||
Position: ptrStr("The Boss"),
|
||||
Roles: ptrStr("system_user"),
|
||||
Locale: ptrStr("en"),
|
||||
}
|
||||
if err := validateUserImportData(&data); err != nil {
|
||||
t.Fatal("Validation failed but should have been valid.")
|
||||
}
|
||||
|
||||
// Test various invalid optional field values.
|
||||
data.Nickname = ptrStr(strings.Repeat("abcdefghij", 7))
|
||||
if err := validateUserImportData(&data); err == nil {
|
||||
t.Fatal("Validation should have failed due to too long Nickname.")
|
||||
}
|
||||
data.Nickname = ptrStr("BobNick")
|
||||
|
||||
data.FirstName = ptrStr(strings.Repeat("abcdefghij", 7))
|
||||
if err := validateUserImportData(&data); err == nil {
|
||||
t.Fatal("Validation should have failed due to too long First Name.")
|
||||
}
|
||||
data.FirstName = ptrStr("Bob")
|
||||
|
||||
data.LastName = ptrStr(strings.Repeat("abcdefghij", 7))
|
||||
if err := validateUserImportData(&data); err == nil {
|
||||
t.Fatal("Validation should have failed due to too long Last name.")
|
||||
}
|
||||
data.LastName = ptrStr("Blob")
|
||||
|
||||
data.Position = ptrStr(strings.Repeat("abcdefghij", 7))
|
||||
if err := validateUserImportData(&data); err == nil {
|
||||
t.Fatal("Validation should have failed due to too long Position.")
|
||||
}
|
||||
data.Position = ptrStr("The Boss")
|
||||
|
||||
data.Roles = ptrStr("system_user wat")
|
||||
if err := validateUserImportData(&data); err == nil {
|
||||
t.Fatal("Validation should have failed due to too unrecognised role.")
|
||||
}
|
||||
data.Roles = nil
|
||||
if err := validateUserImportData(&data); err != nil {
|
||||
t.Fatal("Validation failed but should have been valid.")
|
||||
}
|
||||
|
||||
data.Roles = ptrStr("")
|
||||
if err := validateUserImportData(&data); err != nil {
|
||||
t.Fatal("Validation failed but should have been valid.")
|
||||
}
|
||||
data.Roles = ptrStr("system_user")
|
||||
}
|
||||
|
||||
func TestImportImportTeam(t *testing.T) {
|
||||
_ = Setup()
|
||||
|
||||
@@ -505,6 +618,182 @@ func TestImportImportChannel(t *testing.T) {
|
||||
|
||||
}
|
||||
|
||||
func TestImportImportUser(t *testing.T) {
|
||||
_ = Setup()
|
||||
|
||||
// Check how many users are in the database.
|
||||
var userCount int64
|
||||
if r := <-Srv.Store.User().GetTotalUsersCount(); r.Err == nil {
|
||||
userCount = r.Data.(int64)
|
||||
} else {
|
||||
t.Fatalf("Failed to get user count.")
|
||||
}
|
||||
|
||||
// Do an invalid user in dry-run mode.
|
||||
data := UserImportData{
|
||||
Username: ptrStr(model.NewId()),
|
||||
}
|
||||
if err := ImportUser(&data, true); err == nil {
|
||||
t.Fatalf("Should have failed to import invalid user.")
|
||||
}
|
||||
|
||||
// Check that no more users are in the DB.
|
||||
if r := <-Srv.Store.User().GetTotalUsersCount(); r.Err == nil {
|
||||
if r.Data.(int64) != userCount {
|
||||
t.Fatalf("Unexpected number of users")
|
||||
}
|
||||
} else {
|
||||
t.Fatalf("Failed to get user count.")
|
||||
}
|
||||
|
||||
// Do a valid user in dry-run mode.
|
||||
data = UserImportData{
|
||||
Username: ptrStr(model.NewId()),
|
||||
Email: ptrStr(model.NewId() + "@example.com"),
|
||||
}
|
||||
if err := ImportUser(&data, true); err != nil {
|
||||
t.Fatalf("Should have succeeded to import valid user.")
|
||||
}
|
||||
|
||||
// Check that no more users are in the DB.
|
||||
if r := <-Srv.Store.User().GetTotalUsersCount(); r.Err == nil {
|
||||
if r.Data.(int64) != userCount {
|
||||
t.Fatalf("Unexpected number of users")
|
||||
}
|
||||
} else {
|
||||
t.Fatalf("Failed to get user count.")
|
||||
}
|
||||
|
||||
// Do an invalid user in apply mode.
|
||||
data = UserImportData{
|
||||
Username: ptrStr(model.NewId()),
|
||||
}
|
||||
if err := ImportUser(&data, false); err == nil {
|
||||
t.Fatalf("Should have failed to import invalid user.")
|
||||
}
|
||||
|
||||
// Check that no more users are in the DB.
|
||||
if r := <-Srv.Store.User().GetTotalUsersCount(); r.Err == nil {
|
||||
if r.Data.(int64) != userCount {
|
||||
t.Fatalf("Unexpected number of users")
|
||||
}
|
||||
} else {
|
||||
t.Fatalf("Failed to get user count.")
|
||||
}
|
||||
|
||||
// Do a valid user in apply mode.
|
||||
username := model.NewId()
|
||||
data = UserImportData{
|
||||
Username: &username,
|
||||
Email: ptrStr(model.NewId() + "@example.com"),
|
||||
Nickname: ptrStr(model.NewId()),
|
||||
FirstName: ptrStr(model.NewId()),
|
||||
LastName: ptrStr(model.NewId()),
|
||||
Position: ptrStr(model.NewId()),
|
||||
}
|
||||
if err := ImportUser(&data, false); err != nil {
|
||||
t.Fatalf("Should have succeeded to import valid user.")
|
||||
}
|
||||
|
||||
// Check that one more user is in the DB.
|
||||
if r := <-Srv.Store.User().GetTotalUsersCount(); r.Err == nil {
|
||||
if r.Data.(int64) != userCount + 1 {
|
||||
t.Fatalf("Unexpected number of users")
|
||||
}
|
||||
} else {
|
||||
t.Fatalf("Failed to get user count.")
|
||||
}
|
||||
|
||||
// Get the user and check all the fields are correct.
|
||||
if user, err := GetUserByUsername(username); err != nil {
|
||||
t.Fatalf("Failed to get user from database.")
|
||||
} else {
|
||||
if user.Email != *data.Email || user.Nickname != *data.Nickname || user.FirstName != *data.FirstName || user.LastName != *data.LastName || user.Position != *data.Position {
|
||||
t.Fatalf("User properties do not match Import Data.")
|
||||
}
|
||||
// Check calculated properties.
|
||||
if user.AuthService != "" {
|
||||
t.Fatalf("Expected Auth Service to be empty.")
|
||||
}
|
||||
|
||||
if ! (user.AuthData == nil || *user.AuthData == "") {
|
||||
t.Fatalf("Expected AuthData to be empty.")
|
||||
}
|
||||
|
||||
if len(user.Password) == 0 {
|
||||
t.Fatalf("Expected password to be set.")
|
||||
}
|
||||
|
||||
if !user.EmailVerified {
|
||||
t.Fatalf("Expected EmailVerified to be true.")
|
||||
}
|
||||
|
||||
if user.Locale != *utils.Cfg.LocalizationSettings.DefaultClientLocale {
|
||||
t.Fatalf("Expected Locale to be the default.")
|
||||
}
|
||||
|
||||
if user.Roles != "system_user" {
|
||||
t.Fatalf("Expected roles to be system_user")
|
||||
}
|
||||
}
|
||||
|
||||
// Alter all the fields of that user.
|
||||
data.Email = ptrStr(model.NewId() + "@example.com")
|
||||
data.AuthService = ptrStr("ldap")
|
||||
data.AuthData = &username
|
||||
data.Nickname = ptrStr(model.NewId())
|
||||
data.FirstName = ptrStr(model.NewId())
|
||||
data.LastName = ptrStr(model.NewId())
|
||||
data.Position = ptrStr(model.NewId())
|
||||
data.Roles = ptrStr("system_admin system_user")
|
||||
data.Locale = ptrStr("zh_CN")
|
||||
if err := ImportUser(&data, false); err != nil {
|
||||
t.Fatalf("Should have succeeded to update valid user %v", err)
|
||||
}
|
||||
|
||||
// Check user count the same.
|
||||
if r := <-Srv.Store.User().GetTotalUsersCount(); r.Err == nil {
|
||||
if r.Data.(int64) != userCount + 1 {
|
||||
t.Fatalf("Unexpected number of users")
|
||||
}
|
||||
} else {
|
||||
t.Fatalf("Failed to get user count.")
|
||||
}
|
||||
|
||||
// Get the user and check all the fields are correct.
|
||||
if user, err := GetUserByUsername(username); err != nil {
|
||||
t.Fatalf("Failed to get user from database.")
|
||||
} else {
|
||||
if user.Email != *data.Email || user.Nickname != *data.Nickname || user.FirstName != *data.FirstName || user.LastName != *data.LastName || user.Position != *data.Position {
|
||||
t.Fatalf("Updated User properties do not match Import Data.")
|
||||
}
|
||||
// Check calculated properties.
|
||||
if user.AuthService != "ldap" {
|
||||
t.Fatalf("Expected Auth Service to be ldap \"%v\"", user.AuthService)
|
||||
}
|
||||
|
||||
if ! (user.AuthData == data.AuthData || *user.AuthData == *data.AuthData) {
|
||||
t.Fatalf("Expected AuthData to be set.")
|
||||
}
|
||||
|
||||
if len(user.Password) != 0 {
|
||||
t.Fatalf("Expected password to be empty.")
|
||||
}
|
||||
|
||||
if !user.EmailVerified {
|
||||
t.Fatalf("Expected EmailVerified to be true.")
|
||||
}
|
||||
|
||||
if user.Locale != *data.Locale {
|
||||
t.Fatalf("Expected Locale to be the set.")
|
||||
}
|
||||
|
||||
if user.Roles != *data.Roles {
|
||||
t.Fatalf("Expected roles to be set: %v", user.Roles)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestImportImportLine(t *testing.T) {
|
||||
_ = Setup()
|
||||
|
||||
@@ -528,6 +817,12 @@ func TestImportImportLine(t *testing.T) {
|
||||
if err := ImportLine(line, false); err == nil {
|
||||
t.Fatalf("Expected an error when importing a line with type channel with a nil channel.")
|
||||
}
|
||||
|
||||
// Try import line with user type but nil user.
|
||||
line.Type = "user"
|
||||
if err := ImportLine(line, false); err == nil {
|
||||
t.Fatalf("Expected an error when importing a line with type uesr with a nil user.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestImportBulkImport(t *testing.T) {
|
||||
@@ -538,7 +833,8 @@ func TestImportBulkImport(t *testing.T) {
|
||||
|
||||
// Run bulk import with a valid 1 of everything.
|
||||
data1 := `{"type": "team", "team": {"type": "O", "display_name": "lskmw2d7a5ao7ppwqh5ljchvr4", "name": "` + teamName + `"}}
|
||||
{"type": "channel", "channel": {"type": "O", "display_name": "xr6m6udffngark2uekvr3hoeny", "team": "` + teamName + `", "name": "` + channelName + `"}}`
|
||||
{"type": "channel", "channel": {"type": "O", "display_name": "xr6m6udffngark2uekvr3hoeny", "team": "` + teamName + `", "name": "` + channelName + `"}}
|
||||
{"type": "user", "user": {"username": "kufjgnkxkrhhfgbrip6qxkfsaa", "email": "kufjgnkxkrhhfgbrip6qxkfsaa@example.com"}}`
|
||||
|
||||
if err, line := BulkImport(strings.NewReader(data1), false); err != nil || line != 0 {
|
||||
t.Fatalf("BulkImport should have succeeded: %v, %v", err.Error(), line)
|
||||
|
||||
@@ -178,7 +178,7 @@ func SlackAddUsers(teamId string, slackusers []SlackUser, log *bytes.Buffer) map
|
||||
Password: password,
|
||||
}
|
||||
|
||||
if mUser := ImportUser(team, &newUser); mUser != nil {
|
||||
if mUser := OldImportUser(team, &newUser); mUser != nil {
|
||||
addedUsers[sUser.Id] = mUser
|
||||
log.WriteString(utils.T("api.slackimport.slack_add_users.email_pwd", map[string]interface{}{"Email": newUser.Email, "Password": password}))
|
||||
} else {
|
||||
@@ -210,7 +210,7 @@ func SlackAddBotUser(teamId string, log *bytes.Buffer) *model.User {
|
||||
Password: password,
|
||||
}
|
||||
|
||||
if mUser := ImportUser(team, &botUser); mUser != nil {
|
||||
if mUser := OldImportUser(team, &botUser); mUser != nil {
|
||||
log.WriteString(utils.T("api.slackimport.slack_add_bot_user.email_pwd", map[string]interface{}{"Email": botUser.Email, "Password": password}))
|
||||
return mUser
|
||||
} else {
|
||||
|
||||
63
app/user.go
63
app/user.go
@@ -173,9 +173,23 @@ func CreateUser(user *model.User) (*model.User, *model.AppError) {
|
||||
}
|
||||
}
|
||||
|
||||
user.MakeNonNil()
|
||||
user.Locale = *utils.Cfg.LocalizationSettings.DefaultClientLocale
|
||||
|
||||
if ruser, err := createUser(user); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
// This message goes to everyone, so the teamId, channelId and userId are irrelevant
|
||||
message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_NEW_USER, "", "", "", nil)
|
||||
message.Add("user_id", ruser.Id)
|
||||
go Publish(message)
|
||||
|
||||
return ruser, nil
|
||||
}
|
||||
}
|
||||
|
||||
func createUser(user *model.User) (*model.User, *model.AppError) {
|
||||
user.MakeNonNil()
|
||||
|
||||
if err := utils.IsPasswordValid(user.Password); user.AuthService == "" && err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -199,11 +213,6 @@ func CreateUser(user *model.User) (*model.User, *model.AppError) {
|
||||
|
||||
ruser.Sanitize(map[string]bool{})
|
||||
|
||||
// This message goes to everyone, so the teamId, channelId and userId are irrelevant
|
||||
message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_NEW_USER, "", "", "", nil)
|
||||
message.Add("user_id", ruser.Id)
|
||||
go Publish(message)
|
||||
|
||||
return ruser, nil
|
||||
}
|
||||
}
|
||||
@@ -716,7 +725,7 @@ func SanitizeProfile(user *model.User, asAdmin bool) {
|
||||
}
|
||||
|
||||
func UpdateUserAsUser(user *model.User, siteURL string, asAdmin bool) (*model.User, *model.AppError) {
|
||||
updatedUser, err := UpdateUser(user, siteURL)
|
||||
updatedUser, err := UpdateUser(user, siteURL, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -732,36 +741,38 @@ func UpdateUserAsUser(user *model.User, siteURL string, asAdmin bool) (*model.Us
|
||||
return updatedUser, nil
|
||||
}
|
||||
|
||||
func UpdateUser(user *model.User, siteURL string) (*model.User, *model.AppError) {
|
||||
func UpdateUser(user *model.User, siteURL string, sendNotifications bool) (*model.User, *model.AppError) {
|
||||
if result := <-Srv.Store.User().Update(user, false); result.Err != nil {
|
||||
return nil, result.Err
|
||||
} else {
|
||||
rusers := result.Data.([2]*model.User)
|
||||
|
||||
if rusers[0].Email != rusers[1].Email {
|
||||
go func() {
|
||||
if err := SendEmailChangeEmail(rusers[1].Email, rusers[0].Email, rusers[0].Locale, siteURL); err != nil {
|
||||
l4g.Error(err.Error())
|
||||
}
|
||||
}()
|
||||
|
||||
if utils.Cfg.EmailSettings.RequireEmailVerification {
|
||||
if sendNotifications {
|
||||
if rusers[0].Email != rusers[1].Email {
|
||||
go func() {
|
||||
if err := SendEmailChangeVerifyEmail(rusers[0].Id, rusers[0].Email, rusers[0].Locale, siteURL); err != nil {
|
||||
if err := SendEmailChangeEmail(rusers[1].Email, rusers[0].Email, rusers[0].Locale, siteURL); err != nil {
|
||||
l4g.Error(err.Error())
|
||||
}
|
||||
}()
|
||||
|
||||
if utils.Cfg.EmailSettings.RequireEmailVerification {
|
||||
go func() {
|
||||
if err := SendEmailChangeVerifyEmail(rusers[0].Id, rusers[0].Email, rusers[0].Locale, siteURL); err != nil {
|
||||
l4g.Error(err.Error())
|
||||
}
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
||||
if rusers[0].Username != rusers[1].Username {
|
||||
go func() {
|
||||
if err := SendChangeUsernameEmail(rusers[1].Username, rusers[0].Username, rusers[0].Email, rusers[0].Locale, siteURL); err != nil {
|
||||
l4g.Error(err.Error())
|
||||
}
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
||||
if rusers[0].Username != rusers[1].Username {
|
||||
go func() {
|
||||
if err := SendChangeUsernameEmail(rusers[1].Username, rusers[0].Username, rusers[0].Email, rusers[0].Locale, siteURL); err != nil {
|
||||
l4g.Error(err.Error())
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
InvalidateCacheForUser(user.Id)
|
||||
|
||||
return rusers[0], nil
|
||||
@@ -778,7 +789,7 @@ func UpdateUserNotifyProps(userId string, props map[string]string, siteURL strin
|
||||
user.NotifyProps = props
|
||||
|
||||
var ruser *model.User
|
||||
if ruser, err = UpdateUser(user, siteURL); err != nil {
|
||||
if ruser, err = UpdateUser(user, siteURL, true); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
||||
48
i18n/en.json
48
i18n/en.json
@@ -2803,6 +2803,10 @@
|
||||
"id": "app.import.import_line.null_channel.error",
|
||||
"translation": "Import data line has type \"channel\" but the channel object is null."
|
||||
},
|
||||
{
|
||||
"id": "app.import.import_line.null_user.error",
|
||||
"translation": "Import data line has type \"user\" but the user objcet is null."
|
||||
},
|
||||
{
|
||||
"id": "app.import.import_line.unknown_line_type.error",
|
||||
"translation": "Import data line has unknown type \"{{.Type}}\"."
|
||||
@@ -2899,6 +2903,50 @@
|
||||
"id": "app.import.validate_channel_import_data.purpose_length.error",
|
||||
"translation": "Channel purpose is too long."
|
||||
},
|
||||
{
|
||||
"id": "app.import.validate_user_import_data.username_missing.error",
|
||||
"translation": "Missing require user property: username."
|
||||
},
|
||||
{
|
||||
"id": "app.import.validate_user_import_data.username_invalid.error",
|
||||
"translation": "Username is not valid."
|
||||
},
|
||||
{
|
||||
"id": "app.import.validate_user_import_data.email_missing.error",
|
||||
"translation": "Missing required user property: email."
|
||||
},
|
||||
{
|
||||
"id": "app.import.validate_user_import_data.email_length.error",
|
||||
"translation": "User email has an invalid length."
|
||||
},
|
||||
{
|
||||
"id": "app.import.validate_user_import_data.auth_service_length.error",
|
||||
"translation": "User AuthService should not be empty if it is provided."
|
||||
},
|
||||
{
|
||||
"id": "app.import.validate_user_import_data.auth_data_length.error",
|
||||
"translation": "User AuthData is too long."
|
||||
},
|
||||
{
|
||||
"id": "app.import.validate_user_import_data.nickname_length.error",
|
||||
"translation": "User nickname is too long."
|
||||
},
|
||||
{
|
||||
"id": "app.import.validate_user_import_data.first_name_length.error",
|
||||
"translation": "User First Name is too long."
|
||||
},
|
||||
{
|
||||
"id": "app.import.validate_user_import_data.last_name_length.error",
|
||||
"translation": "User Last Name is too long."
|
||||
},
|
||||
{
|
||||
"id": "app.import.validate_user_import_data.position_length.error",
|
||||
"translation": "User Position is too long."
|
||||
},
|
||||
{
|
||||
"id": "app.import.validate_user_import_data.roles_invalid.error",
|
||||
"translation": "User roles are not valid."
|
||||
},
|
||||
{
|
||||
"id": "authentication.permissions.create_team_roles.description",
|
||||
"translation": "Ability to create new teams"
|
||||
|
||||
@@ -22,6 +22,13 @@ const (
|
||||
DEFAULT_LOCALE = "en"
|
||||
USER_AUTH_SERVICE_EMAIL = "email"
|
||||
USER_AUTH_SERVICE_USERNAME = "username"
|
||||
|
||||
USER_EMAIL_MAX_LENGTH = 128
|
||||
USER_NICKNAME_MAX_RUNES = 64
|
||||
USER_POSITION_MAX_RUNES = 35
|
||||
USER_FIRST_NAME_MAX_RUNES = 64
|
||||
USER_LAST_NAME_MAX_RUNES = 64
|
||||
USER_AUTH_DATA_MAX_LENGTH = 128
|
||||
)
|
||||
|
||||
type User struct {
|
||||
@@ -72,27 +79,27 @@ func (u *User) IsValid() *AppError {
|
||||
return NewAppError("User.IsValid", "model.user.is_valid.username.app_error", nil, "user_id="+u.Id, http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if len(u.Email) > 128 || len(u.Email) == 0 {
|
||||
if len(u.Email) > USER_EMAIL_MAX_LENGTH || len(u.Email) == 0 {
|
||||
return NewAppError("User.IsValid", "model.user.is_valid.email.app_error", nil, "user_id="+u.Id, http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if utf8.RuneCountInString(u.Nickname) > 64 {
|
||||
if utf8.RuneCountInString(u.Nickname) > USER_NICKNAME_MAX_RUNES {
|
||||
return NewAppError("User.IsValid", "model.user.is_valid.nickname.app_error", nil, "user_id="+u.Id, http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if utf8.RuneCountInString(u.Position) > 35 {
|
||||
if utf8.RuneCountInString(u.Position) > USER_POSITION_MAX_RUNES {
|
||||
return NewAppError("User.IsValid", "model.user.is_valid.position.app_error", nil, "user_id="+u.Id, http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if utf8.RuneCountInString(u.FirstName) > 64 {
|
||||
if utf8.RuneCountInString(u.FirstName) > USER_FIRST_NAME_MAX_RUNES {
|
||||
return NewAppError("User.IsValid", "model.user.is_valid.first_name.app_error", nil, "user_id="+u.Id, http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if utf8.RuneCountInString(u.LastName) > 64 {
|
||||
if utf8.RuneCountInString(u.LastName) > USER_LAST_NAME_MAX_RUNES {
|
||||
return NewAppError("User.IsValid", "model.user.is_valid.last_name.app_error", nil, "user_id="+u.Id, http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if u.AuthData != nil && len(*u.AuthData) > 128 {
|
||||
if u.AuthData != nil && len(*u.AuthData) > USER_AUTH_DATA_MAX_LENGTH {
|
||||
return NewAppError("User.IsValid", "model.user.is_valid.auth_data.app_error", nil, "user_id="+u.Id, http.StatusBadRequest)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user