Adding migration support to LDAP from other account types (#3655)
Этот коммит содержится в:
коммит произвёл
Joram Wilander
родитель
528890dba0
Коммит
f5375254f9
5
Makefile
5
Makefile
@@ -182,16 +182,19 @@ ifeq ($(BUILD_ENTERPRISE_READY),true)
|
||||
$(GO) test $(GOFLAGS) -run=$(TESTS) -covermode=count -c ./enterprise/compliance && ./compliance.test -test.v -test.timeout=120s -test.coverprofile=ccompliance.out || exit 1
|
||||
$(GO) test $(GOFLAGS) -run=$(TESTS) -covermode=count -c ./enterprise/emoji && ./emoji.test -test.v -test.timeout=120s -test.coverprofile=cemoji.out || exit 1
|
||||
$(GO) test $(GOFLAGS) -run=$(TESTS) -covermode=count -c ./enterprise/saml && ./saml.test -test.v -test.timeout=60s -test.coverprofile=csaml.out || exit 1
|
||||
$(GO) test $(GOFLAGS) -run=$(TESTS) -covermode=count -c ./enterprise/account_migration && ./account_migration.test -test.v -test.timeout=60s -test.coverprofile=caccount_migration.out || exit 1
|
||||
|
||||
tail -n +2 cldap.out >> ecover.out
|
||||
tail -n +2 ccompliance.out >> ecover.out
|
||||
tail -n +2 cemoji.out >> ecover.out
|
||||
tail -n +2 csaml.out >> ecover.out
|
||||
rm -f cldap.out ccompliance.out cemoji.out csaml.out
|
||||
tail -n +2 caccount_migration.out >> ecover.out
|
||||
rm -f cldap.out ccompliance.out cemoji.out csaml.out caccount_migration.out
|
||||
rm -r ldap.test
|
||||
rm -r compliance.test
|
||||
rm -r emoji.test
|
||||
rm -r saml.test
|
||||
rm -r account_migration.test
|
||||
rm -f config/*.crt
|
||||
rm -f config/*.key
|
||||
endif
|
||||
|
||||
@@ -572,11 +572,7 @@ func ldapSyncNow(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
go func() {
|
||||
if utils.IsLicensed && *utils.License.Features.LDAP && *utils.Cfg.LdapSettings.Enable {
|
||||
if ldapI := einterfaces.GetLdapInterface(); ldapI != nil {
|
||||
if err := ldapI.Syncronize(); err != nil {
|
||||
l4g.Error("%v", err.Error())
|
||||
} else {
|
||||
l4g.Info(utils.T("ent.ldap.syncdone.info"))
|
||||
}
|
||||
ldapI.SyncNow()
|
||||
} else {
|
||||
l4g.Error("%v", model.NewLocAppError("saveComplianceReport", "ent.compliance.licence_disable.app_error", nil, "").Error())
|
||||
}
|
||||
|
||||
20
einterfaces/account_migration.go
Обычный файл
20
einterfaces/account_migration.go
Обычный файл
@@ -0,0 +1,20 @@
|
||||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
package einterfaces
|
||||
|
||||
import "github.com/mattermost/platform/model"
|
||||
|
||||
type AccountMigrationInterface interface {
|
||||
MigrateToLdap(fromAuthService string, forignUserFieldNameToMatch string) *model.AppError
|
||||
}
|
||||
|
||||
var theAccountMigrationInterface AccountMigrationInterface
|
||||
|
||||
func RegisterAccountMigrationInterface(newInterface AccountMigrationInterface) {
|
||||
theAccountMigrationInterface = newInterface
|
||||
}
|
||||
|
||||
func GetAccountMigrationInterface() AccountMigrationInterface {
|
||||
return theAccountMigrationInterface
|
||||
}
|
||||
@@ -15,6 +15,8 @@ type LdapInterface interface {
|
||||
ValidateFilter(filter string) *model.AppError
|
||||
Syncronize() *model.AppError
|
||||
StartLdapSyncJob()
|
||||
SyncNow()
|
||||
GetAllLdapUsers() ([]*model.User, *model.AppError)
|
||||
}
|
||||
|
||||
var theLdapInterface LdapInterface
|
||||
|
||||
@@ -2099,6 +2099,14 @@
|
||||
"id": "cli.license.critical",
|
||||
"translation": "Feature requires an enterprise license. Please contact your system administrator about upgrading your enterprise license."
|
||||
},
|
||||
{
|
||||
"id": "ent.migration.migratetoldap.duplicate_field",
|
||||
"translation": "Unable to migrate LDAP users with specified field. Duplicate entry detected. Please remove all duplcates and try again."
|
||||
},
|
||||
{
|
||||
"id": "ent.migration.migratetoldap.user_not_found",
|
||||
"translation": "Unable to find user on LDAP server: "
|
||||
},
|
||||
{
|
||||
"id": "ent.brand.save_brand_image.decode.app_error",
|
||||
"translation": "Unable to decode image."
|
||||
|
||||
@@ -61,6 +61,7 @@ var flagCmdPermanentDeleteTeam bool
|
||||
var flagCmdPermanentDeleteAllUsers bool
|
||||
var flagCmdResetDatabase bool
|
||||
var flagCmdRunLdapSync bool
|
||||
var flagCmdMigrateAccounts bool
|
||||
var flagUsername string
|
||||
var flagCmdUploadLicense bool
|
||||
var flagConfigFile string
|
||||
@@ -73,6 +74,9 @@ var flagSiteURL string
|
||||
var flagConfirmBackup string
|
||||
var flagRole string
|
||||
var flagRunCmds bool
|
||||
var flagFromAuth string
|
||||
var flagToAuth string
|
||||
var flagMatchField string
|
||||
|
||||
func doLoadConfig(filename string) (err string) {
|
||||
defer func() {
|
||||
@@ -288,6 +292,9 @@ func parseCmds() {
|
||||
flag.StringVar(&flagChannelName, "channel_name", "", "")
|
||||
flag.StringVar(&flagSiteURL, "site_url", "", "")
|
||||
flag.StringVar(&flagConfirmBackup, "confirm_backup", "", "")
|
||||
flag.StringVar(&flagFromAuth, "from_auth", "", "")
|
||||
flag.StringVar(&flagToAuth, "to_auth", "", "")
|
||||
flag.StringVar(&flagMatchField, "match_field", "email", "")
|
||||
flag.StringVar(&flagRole, "role", "", "")
|
||||
|
||||
flag.BoolVar(&flagCmdUpdateDb30, "upgrade_db_30", false, "")
|
||||
@@ -311,6 +318,7 @@ func parseCmds() {
|
||||
flag.BoolVar(&flagCmdPermanentDeleteAllUsers, "permanent_delete_all_users", false, "")
|
||||
flag.BoolVar(&flagCmdResetDatabase, "reset_database", false, "")
|
||||
flag.BoolVar(&flagCmdRunLdapSync, "ldap_sync", false, "")
|
||||
flag.BoolVar(&flagCmdMigrateAccounts, "migrate_accounts", false, "")
|
||||
flag.BoolVar(&flagCmdUploadLicense, "upload_license", false, "")
|
||||
|
||||
flag.Parse()
|
||||
@@ -335,6 +343,7 @@ func parseCmds() {
|
||||
flagCmdPermanentDeleteAllUsers ||
|
||||
flagCmdResetDatabase ||
|
||||
flagCmdRunLdapSync ||
|
||||
flagCmdMigrateAccounts ||
|
||||
flagCmdUploadLicense)
|
||||
}
|
||||
|
||||
@@ -359,6 +368,7 @@ func runCmds() {
|
||||
cmdResetDatabase()
|
||||
cmdUploadLicense()
|
||||
cmdRunLdapSync()
|
||||
cmdRunMigrateAccounts()
|
||||
}
|
||||
|
||||
type TeamForUpgrade struct {
|
||||
@@ -1475,6 +1485,44 @@ func cmdRunLdapSync() {
|
||||
}
|
||||
}
|
||||
|
||||
func cmdRunMigrateAccounts() {
|
||||
if flagCmdMigrateAccounts {
|
||||
if len(flagFromAuth) == 0 || (flagFromAuth != "email" && flagFromAuth != "gitlab" && flagFromAuth != "saml") {
|
||||
fmt.Fprintln(os.Stderr, "flag needs an argument: -from_auth")
|
||||
flag.Usage()
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if len(flagToAuth) == 0 || flagToAuth != "ldap" {
|
||||
fmt.Fprintln(os.Stderr, "flag needs an argument: -from_auth")
|
||||
flag.Usage()
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Email auth in Mattermost system is represented by ""
|
||||
if flagFromAuth == "email" {
|
||||
flagFromAuth = ""
|
||||
}
|
||||
|
||||
if len(flagMatchField) == 0 || (flagMatchField != "email" && flagMatchField != "username") {
|
||||
fmt.Fprintln(os.Stderr, "flag needs an argument: -match_field")
|
||||
flag.Usage()
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if migrate := einterfaces.GetAccountMigrationInterface(); migrate != nil {
|
||||
if err := migrate.MigrateToLdap(flagFromAuth, flagMatchField); err != nil {
|
||||
fmt.Println("ERROR: Account migration failed.")
|
||||
l4g.Error("%v", err.Error())
|
||||
flushLogAndExit(1)
|
||||
} else {
|
||||
fmt.Println("SUCCESS: Account migration complete.")
|
||||
flushLogAndExit(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func cmdUploadLicense() {
|
||||
if flagCmdUploadLicense {
|
||||
if model.BuildEnterpriseReady != "true" {
|
||||
@@ -1651,6 +1699,11 @@ COMMANDS:
|
||||
|
||||
Example:
|
||||
platform -upload_license -license="/path/to/license/example.mattermost-license"
|
||||
|
||||
-migrate_accounts Migrates accounts from one authentication provider to anouther. Requires -from_auth -to_auth and -match_field flags. Supported options for -from_auth: email, gitlab, saml. Supported options for -to_auth ldap. Supported options for -match_field email, username. Will display any accounts that are not migrated succesfully.
|
||||
|
||||
Example:
|
||||
platform -migrate_accounts -from_auth email -to_auth ldap -match_field username
|
||||
|
||||
-upgrade_db_30 Upgrades the database from a version 2.x schema to version 3 see
|
||||
http://www.mattermost.org/upgrading-to-mattermost-3-0/
|
||||
|
||||
@@ -84,6 +84,12 @@ func (task *ScheduledTask) Cancel() {
|
||||
removeTaskByName(task.Name)
|
||||
}
|
||||
|
||||
// Executes the task immediatly. A recurring task will be run regularally after interval.
|
||||
func (task *ScheduledTask) Execute() {
|
||||
task.function()
|
||||
task.timer.Reset(task.Interval)
|
||||
}
|
||||
|
||||
func (task *ScheduledTask) String() string {
|
||||
return fmt.Sprintf(
|
||||
"%s\nInterval: %s\nRecurring: %t\n",
|
||||
|
||||
@@ -126,3 +126,63 @@ func TestGetAllTasks(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestExecuteTask(t *testing.T) {
|
||||
TASK_NAME := "Test Task"
|
||||
TASK_TIME := time.Second * 5
|
||||
|
||||
testValue := 0
|
||||
testFunc := func() {
|
||||
testValue += 1
|
||||
}
|
||||
|
||||
task := CreateTask(TASK_NAME, testFunc, TASK_TIME)
|
||||
if testValue != 0 {
|
||||
t.Fatal("Unexpected execuition of task")
|
||||
}
|
||||
|
||||
task.Execute()
|
||||
|
||||
if testValue != 1 {
|
||||
t.Fatal("Task did not execute")
|
||||
}
|
||||
|
||||
time.Sleep(TASK_TIME + time.Second)
|
||||
|
||||
if testValue != 2 {
|
||||
t.Fatal("Task re-executed")
|
||||
}
|
||||
}
|
||||
|
||||
func TestExecuteTaskRecurring(t *testing.T) {
|
||||
TASK_NAME := "Test Recurring Task"
|
||||
TASK_TIME := time.Second * 5
|
||||
|
||||
testValue := 0
|
||||
testFunc := func() {
|
||||
testValue += 1
|
||||
}
|
||||
|
||||
task := CreateRecurringTask(TASK_NAME, testFunc, TASK_TIME)
|
||||
if testValue != 0 {
|
||||
t.Fatal("Unexpected execuition of task")
|
||||
}
|
||||
|
||||
time.Sleep(time.Second * 3)
|
||||
|
||||
task.Execute()
|
||||
if testValue != 1 {
|
||||
t.Fatal("Task did not execute")
|
||||
}
|
||||
|
||||
time.Sleep(time.Second * 3)
|
||||
if testValue != 1 {
|
||||
t.Fatal("Task should not have executed before 5 seconds")
|
||||
}
|
||||
|
||||
time.Sleep(time.Second * 3)
|
||||
|
||||
if testValue != 2 {
|
||||
t.Fatal("Task did not re-execute after forced execution")
|
||||
}
|
||||
}
|
||||
|
||||
Ссылка в новой задаче
Block a user