mirror of
https://github.com/mattermost/mattermost.git
synced 2025-02-25 18:55:24 -06:00
[MM-29296] model/user: add lock to source (#16054)
* model/user: add lock to source * guard rand creation with locking * use locked random * remove assignment Co-authored-by: Mattermod <mattermod@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
50e29cb47a
commit
b30acfdee6
@@ -14,6 +14,7 @@ import (
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
|
||||
@@ -890,7 +891,22 @@ func UsersWithGroupsAndCountFromJson(data io.Reader) *UsersWithGroupsAndCount {
|
||||
return uwg
|
||||
}
|
||||
|
||||
var passwordRandomSource = rand.NewSource(time.Now().Unix())
|
||||
type lockedRand struct {
|
||||
mu sync.Mutex
|
||||
rn *rand.Rand
|
||||
}
|
||||
|
||||
func (r *lockedRand) Intn(n int) int {
|
||||
r.mu.Lock()
|
||||
m := r.rn.Intn(n)
|
||||
r.mu.Unlock()
|
||||
return m
|
||||
}
|
||||
|
||||
var passwordRandom = lockedRand{
|
||||
rn: rand.New(rand.NewSource(time.Now().Unix())),
|
||||
}
|
||||
|
||||
var passwordSpecialChars = "!$%^&*(),."
|
||||
var passwordNumbers = "0123456789"
|
||||
var passwordUpperCaseLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
@@ -898,16 +914,14 @@ var passwordLowerCaseLetters = "abcdefghijklmnopqrstuvwxyz"
|
||||
var passwordAllChars = passwordSpecialChars + passwordNumbers + passwordUpperCaseLetters + passwordLowerCaseLetters
|
||||
|
||||
func GeneratePassword(minimumLength int) string {
|
||||
r := rand.New(passwordRandomSource)
|
||||
|
||||
// Make sure we are guaranteed at least one of each type to meet any possible password complexity requirements.
|
||||
password := string([]rune(passwordUpperCaseLetters)[r.Intn(len(passwordUpperCaseLetters))]) +
|
||||
string([]rune(passwordNumbers)[r.Intn(len(passwordNumbers))]) +
|
||||
string([]rune(passwordLowerCaseLetters)[r.Intn(len(passwordLowerCaseLetters))]) +
|
||||
string([]rune(passwordSpecialChars)[r.Intn(len(passwordSpecialChars))])
|
||||
password := string([]rune(passwordUpperCaseLetters)[passwordRandom.Intn(len(passwordUpperCaseLetters))]) +
|
||||
string([]rune(passwordNumbers)[passwordRandom.Intn(len(passwordNumbers))]) +
|
||||
string([]rune(passwordLowerCaseLetters)[passwordRandom.Intn(len(passwordLowerCaseLetters))]) +
|
||||
string([]rune(passwordSpecialChars)[passwordRandom.Intn(len(passwordSpecialChars))])
|
||||
|
||||
for len(password) < minimumLength {
|
||||
i := r.Intn(len(passwordAllChars))
|
||||
i := passwordRandom.Intn(len(passwordAllChars))
|
||||
password = password + string([]rune(passwordAllChars)[i])
|
||||
}
|
||||
|
||||
|
||||
@@ -353,7 +353,9 @@ func TestUserSlice(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGeneratePassword(t *testing.T) {
|
||||
passwordRandomSource = rand.NewSource(12345)
|
||||
passwordRandom = lockedRand{
|
||||
rn: rand.New(rand.NewSource(12345)),
|
||||
}
|
||||
|
||||
t.Run("Should be the minimum length or 4, whichever is less", func(t *testing.T) {
|
||||
password1 := GeneratePassword(5)
|
||||
@@ -372,4 +374,10 @@ func TestGeneratePassword(t *testing.T) {
|
||||
assert.Contains(t, []rune(passwordLowerCaseLetters), []rune(password)[2])
|
||||
assert.Contains(t, []rune(passwordSpecialChars), []rune(password)[3])
|
||||
})
|
||||
|
||||
t.Run("Should not fail on concurrent calls", func(t *testing.T) {
|
||||
for i := 0; i < 10; i++ {
|
||||
go GeneratePassword(10)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user