mirror of
https://github.com/h44z/wg-portal.git
synced 2026-02-25 03:46:23 +00:00
Merge commit from fork
* fix: improve user permission checks * fix: improve user permission checks
This commit is contained in:
@@ -54,6 +54,17 @@ func (u UserService) GetAllUsers(ctx context.Context) ([]domain.User, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (u UserService) UpdateUser(ctx context.Context, user *domain.User) (*domain.User, error) {
|
func (u UserService) UpdateUser(ctx context.Context, user *domain.User) (*domain.User, error) {
|
||||||
|
sessionUser := domain.GetUserInfo(ctx)
|
||||||
|
currentUser, err := u.users.GetUser(ctx, user.Identifier)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// if this endpoint is used by non-admins, make sure that the user can only modify a specific subset of attributes
|
||||||
|
if !sessionUser.IsAdmin {
|
||||||
|
user.CopyAdminAttributes(currentUser, u.cfg.Advanced.ApiAdminOnly)
|
||||||
|
}
|
||||||
|
|
||||||
return u.users.UpdateUser(ctx, user)
|
return u.users.UpdateUser(ctx, user)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -272,8 +272,9 @@ func (m Manager) DeactivateApi(ctx context.Context, id domain.UserIdentifier) (*
|
|||||||
func (m Manager) validateModifications(ctx context.Context, old, new *domain.User) error {
|
func (m Manager) validateModifications(ctx context.Context, old, new *domain.User) error {
|
||||||
currentUser := domain.GetUserInfo(ctx)
|
currentUser := domain.GetUserInfo(ctx)
|
||||||
|
|
||||||
if currentUser.Id != new.Identifier && !currentUser.IsAdmin {
|
adminErrors := m.validateAdminModifications(ctx, old, new)
|
||||||
return fmt.Errorf("insufficient permissions")
|
if adminErrors != nil {
|
||||||
|
return adminErrors
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := old.EditAllowed(new); err != nil && currentUser.Id != domain.SystemAdminContextUserInfo().Id {
|
if err := old.EditAllowed(new); err != nil && currentUser.Id != domain.SystemAdminContextUserInfo().Id {
|
||||||
@@ -303,6 +304,46 @@ func (m Manager) validateModifications(ctx context.Context, old, new *domain.Use
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m Manager) validateAdminModifications(ctx context.Context, old, new *domain.User) error {
|
||||||
|
currentUser := domain.GetUserInfo(ctx)
|
||||||
|
|
||||||
|
if currentUser.IsAdmin {
|
||||||
|
if currentUser.Id == old.Identifier && !new.IsAdmin {
|
||||||
|
return fmt.Errorf("cannot remove own admin rights: %w", domain.ErrInvalidData)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil // admins can do (almost) everything
|
||||||
|
}
|
||||||
|
|
||||||
|
// non-admins can only modify very their own profile data
|
||||||
|
|
||||||
|
if currentUser.Id != new.Identifier {
|
||||||
|
return fmt.Errorf("insufficient permissions: %w", domain.ErrInvalidData)
|
||||||
|
}
|
||||||
|
|
||||||
|
if new.IsAdmin {
|
||||||
|
return fmt.Errorf("cannot grant admin rights: %w", domain.ErrInvalidData)
|
||||||
|
}
|
||||||
|
|
||||||
|
if new.Notes != old.Notes {
|
||||||
|
return fmt.Errorf("cannot update notes: %w", domain.ErrInvalidData)
|
||||||
|
}
|
||||||
|
|
||||||
|
if old.Locked != new.Locked || old.LockedReason != new.LockedReason {
|
||||||
|
return fmt.Errorf("cannot change lock state: %w", domain.ErrInvalidData)
|
||||||
|
}
|
||||||
|
|
||||||
|
if old.Disabled != new.Disabled || old.DisabledReason != new.DisabledReason {
|
||||||
|
return fmt.Errorf("cannot change disabled state: %w", domain.ErrInvalidData)
|
||||||
|
}
|
||||||
|
|
||||||
|
if old.PersistLocalChanges != new.PersistLocalChanges {
|
||||||
|
return fmt.Errorf("cannot change disabled state: %w", domain.ErrInvalidData)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (m Manager) validateCreation(ctx context.Context, new *domain.User) error {
|
func (m Manager) validateCreation(ctx context.Context, new *domain.User) error {
|
||||||
currentUser := domain.GetUserInfo(ctx)
|
currentUser := domain.GetUserInfo(ctx)
|
||||||
|
|
||||||
@@ -374,6 +415,10 @@ func (m Manager) validateDeletion(ctx context.Context, del *domain.User) error {
|
|||||||
func (m Manager) validateApiChange(ctx context.Context, user *domain.User) error {
|
func (m Manager) validateApiChange(ctx context.Context, user *domain.User) error {
|
||||||
currentUser := domain.GetUserInfo(ctx)
|
currentUser := domain.GetUserInfo(ctx)
|
||||||
|
|
||||||
|
if !currentUser.IsAdmin && m.cfg.Advanced.ApiAdminOnly {
|
||||||
|
return fmt.Errorf("insufficient permissions to change API access: %w", domain.ErrNoPermission)
|
||||||
|
}
|
||||||
|
|
||||||
if currentUser.Id != user.Identifier {
|
if currentUser.Id != user.Identifier {
|
||||||
return fmt.Errorf("cannot change API access of user: %w", domain.ErrNoPermission)
|
return fmt.Errorf("cannot change API access of user: %w", domain.ErrNoPermission)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -212,6 +212,33 @@ func (u *User) CopyCalculatedAttributes(src *User, withAuthentications bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CopyAdminAttributes copies all attributes from the given user except password, passkey and
|
||||||
|
// api-token if apiAdminOnly is false.
|
||||||
|
func (u *User) CopyAdminAttributes(src *User, apiAdminOnly bool) {
|
||||||
|
u.BaseModel = src.BaseModel
|
||||||
|
u.Identifier = src.Identifier
|
||||||
|
u.Email = src.Email
|
||||||
|
u.Source = src.Source
|
||||||
|
u.ProviderName = src.ProviderName
|
||||||
|
u.IsAdmin = src.IsAdmin
|
||||||
|
u.Authentications = src.Authentications
|
||||||
|
u.PersistLocalChanges = src.PersistLocalChanges
|
||||||
|
u.Firstname = src.Firstname
|
||||||
|
u.Lastname = src.Lastname
|
||||||
|
u.Phone = src.Phone
|
||||||
|
u.Department = src.Department
|
||||||
|
u.Notes = src.Notes
|
||||||
|
u.Disabled = src.Disabled
|
||||||
|
u.DisabledReason = src.DisabledReason
|
||||||
|
u.Locked = src.Locked
|
||||||
|
u.LockedReason = src.LockedReason
|
||||||
|
u.LinkedPeerCount = src.LinkedPeerCount
|
||||||
|
if apiAdminOnly {
|
||||||
|
u.ApiToken = src.ApiToken
|
||||||
|
u.ApiTokenCreated = src.ApiTokenCreated
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// MergeAuthSources merges the given authentication sources with the existing ones.
|
// MergeAuthSources merges the given authentication sources with the existing ones.
|
||||||
// Already existing sources are not overwritten, nor will be added any duplicates.
|
// Already existing sources are not overwritten, nor will be added any duplicates.
|
||||||
func (u *User) MergeAuthSources(extSources ...UserAuthentication) {
|
func (u *User) MergeAuthSources(extSources ...UserAuthentication) {
|
||||||
|
|||||||
Reference in New Issue
Block a user