mirror of
https://github.com/pocket-id/pocket-id.git
synced 2026-10-11 04:09:05 +02:00
fix: push group removals made on the user page to SCIM (#1830)
This commit is contained in:
@@ -594,6 +594,9 @@ func (s *UserService) UpdateUserGroups(ctx context.Context, id string, userGroup
|
||||
return !slices.Contains(userGroupIds, group.ID)
|
||||
})
|
||||
|
||||
// Remember the current groups, because the groups the user leaves change their membership too
|
||||
previousGroupIDs := userGroupIDs(user.UserGroups)
|
||||
|
||||
// Fetch the groups based on userGroupIds
|
||||
var groups []model.UserGroup
|
||||
if len(userGroupIds) > 0 {
|
||||
@@ -623,14 +626,10 @@ func (s *UserService) UpdateUserGroups(ctx context.Context, id string, userGroup
|
||||
return model.User{}, err
|
||||
}
|
||||
|
||||
// Update the UpdatedAt field for all affected groups
|
||||
now := datatype.DateTime(time.Now())
|
||||
for _, group := range groups {
|
||||
group.UpdatedAt = &now
|
||||
err = tx.WithContext(ctx).Save(&group).Error
|
||||
if err != nil {
|
||||
return model.User{}, err
|
||||
}
|
||||
// Bump the UpdatedAt of every group the user joined or left, so the SCIM sync pushes the new membership
|
||||
err = s.touchUserGroups(ctx, tx, append(previousGroupIDs, userGroupIDs(groups)...))
|
||||
if err != nil {
|
||||
return model.User{}, err
|
||||
}
|
||||
|
||||
err = tx.Commit().Error
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"encoding/json"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
"uuid"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -11,6 +12,8 @@ import (
|
||||
"github.com/pocket-id/pocket-id/backend/internal/appconfig"
|
||||
"github.com/pocket-id/pocket-id/backend/internal/apperror"
|
||||
"github.com/pocket-id/pocket-id/backend/internal/dto"
|
||||
"github.com/pocket-id/pocket-id/backend/internal/model"
|
||||
datatype "github.com/pocket-id/pocket-id/backend/internal/model/types"
|
||||
"github.com/pocket-id/pocket-id/backend/internal/storage"
|
||||
testutils "github.com/pocket-id/pocket-id/backend/internal/utils/testing"
|
||||
)
|
||||
@@ -141,3 +144,35 @@ func TestCreateUserBumpsDefaultGroupUpdatedAt(t *testing.T) {
|
||||
require.NotNil(t, updated.UpdatedAt, "adding a default group member must bump the group's UpdatedAt")
|
||||
require.Len(t, updated.Users, 1)
|
||||
}
|
||||
|
||||
func TestUpdateUserGroupsBumpsRemovedGroupUpdatedAt(t *testing.T) {
|
||||
config := &appconfig.AppConfigModel{RequireUserEmail: "false"}
|
||||
userService, groupService := newTestUserService(t)
|
||||
|
||||
oldGroup, err := groupService.Create(t.Context(), dto.UserGroupCreateDto{Name: "old", FriendlyName: "Old"})
|
||||
require.NoError(t, err)
|
||||
newGroup, err := groupService.Create(t.Context(), dto.UserGroupCreateDto{Name: "new", FriendlyName: "New"})
|
||||
require.NoError(t, err)
|
||||
|
||||
user, err := userService.CreateUser(t.Context(), config, dto.UserCreateDto{
|
||||
Username: "mover",
|
||||
FirstName: "Group",
|
||||
LastName: "Mover",
|
||||
UserGroupIds: []string{oldGroup.ID},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
// Backdate both groups so a bump is visible regardless of the timestamp precision
|
||||
past := time.Now().Add(-time.Hour)
|
||||
require.NoError(t, userService.db.Model(&model.UserGroup{}).Where("id IN ?", []string{oldGroup.ID, newGroup.ID}).Update("updated_at", datatype.DateTime(past)).Error)
|
||||
|
||||
// Move the user from the old group to the new one, as the user's group selection does
|
||||
_, err = userService.UpdateUserGroups(t.Context(), user.ID, []string{newGroup.ID})
|
||||
require.NoError(t, err)
|
||||
|
||||
for _, groupID := range []string{oldGroup.ID, newGroup.ID} {
|
||||
updated, err := groupService.Get(t.Context(), groupID)
|
||||
require.NoError(t, err)
|
||||
require.True(t, updated.LastModified().After(past), "group %s changed membership, so its UpdatedAt must be bumped", updated.Name)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user