Auth: Improve user entity model and add unit tests #98
Signed-off-by: Michael Mayer <michael@photoprism.app>
This commit is contained in:
parent
1942f93bf1
commit
43d6a5e193
8 changed files with 220 additions and 23 deletions
|
@ -81,7 +81,7 @@ func StartImport(router *gin.RouterGroup) {
|
|||
RemoveFromFolderCache(entity.RootImport)
|
||||
|
||||
var destFolder string
|
||||
if destFolder = s.User().UploadPath; destFolder == "" {
|
||||
if destFolder = s.User().GetUploadPath(); destFolder == "" {
|
||||
destFolder = conf.ImportDest()
|
||||
}
|
||||
|
||||
|
|
|
@ -175,7 +175,7 @@ func ProcessUserUpload(router *gin.RouterGroup) {
|
|||
imp := get.Import()
|
||||
|
||||
var destFolder string
|
||||
if destFolder = s.User().UploadPath; destFolder == "" {
|
||||
if destFolder = s.User().GetUploadPath(); destFolder == "" {
|
||||
destFolder = conf.ImportDest()
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ import (
|
|||
"github.com/photoprism/photoprism/internal/event"
|
||||
"github.com/photoprism/photoprism/internal/form"
|
||||
"github.com/photoprism/photoprism/pkg/clean"
|
||||
"github.com/photoprism/photoprism/pkg/list"
|
||||
"github.com/photoprism/photoprism/pkg/rnd"
|
||||
"github.com/photoprism/photoprism/pkg/txt"
|
||||
)
|
||||
|
@ -352,19 +353,49 @@ func (m *User) CanUpload() bool {
|
|||
}
|
||||
}
|
||||
|
||||
// SetBasePath changes the user's base folder.
|
||||
// GetBasePath returns the user's relative base path.
|
||||
func (m *User) GetBasePath() string {
|
||||
return m.BasePath
|
||||
}
|
||||
|
||||
// SetBasePath changes the user's relative base path.
|
||||
func (m *User) SetBasePath(dir string) *User {
|
||||
m.BasePath = clean.UserPath(dir)
|
||||
if list.Contains(list.List{"", ".", "./", "/", "\\"}, dir) {
|
||||
m.BasePath = ""
|
||||
} else if dir == "~" && m.UserUID != "" {
|
||||
m.BasePath = fmt.Sprintf("users/%s", m.UserUID)
|
||||
} else {
|
||||
m.BasePath = clean.UserPath(dir)
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
// SetUploadPath changes the user's upload folder.
|
||||
// GetUploadPath returns the user's relative upload path.
|
||||
func (m *User) GetUploadPath() string {
|
||||
basePath := m.GetBasePath()
|
||||
|
||||
if list.Contains(list.List{"", ".", "./"}, m.UploadPath) {
|
||||
return basePath
|
||||
} else if basePath != "" && strings.HasPrefix(m.UploadPath, basePath+"/") {
|
||||
return m.UploadPath
|
||||
} else if basePath == "" && m.UploadPath == "~" && m.UserUID != "" {
|
||||
return fmt.Sprintf("users/%s", m.UserUID)
|
||||
}
|
||||
|
||||
return path.Join(basePath, m.UploadPath)
|
||||
}
|
||||
|
||||
// SetUploadPath changes the user's relative upload path.
|
||||
func (m *User) SetUploadPath(dir string) *User {
|
||||
if m.BasePath == "" {
|
||||
m.UploadPath = clean.UserPath(dir)
|
||||
basePath := m.GetBasePath()
|
||||
|
||||
if list.Contains(list.List{"", ".", "./", "/", "\\"}, dir) {
|
||||
m.UploadPath = ""
|
||||
} else if basePath == "" && dir == "~" && m.UserUID != "" {
|
||||
m.UploadPath = fmt.Sprintf("users/%s", m.UserUID)
|
||||
} else {
|
||||
m.UploadPath = path.Join(m.BasePath, clean.UserPath(dir))
|
||||
m.UploadPath = clean.UserPath(dir)
|
||||
}
|
||||
|
||||
return m
|
||||
|
@ -432,13 +463,19 @@ func (m *User) Email() string {
|
|||
return clean.Email(m.UserEmail)
|
||||
}
|
||||
|
||||
// Handle returns the user's login handle.
|
||||
func (m *User) Handle() string {
|
||||
handle, _, _ := strings.Cut(m.UserName, "@")
|
||||
return handle
|
||||
}
|
||||
|
||||
// FullName returns the name of the user for display purposes.
|
||||
func (m *User) FullName() string {
|
||||
switch {
|
||||
case m.DisplayName != "":
|
||||
return m.DisplayName
|
||||
default:
|
||||
return m.UserName
|
||||
return clean.NameCapitalized(strings.ReplaceAll(m.Handle(), ".", " "))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -837,19 +874,14 @@ func (m *User) SaveForm(f form.User) error {
|
|||
func (m *User) SetDisplayName(name string) *User {
|
||||
name = clean.Name(name)
|
||||
|
||||
// Empty?
|
||||
if name == "" {
|
||||
d := m.Details()
|
||||
|
||||
if name == "" || SrcPriority[SrcAuto] < SrcPriority[d.NameSrc] {
|
||||
return m
|
||||
}
|
||||
|
||||
m.DisplayName = name
|
||||
|
||||
d := m.Details()
|
||||
|
||||
if SrcPriority[SrcAuto] < SrcPriority[d.NameSrc] {
|
||||
return m
|
||||
}
|
||||
|
||||
// Try to parse name into components.
|
||||
n := txt.ParseName(name)
|
||||
|
||||
|
@ -863,6 +895,18 @@ func (m *User) SetDisplayName(name string) *User {
|
|||
return m
|
||||
}
|
||||
|
||||
// SetGivenName updates the user's given name.
|
||||
func (m *User) SetGivenName(name string) *User {
|
||||
m.Details().SetGivenName(name)
|
||||
return m
|
||||
}
|
||||
|
||||
// SetFamilyName updates the user's family name.
|
||||
func (m *User) SetFamilyName(name string) *User {
|
||||
m.Details().SetFamilyName(name)
|
||||
return m
|
||||
}
|
||||
|
||||
// SetAvatar updates the user avatar image.
|
||||
func (m *User) SetAvatar(thumb, thumbSrc string) error {
|
||||
if m.UserName == "" || m.ID <= 0 {
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/photoprism/photoprism/pkg/clean"
|
||||
"github.com/photoprism/photoprism/pkg/rnd"
|
||||
)
|
||||
|
||||
|
@ -100,3 +101,29 @@ func (m *UserDetails) Save() error {
|
|||
func (m *UserDetails) Updates(values interface{}) error {
|
||||
return UnscopedDb().Model(m).Updates(values).Error
|
||||
}
|
||||
|
||||
// SetGivenName updates the user's given name.
|
||||
func (m *UserDetails) SetGivenName(name string) *UserDetails {
|
||||
name = clean.Name(name)
|
||||
|
||||
if name == "" || SrcPriority[SrcAuto] < SrcPriority[m.NameSrc] {
|
||||
return m
|
||||
}
|
||||
|
||||
m.GivenName = name
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
// SetFamilyName updates the user's family name.
|
||||
func (m *UserDetails) SetFamilyName(name string) *UserDetails {
|
||||
name = clean.Name(name)
|
||||
|
||||
if name == "" || SrcPriority[SrcAuto] < SrcPriority[m.NameSrc] {
|
||||
return m
|
||||
}
|
||||
|
||||
m.FamilyName = name
|
||||
|
||||
return m
|
||||
}
|
||||
|
|
|
@ -838,3 +838,129 @@ func TestUser_Provider(t *testing.T) {
|
|||
assert.Equal(t, "password", Admin.Provider())
|
||||
})
|
||||
}
|
||||
|
||||
func TestUser_GetBasePath(t *testing.T) {
|
||||
t.Run("Visitor", func(t *testing.T) {
|
||||
assert.Equal(t, "", Visitor.GetBasePath())
|
||||
})
|
||||
t.Run("UnknownUser", func(t *testing.T) {
|
||||
assert.Equal(t, "", UnknownUser.GetBasePath())
|
||||
})
|
||||
t.Run("Admin", func(t *testing.T) {
|
||||
assert.Equal(t, "", Admin.GetBasePath())
|
||||
})
|
||||
}
|
||||
|
||||
func TestUser_SetBasePath(t *testing.T) {
|
||||
t.Run("Test", func(t *testing.T) {
|
||||
u := User{
|
||||
ID: 1234567,
|
||||
UserUID: "urqdrfb72479n047",
|
||||
UserName: "test",
|
||||
UserRole: acl.RoleAdmin.String(),
|
||||
DisplayName: "Test",
|
||||
SuperAdmin: false,
|
||||
CanLogin: true,
|
||||
WebDAV: true,
|
||||
CanInvite: false,
|
||||
}
|
||||
|
||||
assert.Equal(t, "base", u.SetBasePath("base").GetBasePath())
|
||||
assert.Equal(t, "users/urqdrfb72479n047", u.SetBasePath("~").GetBasePath())
|
||||
assert.Equal(t, "users/urqdrfb72479n047", u.GetUploadPath())
|
||||
})
|
||||
}
|
||||
|
||||
func TestUser_GetUploadPath(t *testing.T) {
|
||||
t.Run("Visitor", func(t *testing.T) {
|
||||
assert.Equal(t, "", Visitor.GetUploadPath())
|
||||
})
|
||||
t.Run("UnknownUser", func(t *testing.T) {
|
||||
assert.Equal(t, "", UnknownUser.GetUploadPath())
|
||||
})
|
||||
t.Run("Admin", func(t *testing.T) {
|
||||
assert.Equal(t, "", Admin.GetUploadPath())
|
||||
})
|
||||
}
|
||||
|
||||
func TestUser_SetUploadPath(t *testing.T) {
|
||||
t.Run("Test", func(t *testing.T) {
|
||||
u := User{
|
||||
ID: 1234567,
|
||||
UserUID: "urqdrfb72479n047",
|
||||
UserName: "test",
|
||||
UserRole: acl.RoleAdmin.String(),
|
||||
DisplayName: "Test",
|
||||
SuperAdmin: false,
|
||||
CanLogin: true,
|
||||
WebDAV: true,
|
||||
CanInvite: false,
|
||||
}
|
||||
|
||||
assert.Equal(t, "upload", u.SetUploadPath("upload").GetUploadPath())
|
||||
assert.Equal(t, "base/upload", u.SetBasePath("base").GetUploadPath())
|
||||
assert.Equal(t, "base", u.SetUploadPath("~").GetUploadPath())
|
||||
assert.Equal(t, "users/urqdrfb72479n047", u.SetBasePath("~").GetUploadPath())
|
||||
})
|
||||
}
|
||||
|
||||
func TestUser_Handle(t *testing.T) {
|
||||
t.Run("Default", func(t *testing.T) {
|
||||
u := User{
|
||||
ID: 1234567,
|
||||
UserUID: "urqdrfb72479n047",
|
||||
UserName: "mr-happy@cat.com",
|
||||
UserRole: acl.RoleAdmin.String(),
|
||||
DisplayName: "",
|
||||
SuperAdmin: false,
|
||||
CanLogin: true,
|
||||
WebDAV: true,
|
||||
CanInvite: false,
|
||||
}
|
||||
|
||||
assert.Equal(t, "mr-happy@cat.com", u.Login())
|
||||
assert.Equal(t, "mr-happy", u.Handle())
|
||||
|
||||
u.UserName = "mr.happy@cat.com"
|
||||
|
||||
assert.Equal(t, "mr.happy", u.Handle())
|
||||
|
||||
u.UserName = "mr.happy"
|
||||
|
||||
assert.Equal(t, "mr.happy", u.Handle())
|
||||
})
|
||||
}
|
||||
|
||||
func TestUser_FullName(t *testing.T) {
|
||||
t.Run("Default", func(t *testing.T) {
|
||||
u := User{
|
||||
ID: 1234567,
|
||||
UserUID: "urqdrfb72479n047",
|
||||
UserName: "mr-happy@cat.com",
|
||||
UserRole: acl.RoleAdmin.String(),
|
||||
DisplayName: "",
|
||||
SuperAdmin: false,
|
||||
CanLogin: true,
|
||||
WebDAV: true,
|
||||
CanInvite: false,
|
||||
}
|
||||
|
||||
assert.Equal(t, "Mr-Happy", u.FullName())
|
||||
|
||||
u.UserName = "mr.happy@cat.com"
|
||||
|
||||
assert.Equal(t, "Mr Happy", u.FullName())
|
||||
|
||||
u.UserName = "mr.happy"
|
||||
|
||||
assert.Equal(t, "Mr Happy", u.FullName())
|
||||
|
||||
u.UserName = "foo@bar.com"
|
||||
|
||||
assert.Equal(t, "Foo", u.FullName())
|
||||
|
||||
u.SetDisplayName("Jane Doe")
|
||||
|
||||
assert.Equal(t, "Jane Doe", u.FullName())
|
||||
})
|
||||
}
|
||||
|
|
|
@ -65,11 +65,11 @@ func UserAlbums(f form.SearchAlbums, sess *entity.Session) (results AlbumResults
|
|||
if sess.IsVisitor() || sess.NotRegistered() {
|
||||
s = s.Where("albums.album_uid IN (?) OR albums.published_at > ?", sess.SharedUIDs(), entity.TimeStamp())
|
||||
} else if acl.Resources.DenyAll(aclResource, aclRole, acl.Permissions{acl.AccessAll, acl.AccessLibrary}) {
|
||||
if user.BasePath == "" {
|
||||
if basePath := user.GetBasePath(); basePath == "" {
|
||||
s = s.Where("albums.album_uid IN (?) OR albums.created_by = ? OR albums.published_at > ?", sess.SharedUIDs(), user.UserUID, entity.TimeStamp())
|
||||
} else {
|
||||
s = s.Where("albums.album_uid IN (?) OR albums.created_by = ? OR albums.published_at > ? OR albums.album_type = ? AND (albums.album_path = ? OR albums.album_path LIKE ?)",
|
||||
sess.SharedUIDs(), user.UserUID, entity.TimeStamp(), entity.AlbumFolder, user.BasePath, user.BasePath+"/%")
|
||||
sess.SharedUIDs(), user.UserUID, entity.TimeStamp(), entity.AlbumFolder, basePath, basePath+"/%")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -127,11 +127,11 @@ func searchPhotos(f form.SearchPhotos, sess *entity.Session, resultCols string)
|
|||
|
||||
if sess.IsVisitor() || sess.NotRegistered() {
|
||||
s = s.Where(sharedAlbums+"photos.published_at > ?", sess.SharedUIDs(), entity.TimeStamp())
|
||||
} else if user.BasePath == "" {
|
||||
} else if basePath := user.GetBasePath(); basePath == "" {
|
||||
s = s.Where(sharedAlbums+"photos.created_by = ? OR photos.published_at > ?", sess.SharedUIDs(), user.UserUID, entity.TimeStamp())
|
||||
} else {
|
||||
s = s.Where(sharedAlbums+"photos.created_by = ? OR photos.published_at > ? OR photos.photo_path = ? OR photos.photo_path LIKE ?",
|
||||
sess.SharedUIDs(), user.UserUID, entity.TimeStamp(), user.BasePath, user.BasePath+"/%")
|
||||
sess.SharedUIDs(), user.UserUID, entity.TimeStamp(), basePath, basePath+"/%")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -125,11 +125,11 @@ func UserPhotosGeo(f form.SearchPhotosGeo, sess *entity.Session) (results GeoRes
|
|||
|
||||
if sess.IsVisitor() || sess.NotRegistered() {
|
||||
s = s.Where(sharedAlbums+"photos.published_at > ?", sess.SharedUIDs(), entity.TimeStamp())
|
||||
} else if user.BasePath == "" {
|
||||
} else if basePath := user.GetBasePath(); basePath == "" {
|
||||
s = s.Where(sharedAlbums+"photos.created_by = ? OR photos.published_at > ?", sess.SharedUIDs(), user.UserUID, entity.TimeStamp())
|
||||
} else {
|
||||
s = s.Where(sharedAlbums+"photos.created_by = ? OR photos.published_at > ? OR photos.photo_path = ? OR photos.photo_path LIKE ?",
|
||||
sess.SharedUIDs(), user.UserUID, entity.TimeStamp(), user.BasePath, user.BasePath+"/%")
|
||||
sess.SharedUIDs(), user.UserUID, entity.TimeStamp(), basePath, basePath+"/%")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue