// Generate a new secure storage minimal file that includes the root user with
// basic Account Management: the root user privilege and password
func createBasicFile(stFilePath string, name string, pass string, key []byte) {
	saltStr, _ := salt.GetRandomSalt(saltLen)
	_, err := salt.GenerateSaltedPassword([]byte(pass), password.MinPasswordLength, password.MaxPasswordLength, saltStr, -1)
	if err != nil {
		log.Fatalf("Error: can't generate salted password for '%v' user, error: %v", name, err)
	}
	ul := en.New()
	ul.AddUser(name)
	amUser, _ := am.NewUserAm(am.SuperUserPermission, []byte(pass), saltStr, true)
	ul.AddPropertyToEntity(name, defs.AmPropertyName, amUser)
	ul.StoreInfo(stFilePath, key, false)
}
// NewStorage : Create a new storage using the given secret
func NewStorage(secret []byte, checkSecretStrength bool) (*SecureStorage, error) {
	err := isValidData(secret)
	if err != nil {
		return nil, err
	}
	err = isSecretStrengthOk(string(secret))
	if err != nil && checkSecretStrength {
		return nil, err
	}
	saltData, _ := salt.GetRandomSalt(SaltLen)
	pass := getSaltedPass(secret, saltData)
	s := SecureStorage{Data: make(SecureDataMap), secret: pass, Salt: saltData, Version: version}
	return &s, nil
}
func getRandomSaltExample(secret []byte, saltLen int, iter int, f func() hash.Hash, size int) ([]byte, []byte, error) {
	salting, _ := salt.GetRandomSalt(saltLen)
	mySalt, err := salt.NewSalt(secret, minSecretLen, maxSecretLen, salting)
	if err != nil {
		return nil, nil, err
	}
	mySalt.Iterations = iter
	mySalt.OutputLen = size
	mySalt.Digest = f
	res, err := mySalt.Generate(minSecretLen, maxSecretLen)
	if err != nil {
		return nil, nil, err
	} else {
		return res, salting, nil
	}
}
func (l AmRestful) restAddAm(request *restful.Request, response *restful.Response) {
	name := request.PathParameter(userIDParam)

	privilege := l.getPrivilegePwd(request, response)
	if privilege == nil {
		return
	}
	saltStr, _ := salt.GetRandomSalt(saltLen)

	data, err := am.NewUserAm(privilege.Privilege, []byte(privilege.Password), saltStr, checkPasswordStrength)
	if err != nil {
		l.setError(response, http.StatusBadRequest, err)
		return
	}
	err = l.st.UsersList.AddPropertyToEntity(name, defs.AmPropertyName, data)
	if err != nil {
		l.setError(response, http.StatusNotFound, err)
		return
	}
	response.WriteHeaderAndEntity(http.StatusCreated, l.getURLPath(request, name))
}
// This example shows how to generate a randomly salted secret contain 8 characters, using hash function of md5 and 3 iterations of calculations
func ExampleGetRandomSalt() {
	iter := 3
	f := md5.New
	size := 8
	saltLen := 32

	randSalt, _ := salt.GetRandomSalt(saltLen)
	mySalt, err := salt.NewSalt(BasicSecret, minSecretLen, maxSecretLen, randSalt)
	if err != nil {
		fmt.Println("Error while creating the new salt structure:", err)
	}
	mySalt.Iterations = iter
	mySalt.OutputLen = size
	mySalt.Digest = f
	res, err := mySalt.Generate(minSecretLen, maxSecretLen)
	if err != nil {
		fmt.Println("GetRandomSaltExample failed with error:", err)
	} else {
		fmt.Println("* Salted password of secret key:", string(BasicSecret), ",random salt length:", saltLen, randSalt,
			"with", iter, "iterations, output password length:", size, "bytes and MD5 function is:", res)
	}
}
// Example of how to use the reset password function:
// This function resets the current password,
// selects a new password with short expiration time
// and lets the user use it exactly once
func ExampleUserPwd_ResetPassword() {
	id := "User1"
	pwd := []byte("a1b2C@3d4")

	saltStr, _ := salt.GetRandomSalt(10)
	userPwd, _ := password.NewUserPwd(pwd, saltStr, false)
	tmpPwd, _ := userPwd.ResetPassword()
	tPwd, _ := salt.GenerateSaltedPassword(tmpPwd, 1, 100, saltStr, -1)
	newPwd := password.GetHashedPwd(tPwd)
	err := userPwd.IsPasswordMatch(newPwd)
	if err != nil {
		fmt.Printf("Check of newly generated password '%v' for user %v failed, error %v\n", newPwd, id, err)
	} else {
		fmt.Printf("Entity %v, after resetting password '%v' verified successfully\n", id, newPwd)
	}
	err = userPwd.IsPasswordMatch(newPwd)
	if err == nil {
		fmt.Printf("Error: Newly generated password '%v' could be used only once\n", newPwd)
	} else {
		fmt.Printf("Newly generated password '%v', for entity %v, can only be used once\n", newPwd, id)
	}
}
// Example of how to use the password.
// 1. Create a new password.
// 2. Verify that the initial password is set correctly
// 3. Change the user's password
// 4. Verify that the old password is not valid anymore
// 5. Verify that the new password is valid
// 6. Verify that the old password can't be used any more
//     (at least not as long as it remains in the old passwords list)
func ExampleUserPwd() {
	id := "User-1"
	pwd := []byte("a1B2c3d^@")
	saltStr, _ := salt.GetRandomSalt(8)

	userPwd, _ := password.NewUserPwd(pwd, saltStr, true)
	tPwd, _ := salt.GenerateSaltedPassword(pwd, minPasswordLength, maxPasswordLength, saltStr, -1)
	newPwd := password.GetHashedPwd(tPwd)
	err := userPwd.IsPasswordMatch(newPwd)
	if err != nil {
		fmt.Println("Error", err)
	}
	userNewPwd := []byte(string(pwd) + "a")
	newPwd, err = userPwd.UpdatePassword(userPwd.Password, userNewPwd, true)
	if err != nil {
		fmt.Printf("Password update for user %v to new password '%v' (%v) failed, error %v\n", id, newPwd, string(userNewPwd), err)
	} else {
		fmt.Printf("User '%v', updated password to '%v' (%v)\n", id, newPwd, string(userNewPwd))
	}
	err = userPwd.IsPasswordMatch(newPwd)
	if err != nil {
		fmt.Printf("Check of the new password, '%v' (%v), for user %v failed, error %v\n", newPwd, string(userNewPwd), id, err)
	} else {
		fmt.Printf("User '%v', new password '%v' (%v) verified successfully\n", id, newPwd, string(userNewPwd))
	}
	err = userPwd.IsPasswordMatch(pwd)
	if err == nil {
		fmt.Printf("Error: Old password '%v' (%v) for user %v accepted\n", pwd, string(pwd), id)
	} else {
		fmt.Printf("User '%v', Note that the old password '%v' (%v) cannot be used anymore\n", id, pwd, string(pwd))
	}
	newPwd, err = userPwd.UpdatePassword(userPwd.Password, pwd, true)
	if err == nil {
		fmt.Printf("Error: Password '%v' (typed password %v) for user %v was already used\n", newPwd, string(pwd), id)
	} else {
		fmt.Printf("Entity '%v'. Note that the old password (entered password) %v was already used\n", id, string(pwd))
	}
}
// NewPwdRestful : return a pointer to the PwdRestful structure
func NewPwdRestful() *PwdRestful {
	saltStr, _ := salt.GetRandomSalt(saltLen)
	return &PwdRestful{nil, saltStr}
}