Auth: Add "node" and "portal" roles, refactor session entity #98

Signed-off-by: Michael Mayer <michael@photoprism.app>
This commit is contained in:
Michael Mayer
2025-09-18 13:33:18 +02:00
parent 2a116cffb3
commit 887a39e7d9
42 changed files with 297 additions and 266 deletions

View File

@@ -70,7 +70,7 @@ func GetAlbum(router *gin.RouterGroup) {
}
// Other restricted users can only access their own or shared content.
if s.User().HasSharedAccessOnly(acl.ResourceAlbums) && album.CreatedBy != s.UserUID && !s.HasShare(uid) {
if s.GetUser().HasSharedAccessOnly(acl.ResourceAlbums) && album.CreatedBy != s.UserUID && !s.HasShare(uid) {
AbortForbidden(c)
return
}
@@ -171,7 +171,7 @@ func UpdateAlbum(router *gin.RouterGroup) {
uid := clean.UID(c.Param("uid"))
// Visitors and other restricted users can only access shared content.
if (s.User().HasSharedAccessOnly(acl.ResourceAlbums) || s.NotRegistered()) && !s.HasShare(uid) {
if (s.GetUser().HasSharedAccessOnly(acl.ResourceAlbums) || s.NotRegistered()) && !s.HasShare(uid) {
AbortForbidden(c)
return
}
@@ -242,7 +242,7 @@ func DeleteAlbum(router *gin.RouterGroup) {
uid := clean.UID(c.Param("uid"))
// Visitors and other restricted users can only access shared content.
if (s.User().HasSharedAccessOnly(acl.ResourceAlbums) || s.NotRegistered()) && !s.HasShare(uid) {
if (s.GetUser().HasSharedAccessOnly(acl.ResourceAlbums) || s.NotRegistered()) && !s.HasShare(uid) {
AbortForbidden(c)
return
}
@@ -317,7 +317,7 @@ func LikeAlbum(router *gin.RouterGroup) {
uid := clean.UID(c.Param("uid"))
// Visitors and other restricted users can only access shared content.
if (s.User().HasSharedAccessOnly(acl.ResourceAlbums) || s.NotRegistered()) && !s.HasShare(uid) {
if (s.GetUser().HasSharedAccessOnly(acl.ResourceAlbums) || s.NotRegistered()) && !s.HasShare(uid) {
AbortForbidden(c)
return
}
@@ -368,7 +368,7 @@ func DislikeAlbum(router *gin.RouterGroup) {
uid := clean.UID(c.Param("uid"))
// Visitors and other restricted users can only access shared content.
if (s.User().HasSharedAccessOnly(acl.ResourceAlbums) || s.NotRegistered()) && !s.HasShare(uid) {
if (s.GetUser().HasSharedAccessOnly(acl.ResourceAlbums) || s.NotRegistered()) && !s.HasShare(uid) {
AbortForbidden(c)
return
}
@@ -421,7 +421,7 @@ func CloneAlbums(router *gin.RouterGroup) {
uid := clean.UID(c.Param("uid"))
// Visitors and other restricted users can only access shared content.
if (s.User().HasSharedAccessOnly(acl.ResourceAlbums) || s.NotRegistered()) && !s.HasShare(uid) {
if (s.GetUser().HasSharedAccessOnly(acl.ResourceAlbums) || s.NotRegistered()) && !s.HasShare(uid) {
AbortForbidden(c)
return
}
@@ -507,7 +507,7 @@ func AddPhotosToAlbum(router *gin.RouterGroup) {
uid := clean.UID(c.Param("uid"))
// Visitors and other restricted users can only access shared content.
if (s.User().HasSharedAccessOnly(acl.ResourceAlbums) || s.NotRegistered()) && !s.HasShare(uid) {
if (s.GetUser().HasSharedAccessOnly(acl.ResourceAlbums) || s.NotRegistered()) && !s.HasShare(uid) {
AbortForbidden(c)
return
}
@@ -622,7 +622,7 @@ func RemovePhotosFromAlbum(router *gin.RouterGroup) {
uid := clean.UID(c.Param("uid"))
// Visitors and other restricted users can only access shared content.
if (s.User().HasSharedAccessOnly(acl.ResourceAlbums) || s.NotRegistered()) && !s.HasShare(uid) {
if (s.GetUser().HasSharedAccessOnly(acl.ResourceAlbums) || s.NotRegistered()) && !s.HasShare(uid) {
AbortForbidden(c)
return
}

View File

@@ -44,31 +44,31 @@ func AuthAny(c *gin.Context, resource acl.Resource, perms acl.Permissions) (s *e
if s.IsClient() {
// Check the resource and required permissions against the session scope.
if s.InsufficientScope(resource, perms) {
event.AuditErr([]string{clientIp, "client %s", "session %s", "access %s", authn.ErrInsufficientScope.Error()}, clean.Log(s.ClientInfo()), s.RefID, string(resource))
event.AuditErr([]string{clientIp, "client %s", "session %s", "access %s", authn.ErrInsufficientScope.Error()}, clean.Log(s.GetClientInfo()), s.RefID, string(resource))
return entity.SessionStatusForbidden()
}
// Check request authorization against client application ACL rules.
if acl.Rules.DenyAll(resource, s.ClientRole(), perms) {
event.AuditErr([]string{clientIp, "client %s", "session %s", "%s %s", authn.Denied}, clean.Log(s.ClientInfo()), s.RefID, perms.String(), string(resource))
if acl.Rules.DenyAll(resource, s.GetClientRole(), perms) {
event.AuditErr([]string{clientIp, "client %s", "session %s", "%s %s", authn.Denied}, clean.Log(s.GetClientInfo()), s.RefID, perms.String(), string(resource))
return entity.SessionStatusForbidden()
}
// Also check the request authorization against the user's ACL rules?
if s.NoUser() {
// Allow access based on the ACL defaults for client applications.
event.AuditInfo([]string{clientIp, "client %s", "session %s", "%s %s", authn.Granted}, clean.Log(s.ClientInfo()), s.RefID, perms.String(), string(resource))
} else if u := s.User(); !u.IsDisabled() && !u.IsUnknown() && u.IsRegistered() {
event.AuditInfo([]string{clientIp, "client %s", "session %s", "%s %s", authn.Granted}, clean.Log(s.GetClientInfo()), s.RefID, perms.String(), string(resource))
} else if u := s.GetUser(); !u.IsDisabled() && !u.IsUnknown() && u.IsRegistered() {
if acl.Rules.DenyAll(resource, u.AclRole(), perms) {
event.AuditErr([]string{clientIp, "client %s", "session %s", "%s %s as %s", authn.Denied}, clean.Log(s.ClientInfo()), s.RefID, perms.String(), string(resource), u.String())
event.AuditErr([]string{clientIp, "client %s", "session %s", "%s %s as %s", authn.Denied}, clean.Log(s.GetClientInfo()), s.RefID, perms.String(), string(resource), u.String())
return entity.SessionStatusForbidden()
}
// Allow access based on the user role.
event.AuditInfo([]string{clientIp, "client %s", "session %s", "%s %s as %s", authn.Granted}, clean.Log(s.ClientInfo()), s.RefID, perms.String(), string(resource), u.String())
event.AuditInfo([]string{clientIp, "client %s", "session %s", "%s %s as %s", authn.Granted}, clean.Log(s.GetClientInfo()), s.RefID, perms.String(), string(resource), u.String())
} else {
// Deny access if it is not a regular user account or the account has been disabled.
event.AuditErr([]string{clientIp, "client %s", "session %s", "%s %s as unauthorized user", authn.Denied}, clean.Log(s.ClientInfo()), s.RefID, perms.String(), string(resource))
event.AuditErr([]string{clientIp, "client %s", "session %s", "%s %s as unauthorized user", authn.Denied}, clean.Log(s.GetClientInfo()), s.RefID, perms.String(), string(resource))
return entity.SessionStatusForbidden()
}
@@ -76,7 +76,7 @@ func AuthAny(c *gin.Context, resource acl.Resource, perms acl.Permissions) (s *e
}
// Otherwise, perform a regular ACL authorization check based on the user role.
if u := s.User(); u.IsUnknown() || u.IsDisabled() {
if u := s.GetUser(); u.IsUnknown() || u.IsDisabled() {
event.AuditWarn([]string{clientIp, "session %s", "%s %s as unauthorized user", authn.Denied}, s.RefID, perms.String(), string(resource))
return entity.SessionStatusUnauthorized()
} else if acl.Rules.DenyAll(resource, u.AclRole(), perms) {

View File

@@ -32,7 +32,7 @@ func TestAuth(t *testing.T) {
// Check successful authorization in public mode.
s := Auth(c, acl.ResourceFiles, acl.ActionUpdate)
assert.NotNil(t, s)
assert.Equal(t, "admin", s.Username())
assert.Equal(t, "admin", s.GetUserName())
assert.Equal(t, session.PublicID, s.ID)
assert.Equal(t, http.StatusOK, s.HttpStatus())
assert.False(t, s.Abort(c))
@@ -40,7 +40,7 @@ func TestAuth(t *testing.T) {
// Check failed authorization in public mode.
s = Auth(c, acl.ResourceUsers, acl.ActionUpload)
assert.NotNil(t, s)
assert.Equal(t, "", s.Username())
assert.Equal(t, "", s.GetUserName())
assert.Equal(t, "", s.ID)
assert.Equal(t, http.StatusForbidden, s.HttpStatus())
assert.True(t, s.Abort(c))
@@ -66,7 +66,7 @@ func TestAuthAny(t *testing.T) {
// Check successful authorization in public mode.
s := AuthAny(c, acl.ResourceFiles, acl.Permissions{acl.ActionUpdate})
assert.NotNil(t, s)
assert.Equal(t, "admin", s.Username())
assert.Equal(t, "admin", s.GetUserName())
assert.Equal(t, session.PublicID, s.ID)
assert.Equal(t, http.StatusOK, s.HttpStatus())
assert.False(t, s.Abort(c))
@@ -74,7 +74,7 @@ func TestAuthAny(t *testing.T) {
// Check failed authorization in public mode.
s = AuthAny(c, acl.ResourceUsers, acl.Permissions{acl.ActionUpload})
assert.NotNil(t, s)
assert.Equal(t, "", s.Username())
assert.Equal(t, "", s.GetUserName())
assert.Equal(t, "", s.ID)
assert.Equal(t, http.StatusForbidden, s.HttpStatus())
assert.True(t, s.Abort(c))
@@ -82,7 +82,7 @@ func TestAuthAny(t *testing.T) {
// Check successful authorization with multiple actions in public mode.
s = AuthAny(c, acl.ResourceUsers, acl.Permissions{acl.ActionUpload, acl.ActionView})
assert.NotNil(t, s)
assert.Equal(t, "admin", s.Username())
assert.Equal(t, "admin", s.GetUserName())
assert.Equal(t, session.PublicID, s.ID)
assert.Equal(t, http.StatusOK, s.HttpStatus())
assert.False(t, s.Abort(c))

View File

@@ -323,7 +323,7 @@ func BatchPhotosDelete(router *gin.RouterGroup) {
var err error
// Abort if user wants to delete all but does not have sufficient privileges.
if frm.All && !acl.Rules.AllowAll(acl.ResourcePhotos, s.UserRole(), acl.Permissions{acl.AccessAll, acl.ActionManage}) {
if frm.All && !acl.Rules.AllowAll(acl.ResourcePhotos, s.GetUserRole(), acl.Permissions{acl.AccessAll, acl.ActionManage}) {
AbortForbidden(c)
return
}

View File

@@ -72,9 +72,9 @@ func SaveSettings(router *gin.RouterGroup) {
var settings *customize.Settings
// Only super admins can change global config defaults.
if s.User().IsSuperAdmin() {
if s.GetUser().IsSuperAdmin() {
// Update global defaults and user preferences.
user := s.User()
user := s.GetUser()
settings = conf.Settings()
// Set values from request.
@@ -103,7 +103,7 @@ func SaveSettings(router *gin.RouterGroup) {
UpdateClientConfig()
} else {
// Update user preferences without changing global defaults.
user := s.User()
user := s.GetUser()
if user == nil {
AbortUnexpectedError(c)
@@ -119,7 +119,7 @@ func SaveSettings(router *gin.RouterGroup) {
}
// Update user preferences.
if acl.Rules.DenyAll(acl.ResourceSettings, s.UserRole(), acl.Permissions{acl.ActionUpdate, acl.ActionManage}) {
if acl.Rules.DenyAll(acl.ResourceSettings, s.GetUserRole(), acl.Permissions{acl.ActionUpdate, acl.ActionManage}) {
c.JSON(http.StatusOK, user.Settings().Apply(settings).ApplyTo(conf.Settings().ApplyACL(acl.Rules, user.AclRole())))
return
} else if err := user.Settings().Apply(settings).Save(); err != nil {

View File

@@ -51,7 +51,7 @@ func Connect(router *gin.RouterGroup) {
s := Auth(c, acl.ResourceConfig, acl.ActionUpdate)
if !s.IsSuperAdmin() {
log.Errorf("connect: %s not authorized", clean.Log(s.User().UserName))
log.Errorf("connect: %s not authorized", clean.Log(s.GetUser().UserName))
AbortForbidden(c)
return
}

View File

@@ -62,7 +62,7 @@ func SearchFolders(router *gin.RouterGroup, urlPath, rootName, rootPath string)
return
}
user := s.User()
user := s.GetUser()
aclRole := user.AclRole()
// Exclude private content?

View File

@@ -85,9 +85,9 @@ func StartImport(router *gin.RouterGroup) {
// To avoid conflicts, uploads are imported from "import_path/upload/session_ref/timestamp".
if token := path.Base(srcFolder); token != "" && path.Dir(srcFolder) == UploadPath {
srcFolder = path.Join(UploadPath, s.RefID+token)
event.AuditInfo([]string{ClientIP(c), "session %s", "import uploads from %s as %s", authn.Granted}, s.RefID, clean.Log(srcFolder), s.UserRole().String())
} else if acl.Rules.Deny(acl.ResourceFiles, s.UserRole(), acl.ActionManage) {
event.AuditErr([]string{ClientIP(c), "session %s", "import files from %s as %s", authn.Denied}, s.RefID, clean.Log(srcFolder), s.UserRole().String())
event.AuditInfo([]string{ClientIP(c), "session %s", "import uploads from %s as %s", authn.Granted}, s.RefID, clean.Log(srcFolder), s.GetUserRole().String())
} else if acl.Rules.Deny(acl.ResourceFiles, s.GetUserRole(), acl.ActionManage) {
event.AuditErr([]string{ClientIP(c), "session %s", "import files from %s as %s", authn.Denied}, s.RefID, clean.Log(srcFolder), s.GetUserRole().String())
AbortForbidden(c)
return
}
@@ -100,7 +100,7 @@ func StartImport(router *gin.RouterGroup) {
// Get destination folder.
var destFolder string
if destFolder = s.User().GetUploadPath(); destFolder == "" {
if destFolder = s.GetUser().GetUploadPath(); destFolder == "" {
destFolder = conf.ImportDest()
}
@@ -117,7 +117,7 @@ func StartImport(router *gin.RouterGroup) {
// Add imported files to albums if allowed.
if len(frm.Albums) > 0 &&
acl.Rules.AllowAny(acl.ResourceAlbums, s.UserRole(), acl.Permissions{acl.ActionCreate, acl.ActionUpload}) {
acl.Rules.AllowAny(acl.ResourceAlbums, s.GetUserRole(), acl.Permissions{acl.ActionCreate, acl.ActionUpload}) {
log.Debugf("import: adding files to album %s", clean.Log(strings.Join(frm.Albums, " and ")))
opt.Albums = frm.Albums
}

View File

@@ -62,7 +62,7 @@ func StartIndexing(router *gin.RouterGroup) {
skipArchived := settings.Index.SkipArchived
indOpt := photoprism.NewIndexOptions(filepath.Clean(frm.Path), frm.Rescan, convert, true, false, skipArchived)
indOpt.SetUser(s.User())
indOpt.SetUser(s.GetUser())
if len(indOpt.Path) > 1 {
event.InfoMsg(i18n.MsgIndexingFiles, clean.Log(indOpt.Path))
@@ -120,7 +120,7 @@ func StartIndexing(router *gin.RouterGroup) {
}
// Delete orphaned index entries, sidecar files and thumbnails?
if frm.Cleanup && s.User().IsAdmin() {
if frm.Cleanup && s.GetUser().IsAdmin() {
event.Publish("index.updating", event.Data{
"uid": indOpt.UID,
"action": indOpt.Action,

View File

@@ -61,14 +61,14 @@ func OAuthRevoke(router *gin.RouterGroup) {
// Set log role and actor based on the session referenced in request header.
sUserUID = s.UserUID
if s.IsClient() {
role = s.ClientRole()
actor = fmt.Sprintf("client %s", clean.Log(s.ClientInfo()))
} else if username := s.Username(); username != "" {
role = s.UserRole()
role = s.GetClientRole()
actor = fmt.Sprintf("client %s", clean.Log(s.GetClientInfo()))
} else if username := s.GetUserName(); username != "" {
role = s.GetUserRole()
actor = fmt.Sprintf("user %s", clean.Log(username))
} else {
role = s.UserRole()
actor = fmt.Sprintf("unknown %s", s.UserRole().String())
role = s.GetUserRole()
actor = fmt.Sprintf("unknown %s", s.GetUserRole().String())
}
}
@@ -113,14 +113,14 @@ func OAuthRevoke(router *gin.RouterGroup) {
// If not already set, get the log role and actor from the session to be revoked.
if sess != nil && role == acl.RoleNone {
if sess.IsClient() {
role = sess.ClientRole()
actor = fmt.Sprintf("client %s", clean.Log(sess.ClientInfo()))
} else if username := sess.Username(); username != "" {
role = s.UserRole()
role = sess.GetClientRole()
actor = fmt.Sprintf("client %s", clean.Log(sess.GetClientInfo()))
} else if username := sess.GetUserName(); username != "" {
role = s.GetUserRole()
actor = fmt.Sprintf("user %s", clean.Log(username))
} else {
role = sess.UserRole()
actor = fmt.Sprintf("unknown %s", sess.UserRole().String())
role = sess.GetUserRole()
actor = fmt.Sprintf("unknown %s", sess.GetUserRole().String())
}
}

View File

@@ -127,17 +127,17 @@ func OAuthToken(router *gin.RouterGroup) {
if s == nil {
AbortInvalidCredentials(c)
return
} else if s.Username() == "" || s.IsClient() || !s.IsRegistered() {
} else if s.GetUserName() == "" || s.IsClient() || !s.IsRegistered() {
event.AuditErr([]string{clientIp, "oauth2", actor, action, authn.ErrInvalidGrantType.Error()})
AbortInvalidCredentials(c)
return
}
actor = fmt.Sprintf("user %s", clean.Log(s.Username()))
actor = fmt.Sprintf("user %s", clean.Log(s.GetUserName()))
if s.User().Provider().SupportsPasswordAuthentication() {
if s.GetUser().Provider().SupportsPasswordAuthentication() {
loginForm := form.Login{
Username: s.Username(),
Username: s.GetUserName(),
Password: frm.Password,
}
@@ -153,7 +153,7 @@ func OAuthToken(router *gin.RouterGroup) {
event.AuditErr([]string{clientIp, "oauth2", actor, action, "%s"}, strings.ToLower(clean.Error(authErr)))
AbortInvalidCredentials(c)
return
} else if !authUser.Equal(s.User()) {
} else if !authUser.Equal(s.GetUser()) {
event.AuditErr([]string{clientIp, "oauth2", actor, action, authn.ErrUserDoesNotMatch.Error()})
AbortInvalidCredentials(c)
return
@@ -164,7 +164,7 @@ func OAuthToken(router *gin.RouterGroup) {
frm.GrantType = authn.GrantSession
}
sess = entity.NewClientSession(frm.ClientName, frm.ExpiresIn, frm.Scope, frm.GrantType, s.User())
sess = entity.NewClientSession(frm.ClientName, frm.ExpiresIn, frm.Scope, frm.GrantType, s.GetUser())
// Return the reserved request rate limit tokens after successful authentication.
r.Success()
@@ -201,7 +201,8 @@ func OAuthToken(router *gin.RouterGroup) {
"access_token": sess.AuthToken(),
"token_type": sess.AuthTokenType(),
"expires_in": sess.ExpiresIn(),
"client_name": sess.ClientName,
"client_name": sess.GetClientName(),
"client_role": sess.GetClientRole(),
"scope": sess.Scope(),
}

View File

@@ -63,7 +63,7 @@ func SearchPhotos(router *gin.RouterGroup) {
// Ignore private flag if feature is disabled.
if frm.Scope == "" &&
settings.Features.Review &&
acl.Rules.Deny(acl.ResourcePhotos, s.UserRole(), acl.ActionManage) {
acl.Rules.Deny(acl.ResourcePhotos, s.GetUserRole(), acl.ActionManage) {
frm.Quality = 3
}

View File

@@ -64,7 +64,7 @@ func SearchGeo(router *gin.RouterGroup) {
// Ignore private flag if feature is disabled.
if frm.Scope == "" &&
settings.Features.Review &&
acl.Rules.Deny(acl.ResourcePhotos, s.UserRole(), acl.ActionManage) {
acl.Rules.Deny(acl.ResourcePhotos, s.GetUserRole(), acl.ActionManage) {
frm.Quality = 3
}

View File

@@ -39,11 +39,11 @@ func LikePhoto(router *gin.RouterGroup) {
return
}
if get.Config().Develop() && acl.Rules.Allow(acl.ResourcePhotos, s.UserRole(), acl.ActionReact) {
logWarn("react", m.React(s.User(), react.Find("love")))
if get.Config().Develop() && acl.Rules.Allow(acl.ResourcePhotos, s.GetUserRole(), acl.ActionReact) {
logWarn("react", m.React(s.GetUser(), react.Find("love")))
}
if acl.Rules.Allow(acl.ResourcePhotos, s.UserRole(), acl.ActionUpdate) {
if acl.Rules.Allow(acl.ResourcePhotos, s.GetUserRole(), acl.ActionUpdate) {
err = m.SetFavorite(true)
if err != nil {
@@ -87,11 +87,11 @@ func DislikePhoto(router *gin.RouterGroup) {
return
}
if get.Config().Develop() && acl.Rules.Allow(acl.ResourcePhotos, s.UserRole(), acl.ActionReact) {
logWarn("react", m.UnReact(s.User()))
if get.Config().Develop() && acl.Rules.Allow(acl.ResourcePhotos, s.GetUserRole(), acl.ActionReact) {
logWarn("react", m.UnReact(s.GetUser()))
}
if acl.Rules.Allow(acl.ResourcePhotos, s.UserRole(), acl.ActionUpdate) {
if acl.Rules.Allow(acl.ResourcePhotos, s.GetUserRole(), acl.ActionUpdate) {
err = m.SetFavorite(false)
if err != nil {

View File

@@ -87,7 +87,7 @@ func CreateSession(router *gin.RouterGroup) {
// Check authentication credentials.
if err = sess.LogIn(frm, c); err != nil {
if sess.Method().IsNot(authn.Method2FA) {
if sess.GetMethod().IsNot(authn.Method2FA) {
c.AbortWithStatusJSON(sess.HttpStatus(), gin.H{"error": i18n.Msg(i18n.ErrInvalidCredentials)})
} else if errors.Is(err, authn.ErrPasscodeRequired) {
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": err.Error(), "code": 32, "message": i18n.Msg(i18n.ErrPasscodeRequired)})

View File

@@ -51,27 +51,27 @@ func DeleteSession(router *gin.RouterGroup) {
// Only admins may delete other sessions by ref id.
if rnd.IsRefID(id) {
if !acl.Rules.AllowAll(acl.ResourceSessions, s.UserRole(), acl.Permissions{acl.AccessAll, acl.ActionManage}) {
event.AuditErr([]string{clientIp, "session %s", "delete %s as %s", authn.Denied}, s.RefID, acl.ResourceSessions.String(), s.UserRole())
if !acl.Rules.AllowAll(acl.ResourceSessions, s.GetUserRole(), acl.Permissions{acl.AccessAll, acl.ActionManage}) {
event.AuditErr([]string{clientIp, "session %s", "delete %s as %s", authn.Denied}, s.RefID, acl.ResourceSessions.String(), s.GetUserRole())
Abort(c, http.StatusForbidden, i18n.ErrForbidden)
return
}
event.AuditInfo([]string{clientIp, "session %s", "delete %s as %s", authn.Granted}, s.RefID, acl.ResourceSessions.String(), s.UserRole())
event.AuditInfo([]string{clientIp, "session %s", "delete %s as %s", authn.Granted}, s.RefID, acl.ResourceSessions.String(), s.GetUserRole())
if s = entity.FindSessionByRefID(id); s == nil {
Abort(c, http.StatusNotFound, i18n.ErrNotFound)
return
}
} else if id != "" && s.ID != id {
event.AuditWarn([]string{clientIp, "session %s", "delete %s as %s", "ids do not match"}, s.RefID, acl.ResourceSessions.String(), s.UserRole())
event.AuditWarn([]string{clientIp, "session %s", "delete %s as %s", "ids do not match"}, s.RefID, acl.ResourceSessions.String(), s.GetUserRole())
Abort(c, http.StatusForbidden, i18n.ErrForbidden)
return
}
// Delete session cache and database record.
if err := s.Delete(); err != nil {
event.AuditErr([]string{clientIp, "session %s", "delete session as %s", "%s"}, s.RefID, s.UserRole(), err)
event.AuditErr([]string{clientIp, "session %s", "delete session as %s", "%s"}, s.RefID, s.GetUserRole(), err)
} else {
event.AuditDebug([]string{clientIp, "session %s", "deleted"}, s.RefID)
}

View File

@@ -32,10 +32,10 @@ func GetSessionResponse(authToken string, sess *entity.Session, conf *config.Cli
"status": StatusSuccess,
"session_id": sess.ID,
"expires_in": sess.ExpiresIn(),
"provider": sess.Provider().String(),
"provider": sess.GetProvider().String(),
"scope": sess.Scope(),
"user": sess.User(),
"data": sess.Data(),
"user": sess.GetUser(),
"data": sess.GetData(),
"config": conf,
}
} else {
@@ -48,10 +48,10 @@ func GetSessionResponse(authToken string, sess *entity.Session, conf *config.Cli
"access_token": authToken,
"token_type": sess.AuthTokenType(),
"expires_in": sess.ExpiresIn(),
"provider": sess.Provider().String(),
"provider": sess.GetProvider().String(),
"scope": sess.Scope(),
"user": sess.User(),
"data": sess.Data(),
"user": sess.GetUser(),
"data": sess.GetData(),
"config": conf,
}
}

View File

@@ -37,9 +37,9 @@ func TestGetSessionResponse(t *testing.T) {
assert.Equal(t, sess.AuthToken(), result["access_token"])
assert.Equal(t, sess.AuthTokenType(), result["token_type"])
assert.Equal(t, sess.ExpiresIn(), result["expires_in"])
assert.Equal(t, sess.Provider().String(), result["provider"])
assert.Equal(t, sess.User(), result["user"])
assert.Equal(t, sess.Data(), result["data"])
assert.Equal(t, sess.GetProvider().String(), result["provider"])
assert.Equal(t, sess.GetUser(), result["user"])
assert.Equal(t, sess.GetData(), result["data"])
assert.Equal(t, conf, result["config"])
})
t.Run("NoAuthToken", func(t *testing.T) {
@@ -56,9 +56,9 @@ func TestGetSessionResponse(t *testing.T) {
assert.Nil(t, result["access_token"])
assert.Nil(t, result["token_type"])
assert.Equal(t, sess.ExpiresIn(), result["expires_in"])
assert.Equal(t, sess.Provider().String(), result["provider"])
assert.Equal(t, sess.User(), result["user"])
assert.Equal(t, sess.Data(), result["data"])
assert.Equal(t, sess.GetProvider().String(), result["provider"])
assert.Equal(t, sess.GetUser(), result["user"])
assert.Equal(t, sess.GetData(), result["data"])
assert.Equal(t, conf, result["config"])
})
}

View File

@@ -37,11 +37,11 @@ func UploadUserAvatar(router *gin.RouterGroup) {
}
// Check if the session user is has user management privileges.
isAdmin := acl.Rules.AllowAll(acl.ResourceUsers, s.UserRole(), acl.Permissions{acl.AccessAll, acl.ActionManage})
isAdmin := acl.Rules.AllowAll(acl.ResourceUsers, s.GetUserRole(), acl.Permissions{acl.AccessAll, acl.ActionManage})
uid := clean.UID(c.Param("uid"))
// Users may only change their own avatar.
if !isAdmin && s.User().UserUID != uid {
if !isAdmin && s.GetUser().UserUID != uid {
event.AuditErr([]string{ClientIP(c), "session %s", "upload avatar", "user does not match"}, s.RefID)
AbortForbidden(c)
return

View File

@@ -243,7 +243,7 @@ func checkUserPasscodeAuth(c *gin.Context, action acl.Permission) (*entity.Sessi
uid := clean.UID(c.Param("uid"))
// Get user from session.
user := s.User()
user := s.GetUser()
// Regular users can only set up a passcode for their own account.
if user.UserUID != uid || !user.CanLogIn() {

View File

@@ -49,18 +49,18 @@ func UpdateUserPassword(router *gin.RouterGroup) {
}
// Check if the current user has management privileges.
isAdmin := acl.Rules.AllowAll(acl.ResourceUsers, s.UserRole(), acl.Permissions{acl.AccessAll, acl.ActionManage})
isSuperAdmin := isAdmin && s.User().IsSuperAdmin()
isAdmin := acl.Rules.AllowAll(acl.ResourceUsers, s.GetUserRole(), acl.Permissions{acl.AccessAll, acl.ActionManage})
isSuperAdmin := isAdmin && s.GetUser().IsSuperAdmin()
uid := clean.UID(c.Param("uid"))
var u *entity.User
// Regular users may only change their own password.
if !isAdmin && s.User().UserUID != uid {
if !isAdmin && s.GetUser().UserUID != uid {
AbortForbidden(c)
return
} else if s.User().UserUID == uid {
u = s.User()
} else if s.GetUser().UserUID == uid {
u = s.GetUser()
isAdmin = false
isSuperAdmin = false
} else if u = entity.FindUserByUID(uid); u == nil {
@@ -94,7 +94,7 @@ func UpdateUserPassword(router *gin.RouterGroup) {
}
// Update tokens if user matches with session.
if s.User().UserUID == u.GetUID() {
if s.GetUser().UserUID == u.GetUID() {
s.SetPreviewToken(u.PreviewToken)
s.SetDownloadToken(u.DownloadToken)
}

View File

@@ -63,7 +63,7 @@ func UpdateUser(router *gin.RouterGroup) {
}
// Check if the session user has user management privileges.
isAdmin := acl.Rules.AllowAll(acl.ResourceUsers, s.UserRole(), acl.Permissions{acl.AccessAll, acl.ActionManage})
isAdmin := acl.Rules.AllowAll(acl.ResourceUsers, s.GetUserRole(), acl.Permissions{acl.AccessAll, acl.ActionManage})
privilegeLevelChange := isAdmin && m.PrivilegeLevelChange(f)
// Check if the user account quota has been exceeded.
@@ -74,7 +74,7 @@ func UpdateUser(router *gin.RouterGroup) {
}
// Get user from session.
u := s.User()
u := s.GetUser()
// Save model with values from form.
if err = m.SaveForm(f, u); err != nil {

View File

@@ -49,7 +49,7 @@ func UploadUserFiles(router *gin.RouterGroup) {
uid := clean.UID(c.Param("uid"))
// Users may only upload files for their own account.
if s.User().UserUID != uid {
if s.GetUser().UserUID != uid {
event.AuditErr([]string{ClientIP(c), "session %s", "upload files", "user does not match"}, s.RefID)
AbortForbidden(c)
return
@@ -264,7 +264,7 @@ func ProcessUserUpload(router *gin.RouterGroup) {
}
// Users may only upload their own files.
if s.User().UserUID != clean.UID(c.Param("uid")) {
if s.GetUser().UserUID != clean.UID(c.Param("uid")) {
AbortForbidden(c)
return
}
@@ -299,7 +299,7 @@ func ProcessUserUpload(router *gin.RouterGroup) {
// Get destination folder.
var destFolder string
if destFolder = s.User().GetUploadPath(); destFolder == "" {
if destFolder = s.GetUser().GetUploadPath(); destFolder == "" {
destFolder = conf.ImportDest()
}
@@ -309,7 +309,7 @@ func ProcessUserUpload(router *gin.RouterGroup) {
// Add imported files to albums if allowed.
if len(frm.Albums) > 0 &&
acl.Rules.AllowAny(acl.ResourceAlbums, s.UserRole(), acl.Permissions{acl.ActionCreate, acl.ActionUpload}) {
acl.Rules.AllowAny(acl.ResourceAlbums, s.GetUserRole(), acl.Permissions{acl.ActionCreate, acl.ActionUpload}) {
log.Debugf("upload: adding files to album %s", clean.Log(strings.Join(frm.Albums, " and ")))
opt.Albums = frm.Albums
}

View File

@@ -39,7 +39,7 @@ func wsReader(ws *websocket.Conn, writeMutex *sync.Mutex, connId string, conf *c
wsAuth.mutex.Lock()
wsAuth.sid[connId] = s.ID
wsAuth.rid[connId] = s.RefID
wsAuth.user[connId] = *s.User()
wsAuth.user[connId] = *s.GetUser()
wsAuth.mutex.Unlock()
wsSendMessage("config.updated", event.Data{"config": conf.ClientSession(s)}, ws, writeMutex)

View File

@@ -8,6 +8,8 @@ const (
RoleViewer Role = "viewer"
RoleGuest Role = "guest"
RoleVisitor Role = "visitor"
RoleNode Role = "node"
RolePortal Role = "portal"
RoleClient Role = "client"
RoleNone Role = ""
)

View File

@@ -157,6 +157,8 @@ var GrantDefaults = Roles{
RoleAdmin: GrantFullAccess,
RoleGuest: GrantReactShared,
RoleVisitor: GrantViewShared,
RoleNode: GrantSearchShared,
RolePortal: GrantFullAccess,
RoleClient: GrantFullAccess,
}

View File

@@ -14,6 +14,8 @@ var UserRoles = RoleStrings{
// ClientRoles maps valid API client roles.
var ClientRoles = RoleStrings{
string(RoleAdmin): RoleAdmin,
string(RoleNode): RoleNode,
string(RolePortal): RolePortal,
string(RoleClient): RoleClient,
string(RoleNone): RoleNone,
}

View File

@@ -47,6 +47,8 @@ var Rules = ACL{
RoleAdmin: GrantFullAccess,
RoleGuest: GrantReactShared,
RoleVisitor: GrantViewShared,
RoleNode: GrantUseOwn,
RolePortal: GrantUseOwn,
RoleClient: GrantFullAccess,
},
ResourceLabels: Roles{
@@ -62,30 +64,38 @@ var Rules = ACL{
RoleAdmin: GrantFullAccess,
RoleGuest: GrantViewUpdateOwn,
RoleVisitor: GrantViewOwn,
RolePortal: GrantFullAccess,
RoleClient: GrantViewUpdateOwn,
},
ResourceServices: Roles{
RoleAdmin: GrantFullAccess,
RoleAdmin: GrantFullAccess,
RolePortal: GrantFullAccess,
},
ResourcePasscode: Roles{
RoleAdmin: GrantFullAccess,
RoleGuest: GrantConfigureOwn,
RoleAdmin: GrantFullAccess,
RolePortal: GrantFullAccess,
RoleGuest: GrantConfigureOwn,
},
ResourcePassword: Roles{
RoleAdmin: GrantFullAccess,
RoleGuest: GrantUpdateOwn,
RoleAdmin: GrantFullAccess,
RolePortal: GrantFullAccess,
RoleGuest: GrantUpdateOwn,
},
ResourceUsers: Roles{
RoleAdmin: GrantManageOwn,
RoleGuest: GrantViewUpdateOwn,
RoleNode: GrantViewOwn,
RolePortal: GrantFullAccess,
RoleClient: GrantViewOwn,
},
ResourceSessions: Roles{
RoleAdmin: GrantManageOwn,
RolePortal: GrantFullAccess,
RoleDefault: GrantOwn,
},
ResourceLogs: Roles{
RoleAdmin: GrantFullAccess,
RolePortal: GrantFullAccess,
RoleClient: GrantFullAccess,
},
ResourceApi: Roles{
@@ -94,6 +104,7 @@ var Rules = ACL{
},
ResourceWebDAV: Roles{
RoleAdmin: GrantFullAccess,
RolePortal: GrantFullAccess,
RoleClient: GrantFullAccess,
},
ResourceWebhooks: Roles{
@@ -102,14 +113,20 @@ var Rules = ACL{
},
ResourceMetrics: Roles{
RoleAdmin: GrantFullAccess,
RoleNode: GrantNone,
RolePortal: GrantViewAll,
RoleClient: GrantViewAll,
},
ResourceVision: Roles{
RoleAdmin: GrantFullAccess,
RoleNode: GrantUseOwn,
RolePortal: GrantUseOwn,
RoleClient: GrantUseOwn,
},
ResourceCluster: Roles{
RoleAdmin: GrantFullAccess,
RoleNode: GrantSearchDownloadUpdateOwn,
RolePortal: GrantFullAccess,
RoleClient: GrantSearchDownloadUpdateOwn,
},
ResourceFeedback: Roles{
@@ -117,6 +134,8 @@ var Rules = ACL{
},
ResourceDefault: Roles{
RoleAdmin: GrantFullAccess,
RoleNode: GrantNone,
RolePortal: GrantNone,
RoleClient: GrantNone,
},
}

View File

@@ -52,8 +52,8 @@ func authListAction(ctx *cli.Context) error {
rows[i] = []string{
res.RefID,
res.UserInfo(),
res.AuthInfo(),
res.ClientInfo(),
res.GetAuthInfo(),
res.GetClientInfo(),
res.AuthScope,
res.LoginIP,
res.ClientIP,

View File

@@ -734,12 +734,12 @@ func (c *Config) ClientRole(role acl.Role) *ClientConfig {
// ClientSession provides the client config values for the specified session.
func (c *Config) ClientSession(sess *entity.Session) (cfg *ClientConfig) {
if sess.NoUser() && sess.IsClient() {
cfg = c.ClientUser(false).ApplyACL(acl.Rules, sess.ClientRole())
cfg = c.ClientUser(false).ApplyACL(acl.Rules, sess.GetClientRole())
cfg.Settings = c.SessionSettings(sess)
} else if sess.User().IsVisitor() {
} else if sess.GetUser().IsVisitor() {
cfg = c.ClientShare()
} else if sess.User().IsRegistered() {
cfg = c.ClientUser(false).ApplyACL(acl.Rules, sess.UserRole())
} else if sess.GetUser().IsRegistered() {
cfg = c.ClientUser(false).ApplyACL(acl.Rules, sess.GetUserRole())
cfg.Settings = c.SessionSettings(sess)
} else {
cfg = c.ClientPublic()

View File

@@ -74,10 +74,10 @@ func (c *Config) SessionSettings(sess *entity.Session) *customize.Settings {
}
if sess.NoUser() && sess.IsClient() {
return c.Settings().ApplyACL(acl.Rules, sess.ClientRole()).ApplyScope(sess.Scope())
return c.Settings().ApplyACL(acl.Rules, sess.GetClientRole()).ApplyScope(sess.Scope())
}
user := sess.User()
user := sess.GetUser()
// Return public settings if the session does not have a user.
if user == nil {

View File

@@ -202,11 +202,11 @@ func (m *Session) Save() error {
}
// Limit the number of sessions that are created with an app password.
if !m.Method().IsSession() {
if !m.GetMethod().IsSession() {
return nil
} else if !m.Provider().IsApplication() {
} else if !m.GetProvider().IsApplication() {
return nil
} else if client := m.Client(); client.NoName() || client.Tokens() < 1 {
} else if client := m.GetClient(); client.NoName() || client.Tokens() < 1 {
return nil
} else if deleted := DeleteClientSessions(client, authn.MethodSession, client.Tokens()); deleted > 0 {
event.AuditInfo([]string{m.IP(), "session %s", "deleted %s"}, m.RefID, english.Plural(deleted, "previously created client session", "previously created client sessions"))
@@ -241,7 +241,7 @@ func (m *Session) BeforeCreate(scope *gorm.Scope) error {
return scope.SetColumn("ID", m.ID)
}
// SetClient updates the client of this session.
// SetClient sets the client of this session.
func (m *Session) SetClient(c *Client) *Session {
if c == nil {
return m
@@ -258,7 +258,7 @@ func (m *Session) SetClient(c *Client) *Session {
return m
}
// SetClientName changes the session's client name.
// SetClientName changes the client name of this session.
func (m *Session) SetClientName(s string) *Session {
if s == "" {
return m
@@ -269,8 +269,8 @@ func (m *Session) SetClientName(s string) *Session {
return m
}
// Client returns the session's client.
func (m *Session) Client() *Client {
// GetClient returns the client this session belongs to.
func (m *Session) GetClient() *Client {
if m == nil {
return &Client{}
} else if m.client != nil {
@@ -284,17 +284,22 @@ func (m *Session) Client() *Client {
UserUID: m.UserUID,
UserName: m.UserName,
ClientUID: m.ClientUID,
ClientName: m.ClientName,
ClientRole: m.ClientRole().String(),
ClientName: m.GetClientName(),
ClientRole: m.GetClientRole().String(),
AuthScope: m.Scope(),
AuthMethod: m.AuthMethod,
}
}
// ClientRole returns the session's client ACL role.
func (m *Session) ClientRole() acl.Role {
// GetClientName returns the client name.
func (m *Session) GetClientName() string {
return m.ClientName
}
// GetClientRole returns the client ACL role.
func (m *Session) GetClientRole() acl.Role {
if m.HasClient() {
return m.Client().AclRole()
return m.GetClient().AclRole()
} else if m.IsClient() {
return acl.RoleClient
}
@@ -302,10 +307,10 @@ func (m *Session) ClientRole() acl.Role {
return acl.RoleNone
}
// ClientInfo returns the session's client identifier string.
func (m *Session) ClientInfo() string {
// GetClientInfo returns the client identifier string.
func (m *Session) GetClientInfo() string {
if m.HasClient() {
return m.Client().String()
return m.GetClient().String()
} else if m.ClientName != "" {
return m.ClientName
}
@@ -332,8 +337,8 @@ func (m *Session) IsClient() bool {
return authn.Provider(m.AuthProvider).IsClient()
}
// User returns the session's user entity.
func (m *Session) User() *User {
// GetUser returns the related user entity.
func (m *Session) GetUser() *User {
if m == nil {
return &User{}
} else if m.user != nil {
@@ -350,20 +355,20 @@ func (m *Session) User() *User {
return &User{}
}
// UserRole returns the session's user ACL role.
func (m *Session) UserRole() acl.Role {
return m.User().AclRole()
// GetUserRole returns the session's user ACL role.
func (m *Session) GetUserRole() acl.Role {
return m.GetUser().AclRole()
}
// UserInfo returns the session's user information.
func (m *Session) UserInfo() string {
name := m.Username()
name := m.GetUserName()
if name != "" {
return name
}
return m.UserRole().String()
return m.GetUserRole().String()
}
// SetUser updates the user entity of this session.
@@ -414,15 +419,15 @@ func (m *Session) RefreshUser() *Session {
return m
}
// Username returns the login name.
func (m *Session) Username() string {
// GetUserName returns the login name.
func (m *Session) GetUserName() string {
return m.UserName
}
// AuthInfo returns information about the authentication type.
func (m *Session) AuthInfo() string {
provider := m.Provider()
method := m.Method()
// GetAuthInfo returns information about the authentication type.
func (m *Session) GetAuthInfo() string {
provider := m.GetProvider()
method := m.GetMethod()
if method.IsDefault() {
return provider.Pretty()
@@ -443,8 +448,8 @@ func (m *Session) SetAuthID(id, issuer string) *Session {
return m
}
// Provider returns the authentication provider.
func (m *Session) Provider() authn.ProviderType {
// GetProvider returns the authentication provider.
func (m *Session) GetProvider() authn.ProviderType {
return authn.Provider(m.AuthProvider)
}
@@ -459,14 +464,14 @@ func (m *Session) SetProvider(provider authn.ProviderType) *Session {
return m
}
// Method returns the authentication method.
func (m *Session) Method() authn.MethodType {
// GetMethod returns the authentication method.
func (m *Session) GetMethod() authn.MethodType {
return authn.Method(m.AuthMethod)
}
// Is2FA checks if 2-Factor Authentication (2FA) was used to log in.
func (m *Session) Is2FA() bool {
return m.Method().Is(authn.Method2FA)
return m.GetMethod().Is(authn.Method2FA)
}
// SetMethod sets a custom authentication method.
@@ -539,8 +544,8 @@ func (m *Session) SetScope(scope string) *Session {
return m
}
// AuthGrantType returns the session's grant type as authn.GrantType.
func (m *Session) AuthGrantType() authn.GrantType {
// GetGrantType returns the session's grant type as authn.GrantType.
func (m *Session) GetGrantType() authn.GrantType {
return authn.Grant(m.GrantType)
}
@@ -557,7 +562,7 @@ func (m *Session) SetGrantType(t authn.GrantType) *Session {
// ChangePassword changes the password of the current user.
func (m *Session) ChangePassword(newPw string) (err error) {
u := m.User()
u := m.GetUser()
if u == nil {
return fmt.Errorf("unknown user")
@@ -606,8 +611,8 @@ func (m *Session) SetDownloadToken(token string) *Session {
return m
}
// Data returns the session's data.
func (m *Session) Data() (data *SessionData) {
// GetData returns the data that belong to this session.
func (m *Session) GetData() (data *SessionData) {
if m.data != nil {
data = m.data
}
@@ -626,7 +631,7 @@ func (m *Session) Data() (data *SessionData) {
return data
}
// SetData updates the session's data.
// SetData updates the data that belong to this session.
func (m *Session) SetData(data *SessionData) *Session {
if data == nil {
log.Debugf("auth: empty data passed to session %s", m.RefID)
@@ -704,7 +709,7 @@ func (m *Session) UpdateContext(c *gin.Context) *Session {
// IsVisitor checks if the session belongs to a sharing link visitor.
func (m *Session) IsVisitor() bool {
return m.User().IsVisitor()
return m.GetUser().IsVisitor()
}
// IsSuperAdmin checks if the session belongs to a registered super admin user.
@@ -713,7 +718,7 @@ func (m *Session) IsSuperAdmin() bool {
return false
}
return m.User().IsSuperAdmin()
return m.GetUser().IsSuperAdmin()
}
// IsRegistered checks if the session belongs to a registered user account.
@@ -722,7 +727,7 @@ func (m *Session) IsRegistered() bool {
return false
}
return m.User().IsRegistered()
return m.GetUser().IsRegistered()
}
// NotRegistered checks if the user is not registered with an own account.
@@ -737,9 +742,9 @@ func (m *Session) NoShares() bool {
// HasShares checks if the session has any shares.
func (m *Session) HasShares() bool {
if user := m.User(); user.IsRegistered() {
if user := m.GetUser(); user.IsRegistered() {
return user.HasShares()
} else if data := m.Data(); data == nil {
} else if data := m.GetData(); data == nil {
return false
} else {
return data.HasShares()
@@ -752,14 +757,14 @@ func (m *Session) HasRegisteredUser() bool {
return false
}
return m.User().IsRegistered()
return m.GetUser().IsRegistered()
}
// HasShare if the session includes the specified share
func (m *Session) HasShare(uid string) bool {
if user := m.User(); user.IsRegistered() {
if user := m.GetUser(); user.IsRegistered() {
return user.HasShare(uid)
} else if data := m.Data(); data == nil {
} else if data := m.GetData(); data == nil {
return false
} else {
return data.HasShare(uid)
@@ -768,9 +773,9 @@ func (m *Session) HasShare(uid string) bool {
// SharedUIDs returns shared entity UIDs.
func (m *Session) SharedUIDs() UIDs {
if user := m.User(); user.IsRegistered() {
if user := m.GetUser(); user.IsRegistered() {
return user.SharedUIDs()
} else if data := m.Data(); data == nil {
} else if data := m.GetData(); data == nil {
return UIDs{}
} else {
return data.SharedUIDs()
@@ -779,9 +784,9 @@ func (m *Session) SharedUIDs() UIDs {
// RedeemToken updates shared entity UIDs using the specified token.
func (m *Session) RedeemToken(token string) (n int) {
if user := m.User(); user.IsRegistered() {
if user := m.GetUser(); user.IsRegistered() {
return user.RedeemToken(token)
} else if data := m.Data(); data == nil {
} else if data := m.GetData(); data == nil {
return 0
} else {
return data.RedeemToken(token)
@@ -889,7 +894,7 @@ func (m *Session) UpdateLastActive(save bool) *Session {
}
// Update the activity timestamp of the parent session, if any.
if m.Method().IsNot(authn.MethodSession) || m.AuthID == "" || m.AuthID == m.ID {
if m.GetMethod().IsNot(authn.MethodSession) || m.AuthID == "" || m.AuthID == m.ID {
return m
} else if err := Db().Table(Session{}.TableName()).Where("id = ?", m.AuthID).UpdateColumn("last_active", m.LastActive).Error; err != nil {
event.AuditWarn([]string{m.IP(), "session %s", "failed to update activity timestamp of parent session", "%s"}, m.RefID, err)
@@ -909,7 +914,7 @@ func (m *Session) Valid() bool {
return true
}
return m.User().IsRegistered() || m.IsVisitor() && m.HasShares()
return m.GetUser().IsRegistered() || m.IsVisitor() && m.HasShares()
}
// Abort aborts the request with the appropriate error code if access to the requested resource is denied.

View File

@@ -42,7 +42,7 @@ func DeleteSession(s *Session) error {
func DeleteChildSessions(s *Session) (deleted int) {
if s == nil {
return 0
} else if !rnd.IsSessionID(s.ID) || s.Method().Is(authn.MethodSession) {
} else if !rnd.IsSessionID(s.ID) || s.GetMethod().Is(authn.MethodSession) {
return 0
}

View File

@@ -65,7 +65,7 @@ func AuthSession(frm form.Login, c *gin.Context) (sess *Session, user *User, err
sess.UpdateContext(c)
// Returns session and user if all checks have passed.
return sess, sess.User(), nil
return sess, sess.GetUser(), nil
}
// AuthLocal authenticates against the local user database with the specified username and password.
@@ -140,7 +140,7 @@ func AuthLocal(user *User, frm form.Login, s *Session, c *gin.Context) (provider
if s != nil {
// Set scope, client UID, and client name to that of the parent session.
s.ClientUID = authSess.ClientUID
s.ClientName = authSess.ClientName
s.ClientName = authSess.GetClientName()
s.SetScope(authSess.Scope())
// Set provider and method to help identify the session type.
@@ -267,7 +267,7 @@ func (m *Session) LogIn(frm form.Login, c *gin.Context) (err error) {
// Try to redeem link share token, if provided.
if frm.HasShareToken() {
user = m.User()
user = m.GetUser()
// Redeem token.
if user.IsRegistered() {
@@ -279,7 +279,7 @@ func (m *Session) LogIn(frm form.Login, c *gin.Context) (err error) {
} else {
event.AuditInfo([]string{m.IP(), "session %s", "token redeemed for %d shares"}, m.RefID, user.RedeemToken(frm.Token))
}
} else if data := m.Data(); data == nil {
} else if data := m.GetData(); data == nil {
m.Status = http.StatusInternalServerError
return i18n.Error(i18n.ErrUnexpected)
} else if shares := data.RedeemToken(frm.Token); shares == 0 {
@@ -308,7 +308,7 @@ func (m *Session) LogIn(frm form.Login, c *gin.Context) (err error) {
}
// Unregistered visitors must use a valid share link to obtain a session.
if m.User().NotRegistered() && m.Data().NoShares() {
if m.GetUser().NotRegistered() && m.GetData().NoShares() {
m.Status = http.StatusUnauthorized
return i18n.Error(i18n.ErrInvalidCredentials)
}

View File

@@ -101,9 +101,9 @@ func TestAuthSession(t *testing.T) {
assert.NotNil(t, authUser)
assert.Equal(t, u.UserUID, s.UserUID)
assert.Equal(t, u.Username(), s.Username())
assert.Equal(t, u.Username(), s.GetUserName())
assert.Equal(t, authUser.UserUID, authSess.UserUID)
assert.Equal(t, authUser.Username(), authSess.Username())
assert.Equal(t, authUser.Username(), authSess.GetUserName())
assert.Equal(t, authUser.UserUID, authUser.UserUID)
assert.Equal(t, authUser.Username(), authUser.Username())
@@ -139,9 +139,9 @@ func TestAuthSession(t *testing.T) {
assert.NotNil(t, authUser)
assert.Equal(t, u.UserUID, s.UserUID)
assert.Equal(t, u.Username(), s.Username())
assert.Equal(t, u.Username(), s.GetUserName())
assert.Equal(t, authUser.UserUID, authSess.UserUID)
assert.Equal(t, authUser.Username(), authSess.Username())
assert.Equal(t, authUser.Username(), authSess.GetUserName())
assert.Equal(t, authUser.UserUID, authUser.UserUID)
assert.Equal(t, authUser.Username(), authUser.Username())

View File

@@ -26,8 +26,8 @@ func TestNewSession(t *testing.T) {
assert.False(t, m.UpdatedAt.IsZero())
assert.False(t, m.ExpiresAt().IsZero())
assert.NotEmpty(t, m.ID)
assert.NotNil(t, m.Data())
assert.Equal(t, 0, len(m.Data().Tokens))
assert.NotNil(t, m.GetData())
assert.Equal(t, 0, len(m.GetData().Tokens))
})
t.Run("EmptySessionData", func(t *testing.T) {
m := NewSession(unix.Day, unix.Hour*6)
@@ -39,8 +39,8 @@ func TestNewSession(t *testing.T) {
assert.False(t, m.UpdatedAt.IsZero())
assert.False(t, m.ExpiresAt().IsZero())
assert.NotEmpty(t, m.ID)
assert.NotNil(t, m.Data())
assert.Equal(t, 0, len(m.Data().Tokens))
assert.NotNil(t, m.GetData())
assert.Equal(t, 0, len(m.GetData().Tokens))
})
t.Run("WithSessionData", func(t *testing.T) {
data := NewSessionData()
@@ -54,10 +54,10 @@ func TestNewSession(t *testing.T) {
assert.False(t, m.UpdatedAt.IsZero())
assert.False(t, m.ExpiresAt().IsZero())
assert.NotEmpty(t, m.ID)
assert.NotNil(t, m.Data())
assert.Len(t, m.Data().Tokens, 2)
assert.Equal(t, "foo", m.Data().Tokens[0])
assert.Equal(t, "bar", m.Data().Tokens[1])
assert.NotNil(t, m.GetData())
assert.Len(t, m.GetData().Tokens, 2)
assert.Equal(t, "foo", m.GetData().Tokens[0])
assert.Equal(t, "bar", m.GetData().Tokens[1])
})
}
@@ -292,72 +292,72 @@ func TestSession_Client(t *testing.T) {
t.Run("Alice", func(t *testing.T) {
m := FindSessionByRefID("sessxkkcabcd")
assert.Equal(t, "uqxetse3cy5eo9z2", m.UserUID)
assert.Equal(t, "uqxetse3cy5eo9z2", m.User().UserUID)
assert.Equal(t, "", m.Client().ClientUID)
assert.Equal(t, "uqxetse3cy5eo9z2", m.Client().UserUID)
assert.Equal(t, acl.RoleNone, m.Client().AclRole())
assert.Equal(t, acl.RoleNone, m.ClientRole())
assert.Equal(t, "uqxetse3cy5eo9z2", m.GetUser().UserUID)
assert.Equal(t, "", m.GetClient().ClientUID)
assert.Equal(t, "uqxetse3cy5eo9z2", m.GetClient().UserUID)
assert.Equal(t, acl.RoleNone, m.GetClient().AclRole())
assert.Equal(t, acl.RoleNone, m.GetClientRole())
})
t.Run("AliceTokenPersonal", func(t *testing.T) {
m := SessionFixtures.Get("alice_token_personal")
assert.Equal(t, "uqxetse3cy5eo9z2", m.UserUID)
assert.Equal(t, "uqxetse3cy5eo9z2", m.User().UserUID)
assert.Equal(t, "", m.Client().ClientUID)
assert.Equal(t, "uqxetse3cy5eo9z2", m.Client().UserUID)
assert.Equal(t, acl.RoleClient, m.Client().AclRole())
assert.Equal(t, acl.RoleClient, m.ClientRole())
assert.Equal(t, "uqxetse3cy5eo9z2", m.GetUser().UserUID)
assert.Equal(t, "", m.GetClient().ClientUID)
assert.Equal(t, "uqxetse3cy5eo9z2", m.GetClient().UserUID)
assert.Equal(t, acl.RoleClient, m.GetClient().AclRole())
assert.Equal(t, acl.RoleClient, m.GetClientRole())
})
t.Run("ClientMetrics", func(t *testing.T) {
m := SessionFixtures.Get("client_metrics")
assert.Equal(t, "", m.UserUID)
assert.Equal(t, "", m.User().UserUID)
assert.Equal(t, "cs5cpu17n6gj2qo5", m.Client().ClientUID)
assert.Equal(t, "", m.Client().UserUID)
assert.Equal(t, acl.RoleClient, m.Client().AclRole())
assert.Equal(t, acl.RoleClient, m.ClientRole())
assert.Equal(t, "", m.GetUser().UserUID)
assert.Equal(t, "cs5cpu17n6gj2qo5", m.GetClient().ClientUID)
assert.Equal(t, "", m.GetClient().UserUID)
assert.Equal(t, acl.RoleClient, m.GetClient().AclRole())
assert.Equal(t, acl.RoleClient, m.GetClientRole())
})
t.Run("Default", func(t *testing.T) {
m := &Session{}
assert.Equal(t, "", m.UserUID)
assert.Equal(t, "", m.User().UserUID)
assert.Equal(t, "", m.Client().ClientUID)
assert.Equal(t, "", m.Client().UserUID)
assert.Equal(t, acl.RoleNone, m.Client().AclRole())
assert.Equal(t, acl.RoleNone, m.ClientRole())
assert.Equal(t, "", m.GetUser().UserUID)
assert.Equal(t, "", m.GetClient().ClientUID)
assert.Equal(t, "", m.GetClient().UserUID)
assert.Equal(t, acl.RoleNone, m.GetClient().AclRole())
assert.Equal(t, acl.RoleNone, m.GetClientRole())
})
}
func TestSession_ClientRole(t *testing.T) {
t.Run("Alice", func(t *testing.T) {
m := SessionFixtures.Get("alice")
assert.Equal(t, acl.RoleNone, m.ClientRole())
assert.Equal(t, acl.RoleNone, m.GetClientRole())
})
t.Run("AliceTokenPersonal", func(t *testing.T) {
m := SessionFixtures.Get("alice_token_personal")
assert.Equal(t, acl.RoleClient, m.ClientRole())
assert.Equal(t, acl.RoleClient, m.GetClientRole())
})
t.Run("TokenMetrics", func(t *testing.T) {
m := SessionFixtures.Get("token_metrics")
assert.Equal(t, acl.RoleClient, m.ClientRole())
assert.Equal(t, acl.RoleClient, m.GetClientRole())
})
t.Run("TokenSettings", func(t *testing.T) {
m := SessionFixtures.Get("token_settings")
assert.Equal(t, acl.RoleClient, m.ClientRole())
assert.Equal(t, acl.RoleClient, m.GetClientRole())
})
t.Run("Default", func(t *testing.T) {
m := &Session{}
assert.Equal(t, acl.RoleNone, m.ClientRole())
assert.Equal(t, acl.RoleNone, m.GetClientRole())
})
}
func TestSession_ClientInfo(t *testing.T) {
t.Run("Alice", func(t *testing.T) {
m := SessionFixtures.Get("alice")
assert.Equal(t, "n/a", m.ClientInfo())
assert.Equal(t, "n/a", m.GetClientInfo())
})
t.Run("Metrics", func(t *testing.T) {
m := SessionFixtures.Get("client_metrics")
assert.Equal(t, "cs5cpu17n6gj2qo5", m.ClientInfo())
assert.Equal(t, "cs5cpu17n6gj2qo5", m.GetClientInfo())
})
}
@@ -375,11 +375,11 @@ func TestSession_NoClient(t *testing.T) {
func TestSession_SetClient(t *testing.T) {
t.Run("Alice", func(t *testing.T) {
m := SessionFixtures.Get("alice")
assert.Equal(t, acl.RoleNone, m.ClientRole())
assert.Equal(t, "", m.Client().ClientUID)
assert.Equal(t, acl.RoleNone, m.GetClientRole())
assert.Equal(t, "", m.GetClient().ClientUID)
m.SetClient(ClientFixtures.Pointer("alice"))
assert.Equal(t, acl.RoleClient, m.ClientRole())
assert.Equal(t, "cs5gfen1bgxz7s9i", m.Client().ClientUID)
assert.Equal(t, acl.RoleClient, m.GetClientRole())
assert.Equal(t, "cs5gfen1bgxz7s9i", m.GetClient().ClientUID)
})
}
@@ -387,36 +387,36 @@ func TestSession_SetClientName(t *testing.T) {
t.Run("Empty", func(t *testing.T) {
m := SessionFixtures.Get("alice_token_personal")
assert.Equal(t, "", m.ClientUID)
assert.Equal(t, "alice_token_personal", m.ClientName)
assert.Equal(t, "alice_token_personal", m.ClientInfo())
assert.Equal(t, "alice_token_personal", m.GetClientName())
assert.Equal(t, "alice_token_personal", m.GetClientInfo())
m.SetClientName("Foo Bar!")
assert.Equal(t, "", m.ClientUID)
assert.Equal(t, "Foo Bar!", m.ClientName)
assert.Equal(t, "Foo Bar!", m.ClientInfo())
assert.Equal(t, "Foo Bar!", m.GetClientName())
assert.Equal(t, "Foo Bar!", m.GetClientInfo())
m.SetClientName("")
assert.Equal(t, "Foo Bar!", m.ClientName)
assert.Equal(t, "Foo Bar!", m.ClientInfo())
assert.Equal(t, "Foo Bar!", m.GetClientName())
assert.Equal(t, "Foo Bar!", m.GetClientInfo())
})
t.Run("setNewID", func(t *testing.T) {
m := NewSession(0, 0)
assert.Equal(t, "", m.ClientUID)
assert.Equal(t, "", m.ClientName)
assert.Equal(t, report.NotAssigned, m.ClientInfo())
assert.Equal(t, "", m.GetClientName())
assert.Equal(t, report.NotAssigned, m.GetClientInfo())
m.SetClientName("Foo Bar!")
assert.Equal(t, "", m.ClientUID)
assert.Equal(t, "Foo Bar!", m.ClientName)
assert.Equal(t, "Foo Bar!", m.ClientInfo())
assert.Equal(t, "Foo Bar!", m.GetClientName())
assert.Equal(t, "Foo Bar!", m.GetClientInfo())
})
}
func TestSession_User(t *testing.T) {
t.Run("Alice", func(t *testing.T) {
m := FindSessionByRefID("sessxkkcabcd")
assert.Equal(t, "uqxetse3cy5eo9z2", m.User().UserUID)
assert.Equal(t, "uqxetse3cy5eo9z2", m.GetUser().UserUID)
})
t.Run("Default", func(t *testing.T) {
m := &Session{}
assert.Equal(t, "", m.User().UserUID)
assert.Equal(t, "", m.GetUser().UserUID)
})
}
@@ -434,15 +434,15 @@ func TestSession_UserInfo(t *testing.T) {
func TestSession_UserRole(t *testing.T) {
t.Run("Alice", func(t *testing.T) {
m := FindSessionByRefID("sessxkkcabcd")
assert.Equal(t, acl.RoleAdmin, m.UserRole())
assert.Equal(t, acl.RoleAdmin, m.GetUserRole())
})
t.Run("Bob", func(t *testing.T) {
m := FindSessionByRefID("sessxkkcabce")
assert.Equal(t, acl.RoleAdmin, m.UserRole())
assert.Equal(t, acl.RoleAdmin, m.GetUserRole())
})
t.Run("Default", func(t *testing.T) {
m := &Session{}
assert.Equal(t, acl.RoleNone, m.UserRole())
assert.Equal(t, acl.RoleNone, m.GetUserRole())
})
}
@@ -450,15 +450,15 @@ func TestSession_RefreshUser(t *testing.T) {
t.Run("Bob", func(t *testing.T) {
m := FindSessionByRefID("sessxkkcabce")
assert.Equal(t, "bob", m.Username())
assert.Equal(t, "bob", m.GetUserName())
m.UserName = "bobby"
assert.Equal(t, "bobby", m.Username())
assert.Equal(t, "bobby", m.GetUserName())
assert.Equal(t, "bob", m.RefreshUser().UserName)
assert.Equal(t, "bob", m.Username())
assert.Equal(t, "bob", m.GetUserName())
})
t.Run("Empty", func(t *testing.T) {
m := &Session{}
@@ -470,14 +470,14 @@ func TestSession_AuthInfo(t *testing.T) {
t.Run("bob", func(t *testing.T) {
m := FindSessionByRefID("sessxkkcabce")
i := m.AuthInfo()
i := m.GetAuthInfo()
assert.Equal(t, "Default", i)
})
t.Run("aliceTokenWebDAV", func(t *testing.T) {
m := FindSessionByRefID("sesshjtgx8qt")
i := m.AuthInfo()
i := m.GetAuthInfo()
assert.Equal(t, "Access Token", i)
})
@@ -521,8 +521,8 @@ func TestSession_SetMethod(t *testing.T) {
m := s.SetMethod("")
assert.Equal(t, authn.ProviderAccessToken, m.Provider())
assert.Equal(t, authn.MethodDefault, m.Method())
assert.Equal(t, authn.ProviderAccessToken, m.GetProvider())
assert.Equal(t, authn.MethodDefault, m.GetMethod())
})
t.Run("Test", func(t *testing.T) {
s := &Session{
@@ -534,8 +534,8 @@ func TestSession_SetMethod(t *testing.T) {
m := s.SetMethod("Test")
assert.Equal(t, authn.ProviderAccessToken, m.Provider())
assert.Equal(t, authn.Method("Test"), m.Method())
assert.Equal(t, authn.ProviderAccessToken, m.GetProvider())
assert.Equal(t, authn.Method("Test"), m.GetMethod())
})
t.Run("Test", func(t *testing.T) {
s := &Session{
@@ -547,8 +547,8 @@ func TestSession_SetMethod(t *testing.T) {
m := s.SetMethod(authn.MethodSession)
assert.Equal(t, authn.ProviderAccessToken, m.Provider())
assert.Equal(t, authn.MethodSession, m.Method())
assert.Equal(t, authn.ProviderAccessToken, m.GetProvider())
assert.Equal(t, authn.MethodSession, m.GetMethod())
})
t.Run("2FA", func(t *testing.T) {
s := &Session{
@@ -568,13 +568,13 @@ func TestSession_SetMethod(t *testing.T) {
func TestSession_SetProvider(t *testing.T) {
m := FindSessionByRefID("sessxkkcabce")
assert.Equal(t, authn.ProviderDefault, m.Provider())
assert.Equal(t, authn.ProviderDefault, m.GetProvider())
m.SetProvider("")
assert.Equal(t, authn.ProviderDefault, m.Provider())
assert.Equal(t, authn.ProviderDefault, m.GetProvider())
m.SetProvider(authn.ProviderLink)
assert.Equal(t, authn.ProviderLink, m.Provider())
assert.Equal(t, authn.ProviderLink, m.GetProvider())
m.SetProvider(authn.ProviderDefault)
assert.Equal(t, authn.ProviderDefault, m.Provider())
assert.Equal(t, authn.ProviderDefault, m.GetProvider())
}
func TestSession_ChangePassword(t *testing.T) {
@@ -729,7 +729,7 @@ func TestSession_SetGrantType(t *testing.T) {
assert.Equal(t, expected, m.GrantType)
m.SetGrantType(authn.GrantUndefined)
assert.Equal(t, expected, m.GrantType)
assert.Equal(t, authn.GrantPassword, m.AuthGrantType())
assert.Equal(t, authn.GrantPassword, m.GetGrantType())
})
t.Run("ClientCredentials", func(t *testing.T) {
client := ClientFixtures.Pointer("alice")
@@ -742,7 +742,7 @@ func TestSession_SetGrantType(t *testing.T) {
assert.Equal(t, expected, m.GrantType)
m.SetGrantType(authn.GrantUndefined)
assert.Equal(t, expected, m.GrantType)
assert.Equal(t, authn.GrantClientCredentials, m.AuthGrantType())
assert.Equal(t, authn.GrantClientCredentials, m.GetGrantType())
})
}
@@ -799,7 +799,7 @@ func TestSession_NotRegistered(t *testing.T) {
func TestSession_NoShares(t *testing.T) {
alice := FindSessionByRefID("sessxkkcabcd")
alice.RefreshUser()
alice.User().RefreshShares()
alice.GetUser().RefreshShares()
assert.False(t, alice.NoShares())
bob := FindSessionByRefID("sessxkkcabce")
@@ -835,13 +835,13 @@ func TestSession_HasRegisteredUser(t *testing.T) {
func TestSession_HasShare(t *testing.T) {
alice := FindSessionByRefID("sessxkkcabcd")
alice.RefreshUser()
alice.User().RefreshShares()
alice.GetUser().RefreshShares()
assert.True(t, alice.HasShare("as6sg6bxpogaaba9"))
assert.False(t, alice.HasShare("as6sg6bxpogaaba7"))
bob := FindSessionByRefID("sessxkkcabce")
bob.RefreshUser()
bob.User().RefreshShares()
bob.GetUser().RefreshShares()
assert.False(t, bob.HasShare("as6sg6bxpogaaba9"))
m := &Session{}
@@ -851,12 +851,12 @@ func TestSession_HasShare(t *testing.T) {
func TestSession_SharedUIDs(t *testing.T) {
alice := FindSessionByRefID("sessxkkcabcd")
alice.RefreshUser()
alice.User().RefreshShares()
alice.GetUser().RefreshShares()
assert.Equal(t, "as6sg6bxpogaaba9", alice.SharedUIDs()[0])
bob := FindSessionByRefID("sessxkkcabce")
bob.RefreshUser()
bob.User().RefreshShares()
bob.GetUser().RefreshShares()
assert.Empty(t, bob.SharedUIDs())
m := &Session{}
@@ -867,12 +867,12 @@ func TestSession_RedeemToken(t *testing.T) {
t.Run("bob", func(t *testing.T) {
bob := FindSessionByRefID("sessxkkcabce")
bob.RefreshUser()
bob.User().RefreshShares()
bob.GetUser().RefreshShares()
assert.Equal(t, 0, bob.RedeemToken("1234"))
assert.Empty(t, bob.User().UserShares)
assert.Empty(t, bob.GetUser().UserShares)
assert.Equal(t, 1, bob.RedeemToken("1jxf3jfn2k"))
bob.User().RefreshShares()
assert.Equal(t, "as6sg6bxpogaaba8", bob.User().UserShares[0].ShareUID)
bob.GetUser().RefreshShares()
assert.Equal(t, "as6sg6bxpogaaba8", bob.GetUser().UserShares[0].ShareUID)
})
t.Run("Empty session", func(t *testing.T) {
m := &Session{}

View File

@@ -38,7 +38,7 @@ func UserAlbums(frm form.SearchAlbums, sess *entity.Session) (results AlbumResul
// Check session permissions and apply as needed.
if sess != nil {
user := sess.User()
user := sess.GetUser()
aclRole := user.AclRole()
// Determine resource to check.

View File

@@ -135,7 +135,7 @@ func searchPhotos(frm form.SearchPhotos, sess *entity.Session, resultCols string
// Check session permissions and apply as needed.
if sess != nil {
user := sess.User()
user := sess.GetUser()
aclRole := user.AclRole()
// Exclude private content.
@@ -156,7 +156,7 @@ func searchPhotos(frm form.SearchPhotos, sess *entity.Session, resultCols string
}
// Visitors and other restricted users can only access shared content.
if frm.Scope != "" && album.CreatedBy != user.UserUID && !sess.HasShare(frm.Scope) && (sess.User().HasSharedAccessOnly(acl.ResourcePhotos) || sess.NotRegistered()) ||
if frm.Scope != "" && album.CreatedBy != user.UserUID && !sess.HasShare(frm.Scope) && (sess.GetUser().HasSharedAccessOnly(acl.ResourcePhotos) || sess.NotRegistered()) ||
frm.Scope == "" && acl.Rules.Deny(acl.ResourcePhotos, aclRole, acl.ActionSearch) {
event.AuditErr([]string{sess.IP(), "session %s", "%s %s as %s", authn.Denied}, sess.RefID, acl.ActionSearch.String(), string(acl.ResourcePhotos), aclRole)
return PhotoResults{}, 0, ErrForbidden

View File

@@ -118,7 +118,7 @@ func UserPhotosGeo(frm form.SearchPhotosGeo, sess *entity.Session) (results GeoR
// Check session permissions and apply as needed.
if sess != nil {
user := sess.User()
user := sess.GetUser()
aclRole := user.AclRole()
// Exclude private content.
@@ -134,7 +134,7 @@ func UserPhotosGeo(frm form.SearchPhotosGeo, sess *entity.Session) (results GeoR
}
// Visitors and other restricted users can only access shared content.
if frm.Scope != "" && album.CreatedBy != user.UserUID && !sess.HasShare(frm.Scope) && (sess.User().HasSharedAccessOnly(acl.ResourcePlaces) || sess.NotRegistered()) ||
if frm.Scope != "" && album.CreatedBy != user.UserUID && !sess.HasShare(frm.Scope) && (sess.GetUser().HasSharedAccessOnly(acl.ResourcePlaces) || sess.NotRegistered()) ||
frm.Scope == "" && acl.Rules.Deny(acl.ResourcePlaces, aclRole, acl.ActionSearch) {
event.AuditErr([]string{sess.IP(), "session %s", "%s %s as %s", authn.Denied}, sess.RefID, acl.ActionSearch.String(), string(acl.ResourcePlaces), aclRole)
return GeoResults{}, ErrForbidden

View File

@@ -108,32 +108,32 @@ func WebDAVAuth(conf *config.Config) gin.HandlerFunc {
// Ignore and try basic auth next.
} else if !sess.HasUser() || user == nil {
// Log error if session does not belong to an authorized user account.
event.AuditErr([]string{clientIp, "webdav", "client %s", "session %s", "access without user account", authn.Denied}, clean.Log(sess.ClientInfo()), sess.RefID)
event.AuditErr([]string{clientIp, "webdav", "client %s", "session %s", "access without user account", authn.Denied}, clean.Log(sess.GetClientInfo()), sess.RefID)
WebDAVAbortUnauthorized(c)
return
} else if sess.IsClient() && sess.InsufficientScope(acl.ResourceWebDAV, nil) {
// Log error if the client is allowed to access webdav based on its scope.
message := authn.ErrInsufficientScope.Error()
event.AuditWarn([]string{clientIp, "webdav", "client %s", "session %s", "access as %s", message}, clean.Log(sess.ClientInfo()), sess.RefID, clean.LogQuote(user.Username()))
event.AuditWarn([]string{clientIp, "webdav", "client %s", "session %s", "access as %s", message}, clean.Log(sess.GetClientInfo()), sess.RefID, clean.LogQuote(user.Username()))
WebDAVAbortUnauthorized(c)
return
} else if !user.CanUseWebDAV() {
// Log warning if WebDAV is disabled for this account.
message := authn.ErrWebDAVAccessDisabled.Error()
event.AuditWarn([]string{clientIp, "webdav", "client %s", "session %s", "access as %s", message}, clean.Log(sess.ClientInfo()), sess.RefID, clean.LogQuote(user.Username()))
event.AuditWarn([]string{clientIp, "webdav", "client %s", "session %s", "access as %s", message}, clean.Log(sess.GetClientInfo()), sess.RefID, clean.LogQuote(user.Username()))
WebDAVAbortUnauthorized(c)
return
} else if username != "" && !strings.EqualFold(clean.Username(username), user.Username()) {
limiter.Auth.Reserve(clientIp)
// Log warning if auth token username and specified username do not match.
message := authn.ErrUsernameDoesNotMatch.Error()
event.AuditWarn([]string{clientIp, "webdav", "client %s", "session %s", "access as %s", message}, clean.Log(sess.ClientInfo()), sess.RefID, clean.LogQuote(user.Username()))
event.AuditWarn([]string{clientIp, "webdav", "client %s", "session %s", "access as %s", message}, clean.Log(sess.GetClientInfo()), sess.RefID, clean.LogQuote(user.Username()))
WebDAVAbortUnauthorized(c)
return
} else if err := fs.MkdirAll(filepath.Join(conf.OriginalsPath(), user.GetUploadPath())); err != nil {
// Log warning if upload path could not be created.
message := authn.ErrFailedToCreateUploadPath.Error()
event.AuditWarn([]string{clientIp, "webdav", "client %s", "session %s", "access as %s", message}, clean.Log(sess.ClientInfo()), sess.RefID, clean.LogQuote(user.Username()))
event.AuditWarn([]string{clientIp, "webdav", "client %s", "session %s", "access as %s", message}, clean.Log(sess.GetClientInfo()), sess.RefID, clean.LogQuote(user.Username()))
WebDAVAbortServerError(c)
return
} else {
@@ -141,7 +141,7 @@ func WebDAVAuth(conf *config.Config) gin.HandlerFunc {
sess.UpdateLastActive(true)
// Log successful authentication.
event.AuditInfo([]string{clientIp, "webdav", "client %s", "session %s", "access as %s", authn.Succeeded}, clean.Log(sess.ClientInfo()), sess.RefID, clean.LogQuote(user.Username()))
event.AuditInfo([]string{clientIp, "webdav", "client %s", "session %s", "access as %s", authn.Succeeded}, clean.Log(sess.GetClientInfo()), sess.RefID, clean.LogQuote(user.Username()))
event.LoginInfo(clientIp, "webdav", user.Username(), api.UserAgent(c))
// Cache authentication to improve performance.

View File

@@ -56,5 +56,5 @@ func WebDAVAuthSession(c *gin.Context, authToken string) (sess *entity.Session,
sess.UpdateContext(c)
// Return session and user.
return sess, sess.User(), sid, false
return sess, sess.GetUser(), sid, false
}

View File

@@ -14,7 +14,7 @@ type NodeOpts struct {
// NodeOptsForSession returns the default exposure policy for a session.
// Admin users see internalUrl and DB metadata; others get a redacted view.
func NodeOptsForSession(s *entity.Session) NodeOpts {
if s != nil && s.User() != nil && s.User().IsAdmin() {
if s != nil && s.GetUser() != nil && s.GetUser().IsAdmin() {
return NodeOpts{IncludeInternalURL: true, IncludeDBMeta: true}
}