84 lines
1.7 KiB
Go
84 lines
1.7 KiB
Go
|
|
package state
|
||
|
|
|
||
|
|
import (
|
||
|
|
"crypto/rand"
|
||
|
|
"crypto/sha256"
|
||
|
|
"crypto/subtle"
|
||
|
|
"encoding/hex"
|
||
|
|
"fmt"
|
||
|
|
"sort"
|
||
|
|
"strings"
|
||
|
|
"time"
|
||
|
|
"unicode"
|
||
|
|
)
|
||
|
|
|
||
|
|
func randomHex(bytes int) string {
|
||
|
|
buf := make([]byte, bytes)
|
||
|
|
_, _ = rand.Read(buf)
|
||
|
|
return hex.EncodeToString(buf)
|
||
|
|
}
|
||
|
|
|
||
|
|
func newUUIDv4() string {
|
||
|
|
buf := make([]byte, 16)
|
||
|
|
_, _ = rand.Read(buf)
|
||
|
|
buf[6] = (buf[6] & 0x0f) | 0x40
|
||
|
|
buf[8] = (buf[8] & 0x3f) | 0x80
|
||
|
|
|
||
|
|
return fmt.Sprintf("%x-%x-%x-%x-%x", buf[0:4], buf[4:6], buf[6:8], buf[8:10], buf[10:16])
|
||
|
|
}
|
||
|
|
|
||
|
|
func normalizeName(input string, max int) string {
|
||
|
|
trimmed := strings.TrimSpace(input)
|
||
|
|
if trimmed == "" {
|
||
|
|
return ""
|
||
|
|
}
|
||
|
|
|
||
|
|
builder := strings.Builder{}
|
||
|
|
for _, r := range trimmed {
|
||
|
|
if r == '\n' || r == '\r' || r == '\t' {
|
||
|
|
continue
|
||
|
|
}
|
||
|
|
if unicode.IsPrint(r) {
|
||
|
|
builder.WriteRune(r)
|
||
|
|
}
|
||
|
|
if builder.Len() >= max {
|
||
|
|
break
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return strings.TrimSpace(builder.String())
|
||
|
|
}
|
||
|
|
|
||
|
|
func normalizeCard(input string) string {
|
||
|
|
return normalizeName(input, 8)
|
||
|
|
}
|
||
|
|
|
||
|
|
func hashPassword(password, salt string) string {
|
||
|
|
h := sha256.Sum256([]byte(salt + ":" + password))
|
||
|
|
return hex.EncodeToString(h[:])
|
||
|
|
}
|
||
|
|
|
||
|
|
func passwordMatches(password, salt, expectedHash string) bool {
|
||
|
|
computed := hashPassword(password, salt)
|
||
|
|
return subtle.ConstantTimeCompare([]byte(computed), []byte(expectedHash)) == 1
|
||
|
|
}
|
||
|
|
|
||
|
|
func nowUTC() time.Time {
|
||
|
|
return time.Now().UTC()
|
||
|
|
}
|
||
|
|
|
||
|
|
func sortParticipants(participants map[string]*Participant) []*Participant {
|
||
|
|
list := make([]*Participant, 0, len(participants))
|
||
|
|
for _, participant := range participants {
|
||
|
|
list = append(list, participant)
|
||
|
|
}
|
||
|
|
|
||
|
|
sort.SliceStable(list, func(i, j int) bool {
|
||
|
|
if list[i].JoinedAt.Equal(list[j].JoinedAt) {
|
||
|
|
return list[i].Username < list[j].Username
|
||
|
|
}
|
||
|
|
return list[i].JoinedAt.Before(list[j].JoinedAt)
|
||
|
|
})
|
||
|
|
|
||
|
|
return list
|
||
|
|
}
|