Newly created access tokens are now lowercase only
parent
ae3e8a0094
commit
e96e35b40b
|
@ -1227,6 +1227,7 @@ and the [ntfy Android app](https://github.com/binwiederhier/ntfy-android/release
|
||||||
* Support encoding any header as RFC 2047 ([#737](https://github.com/binwiederhier/ntfy/issues/737), thanks to [@cfouche3005](https://github.com/cfouche3005) for reporting)
|
* Support encoding any header as RFC 2047 ([#737](https://github.com/binwiederhier/ntfy/issues/737), thanks to [@cfouche3005](https://github.com/cfouche3005) for reporting)
|
||||||
* Do not forward poll requests for UnifiedPush messages (no ticket, thanks to NoName for reporting)
|
* Do not forward poll requests for UnifiedPush messages (no ticket, thanks to NoName for reporting)
|
||||||
* Fix `ntfy pub %` segfaulting ([#760](https://github.com/binwiederhier/ntfy/issues/760), thanks to [@clesmian](https://github.com/clesmian) for reporting)
|
* Fix `ntfy pub %` segfaulting ([#760](https://github.com/binwiederhier/ntfy/issues/760), thanks to [@clesmian](https://github.com/clesmian) for reporting)
|
||||||
|
* Newly created access tokens are now lowercase only to fully support `<topic>+<token>@<domain>` email syntax ([#773](https://github.com/binwiederhier/ntfy/issues/773), thanks to gingervitiz for reporting)
|
||||||
|
|
||||||
**Maintenance:**
|
**Maintenance:**
|
||||||
|
|
||||||
|
|
|
@ -508,7 +508,7 @@ func (a *Manager) AuthenticateToken(token string) (*User, error) {
|
||||||
// after a fixed duration unless ChangeToken is called. This function also prunes tokens for the
|
// after a fixed duration unless ChangeToken is called. This function also prunes tokens for the
|
||||||
// given user, if there are too many of them.
|
// given user, if there are too many of them.
|
||||||
func (a *Manager) CreateToken(userID, label string, expires time.Time, origin netip.Addr) (*Token, error) {
|
func (a *Manager) CreateToken(userID, label string, expires time.Time, origin netip.Addr) (*Token, error) {
|
||||||
token := util.RandomStringPrefix(tokenPrefix, tokenLength)
|
token := util.RandomLowerStringPrefix(tokenPrefix, tokenLength) // Lowercase only to support "<topic>+<token>@<domain>" email addresses
|
||||||
tx, err := a.db.Begin()
|
tx, err := a.db.Begin()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -183,6 +183,19 @@ func TestManager_MarkUserRemoved_RemoveDeletedUsers(t *testing.T) {
|
||||||
require.Equal(t, ErrUserNotFound, err)
|
require.Equal(t, ErrUserNotFound, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestManager_CreateToken_Only_Lower(t *testing.T) {
|
||||||
|
a := newTestManager(t, PermissionDenyAll)
|
||||||
|
|
||||||
|
// Create user, add reservations and token
|
||||||
|
require.Nil(t, a.AddUser("user", "pass", RoleAdmin))
|
||||||
|
u, err := a.User("user")
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
token, err := a.CreateToken(u.ID, "", time.Now().Add(time.Hour), netip.IPv4Unspecified())
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Equal(t, token.Value, strings.ToLower(token.Value))
|
||||||
|
}
|
||||||
|
|
||||||
func TestManager_UserManagement(t *testing.T) {
|
func TestManager_UserManagement(t *testing.T) {
|
||||||
a := newTestManager(t, PermissionDenyAll)
|
a := newTestManager(t, PermissionDenyAll)
|
||||||
require.Nil(t, a.AddUser("phil", "phil", RoleAdmin))
|
require.Nil(t, a.AddUser("phil", "phil", RoleAdmin))
|
||||||
|
|
14
util/util.go
14
util/util.go
|
@ -23,7 +23,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
randomStringCharset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
randomStringCharset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
||||||
|
randomStringLowerCaseCharset = "abcdefghijklmnopqrstuvwxyz0123456789"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -112,11 +113,20 @@ func RandomString(length int) string {
|
||||||
|
|
||||||
// RandomStringPrefix returns a random string with a given length, with a prefix
|
// RandomStringPrefix returns a random string with a given length, with a prefix
|
||||||
func RandomStringPrefix(prefix string, length int) string {
|
func RandomStringPrefix(prefix string, length int) string {
|
||||||
|
return randomStringPrefixWithCharset(prefix, length, randomStringCharset)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RandomLowerStringPrefix returns a random lowercase-only string with a given length, with a prefix
|
||||||
|
func RandomLowerStringPrefix(prefix string, length int) string {
|
||||||
|
return randomStringPrefixWithCharset(prefix, length, randomStringLowerCaseCharset)
|
||||||
|
}
|
||||||
|
|
||||||
|
func randomStringPrefixWithCharset(prefix string, length int, charset string) string {
|
||||||
randomMutex.Lock() // Who would have thought that random.Intn() is not thread-safe?!
|
randomMutex.Lock() // Who would have thought that random.Intn() is not thread-safe?!
|
||||||
defer randomMutex.Unlock()
|
defer randomMutex.Unlock()
|
||||||
b := make([]byte, length-len(prefix))
|
b := make([]byte, length-len(prefix))
|
||||||
for i := range b {
|
for i := range b {
|
||||||
b[i] = randomStringCharset[random.Intn(len(randomStringCharset))]
|
b[i] = charset[random.Intn(len(charset))]
|
||||||
}
|
}
|
||||||
return prefix + string(b)
|
return prefix + string(b)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue