Auth: Improve username validation and parsing

Signed-off-by: Michael Mayer <michael@photoprism.app>
This commit is contained in:
Michael Mayer 2023-03-14 16:36:30 +01:00
parent 9762150da6
commit 9ab833c2ec
4 changed files with 32 additions and 9 deletions

View file

@ -112,6 +112,15 @@ export class User extends RestModel {
};
}
getHandle() {
if (!this.Name) {
return "";
}
const s = this.Name.split("@");
return s[0].trim();
}
getDisplayName() {
if (this.DisplayName) {
return this.DisplayName;

View file

@ -429,11 +429,11 @@ func (m *User) CanUpload() bool {
// DefaultBasePath returns the default base path of the user based on the user name.
func (m *User) DefaultBasePath() string {
if m.UserName == "" {
if s := m.Handle(); s == "" {
return ""
} else {
return fmt.Sprintf("users/%s", s)
}
return fmt.Sprintf("users/%s", m.UserName)
}
// GetBasePath returns the user's relative base path.
@ -591,8 +591,7 @@ func (m *User) Email() string {
// Handle returns the user's login handle.
func (m *User) Handle() string {
handle, _, _ := strings.Cut(m.UserName, "@")
return handle
return clean.Handle(m.UserName)
}
// FullName returns the name of the user for display purposes.

View file

@ -12,13 +12,16 @@ var EmailRegexp = regexp.MustCompile("^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0
// Handle returns the sanitized username with trimmed whitespace and in lowercase.
func Handle(s string) string {
s, _, _ = strings.Cut(s, "@")
s = strings.TrimSpace(s)
// Remove unwanted characters.
s = strings.Map(func(r rune) rune {
if r <= 42 || r == 127 {
if r <= 31 || r == 127 {
return -1
}
switch r {
case '`', '~', '?', '|', '*', '\\', '%', '$', '@', ':', ';', '<', '>', '{', '}':
case '"', '\'', '(', ')', '#', '&', '$', ',', '+', '=', '`', '~', '?', '|', '*', '\\', '/', ':', ';', '<', '>', '{', '}':
return -1
}
return r
@ -42,7 +45,7 @@ func Username(s string) string {
return -1
}
switch r {
case '"', ',', '+', '=', '`', '~', '?', '|', '*', '\\', ':', ';', '<', '>', '{', '}':
case '"', '\'', '(', ')', '#', '&', '$', ',', '+', '=', '`', '~', '?', '|', '*', '\\', '/', ':', ';', '<', '>', '{', '}':
return -1
}
return r

View file

@ -11,11 +11,17 @@ func TestHandle(t *testing.T) {
assert.Equal(t, "admin", Handle("Admin "))
})
t.Run(" Admin ", func(t *testing.T) {
assert.Equal(t, "adminfoo", Handle(" Admin@foo "))
assert.Equal(t, "admin", Handle(" Admin@foo "))
})
t.Run(" Admin ", func(t *testing.T) {
assert.Equal(t, "admin foo", Handle(" Admin foo "))
})
t.Run(" admin ", func(t *testing.T) {
assert.Equal(t, "admin", Handle(" admin "))
})
t.Run("admin/user", func(t *testing.T) {
assert.Equal(t, "adminuser", Handle("admin/user"))
})
}
func TestUsername(t *testing.T) {
@ -25,9 +31,15 @@ func TestUsername(t *testing.T) {
t.Run(" Admin ", func(t *testing.T) {
assert.Equal(t, "admin@foo", Username(" Admin@foo "))
})
t.Run(" Admin ", func(t *testing.T) {
assert.Equal(t, "admin foo", Username(" Admin foo "))
})
t.Run(" admin ", func(t *testing.T) {
assert.Equal(t, "admin", Username(" admin "))
})
t.Run("admin/user", func(t *testing.T) {
assert.Equal(t, "adminuser", Username("admin/user"))
})
}
func TestEmail(t *testing.T) {