func (db *Database) UpsertUser(user *User) error {
	if user.Username == "" {
		return fmt.Errorf("user has no Username")
	}
	if (user.Password != "" || user.PasswordHash != "") && user.UserSource != "" {
		return fmt.Errorf("user has both Password/PasswordHash and UserSource set")
	}
	if len(user.OtherDBRoles) > 0 && db.Name != "admin" && db.Name != "$external" {
		return fmt.Errorf("user with OtherDBRoles is only supported in the admin or $external databases")
	}

	// Attempt to run this using 2.6+ commands.
	rundb := db
	if user.UserSource != "" {
		// Compatibility logic for the userSource field of MongoDB <= 2.4.X
		rundb = db.Session.DB(user.UserSource)
	}
	err := rundb.runUserCmd("updateUser", user)
	// retry with createUser when isAuthError in order to enable the "localhost exception"
	if isNotFound(err) || isAuthError(err) {
		return rundb.runUserCmd("createUser", user)
	}
	if !isNoCmd(err) {
		return err
	}

	// Command does not exist. Fallback to pre-2.6 behavior.
	var set, unset bson.D
	if user.Password != "" {
		psum := md5.New()
		psum.Write([]byte(user.Username + ":mongo:" + user.Password))
		set = append(set, bson.DocElem{"pwd", hex.EncodeToString(psum.Sum(nil))})
		unset = append(unset, bson.DocElem{"userSource", 1})
	} else if user.PasswordHash != "" {
		set = append(set, bson.DocElem{"pwd", user.PasswordHash})
		unset = append(unset, bson.DocElem{"userSource", 1})
	}
	if user.UserSource != "" {
		set = append(set, bson.DocElem{"userSource", user.UserSource})
		unset = append(unset, bson.DocElem{"pwd", 1})
	}
	if user.Roles != nil || user.OtherDBRoles != nil {
		set = append(set, bson.DocElem{"roles", user.Roles})
		if len(user.OtherDBRoles) > 0 {
			set = append(set, bson.DocElem{"otherDBRoles", user.OtherDBRoles})
		} else {
			unset = append(unset, bson.DocElem{"otherDBRoles", 1})
		}
	}
	users := db.C("system.users")
	err = users.Update(bson.D{{"user", user.Username}}, bson.D{{"$unset", unset}, {"$set", set}})
	if err == ErrNotFound {
		set = append(set, bson.DocElem{"user", user.Username})
		if user.Roles == nil && user.OtherDBRoles == nil {
			// Roles must be sent, as it's the way MongoDB distinguishes
			// old-style documents from new-style documents in pre-2.6.
			set = append(set, bson.DocElem{"roles", user.Roles})
		}
		err = users.Insert(set)
	}
	return err
}
func (db *Database) UpsertUser(user *User) error {
	if user.Username == "" {
		return fmt.Errorf("user has no Username")
	}
	if (user.Password != "" || user.PasswordHash != "") && user.UserSource != "" {
		return fmt.Errorf("user has both Password/PasswordHash and UserSource set")
	}
	if len(user.OtherDBRoles) > 0 && db.Name != "admin" && db.Name != "$external" {
		return fmt.Errorf("user with OtherDBRoles is only supported in the admin or $external databases")
	}

	
	rundb := db
	if user.UserSource != "" {
		
		rundb = db.Session.DB(user.UserSource)
	}
	err := rundb.runUserCmd("updateUser", user)
	
	if isNotFound(err) || isAuthError(err) {
		return rundb.runUserCmd("createUser", user)
	}
	if !isNoCmd(err) {
		return err
	}

	
	var set, unset bson.D
	if user.Password != "" {
		psum := md5.New()
		psum.Write([]byte(user.Username + ":mongo:" + user.Password))
		set = append(set, bson.DocElem{"pwd", hex.EncodeToString(psum.Sum(nil))})
		unset = append(unset, bson.DocElem{"userSource", 1})
	} else if user.PasswordHash != "" {
		set = append(set, bson.DocElem{"pwd", user.PasswordHash})
		unset = append(unset, bson.DocElem{"userSource", 1})
	}
	if user.UserSource != "" {
		set = append(set, bson.DocElem{"userSource", user.UserSource})
		unset = append(unset, bson.DocElem{"pwd", 1})
	}
	if user.Roles != nil || user.OtherDBRoles != nil {
		set = append(set, bson.DocElem{"roles", user.Roles})
		if len(user.OtherDBRoles) > 0 {
			set = append(set, bson.DocElem{"otherDBRoles", user.OtherDBRoles})
		} else {
			unset = append(unset, bson.DocElem{"otherDBRoles", 1})
		}
	}
	users := db.C("system.users")
	err = users.Update(bson.D{{"user", user.Username}}, bson.D{{"$unset", unset}, {"$set", set}})
	if err == ErrNotFound {
		set = append(set, bson.DocElem{"user", user.Username})
		if user.Roles == nil && user.OtherDBRoles == nil {
			
			
			set = append(set, bson.DocElem{"roles", user.Roles})
		}
		err = users.Insert(set)
	}
	return err
}
func ( db * Database ) UpsertUser ( user * User ) error { if user . Username == " " { return fmt . Errorf ( " " ) } if ( user . Password != " " || user . PasswordHash != " " ) && user . UserSource != " " { return fmt . Errorf ( " " ) } if len ( user . OtherDBRoles ) > 0 && db . Name != " " && db . Name != " " { return fmt . Errorf ( " " ) } // Attempt to run this using 2.6+ commands. rundb := db if user . UserSource != " " { // Compatibility logic for the userSource field of MongoDB <= 2.4.X rundb = db . Session . DB ( user . UserSource ) } err := rundb . runUserCmd ( " " , user ) // retry with createUser when isAuthError in order to enable the "localhost exception" if isNotFound ( err ) || isAuthError ( err ) { return rundb . runUserCmd ( " " , user ) } if ! isNoCmd ( err ) { return err } // Command does not exist. Fallback to pre-2.6 behavior. var set , unset bson . D if user . Password != " " { psum := md5 . New ( ) psum . Write ( [ ] byte ( user . Username + " " + user . Password ) ) set = append ( set , bson . DocElem { " " , hex . EncodeToString ( psum . Sum ( nil ) ) } ) unset = append ( unset , bson . DocElem { " " , 1 } ) } else if user . PasswordHash != " " { set = append ( set , bson . DocElem { " " , user . PasswordHash } ) unset = append ( unset , bson . DocElem { " " , 1 } ) } if user . UserSource != " " { set = append ( set , bson . DocElem { " " , user . UserSource } ) unset = append ( unset , bson . DocElem { " " , 1 } ) } if user . Roles != nil || user . OtherDBRoles != nil { set = append ( set , bson . DocElem { " " , user . Roles } ) if len ( user . OtherDBRoles ) > 0 { set = append ( set , bson . DocElem { " " , user . OtherDBRoles } ) } else { unset = append ( unset , bson . DocElem { " " , 1 } ) } } users := db . C ( " " ) err = users . Update ( bson . D { { " " , user . Username } } , bson . D { { " " , unset } , { " " , set } } ) if err == ErrNotFound { set = append ( set , bson . DocElem { " " , user . Username } ) if user . Roles == nil && user . OtherDBRoles == nil { // Roles must be sent, as it's the way MongoDB distinguishes // old-style documents from new-style documents in pre-2.6. set = append ( set , bson . DocElem { " " , user . Roles } ) } err = users . Insert ( set ) } return err }
// UpsertUser updates the authentication credentials and the roles for
// a MongoDB user within the db database. If the named user doesn't exist
// it will be created.
//
// This method should only be used from MongoDB 2.4 and on. For older
// MongoDB releases, use the obsolete AddUser method instead.
//
// Relevant documentation:
//
//     http://docs.mongodb.org/manual/reference/user-privileges/
//     http://docs.mongodb.org/manual/reference/privilege-documents/
//
UpsertUser updates the authentication credentials and the roles for a MongoDB user within the db database . If the named user doesn t exist it will be created . This method should only be used from MongoDB 2 . 4 and on . For older MongoDB releases use the obsolete AddUser method instead . Relevant documentation : http : // docs . mongodb . org / manual / reference / user - privileges / http : // docs . mongodb . org / manual / reference / privilege - documents /