Fix resolve not sticking: heal stale UserPermission IDs and stop scroll jump

- After push_to_keycloak membership resolve, update any UserPermission
  rows with stale keycloak_user_id to match the user's current KC ID.
  This was the root cause: resolve added user to KC by their current ID,
  but the discrepancy scan still saw the old ID in UserPermission.
- Remove removeQueries/invalidateQueries from resolve hooks — wiping the
  cache caused the UI to unmount to "Not yet scanned" and re-mount,
  jumping to the top. The component's refetch() already handles refresh.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-23 19:37:26 -07:00
parent 741343f28f
commit 6a2cc72d88
2 changed files with 16 additions and 12 deletions

View File

@@ -638,6 +638,22 @@ def _resolve_membership(kc: KeycloakClient, action: str, params: dict) -> dict:
try:
kc.add_user_to_group(user.keycloak_id, kc_group_id)
# Fix any stale UserPermission rows for this user/project so the
# next discrepancy scan sees the correct keycloak_user_id.
stale_perms = UserPermission.query.filter_by(
project_key=project_key,
).filter(
(UserPermission.user_id == user.id) |
(UserPermission.keycloak_user_id == params.get("keycloak_user_id"))
).all()
for perm in stale_perms:
if perm.keycloak_user_id != user.keycloak_id:
perm.keycloak_user_id = user.keycloak_id
if perm.user_id != user.id:
perm.user_id = user.id
db.session.commit()
return {"status": "resolved", "action": action, "local_user_id": local_user_id, "project_key": project_key}
except KeycloakError as e:
return {"status": "error", "message": str(e)}

View File

@@ -104,17 +104,11 @@ export function useKeycloakDiscrepancies() {
}
export function useResolveDiscrepancy() {
const queryClient = useQueryClient();
return useMutation<unknown, unknown, ResolveRequest>({
mutationFn: async (params) => {
const { data } = await api.post("/settings/keycloak-resolve", params);
return data;
},
onSuccess: () => {
queryClient.removeQueries({
queryKey: ["settings", "keycloak-discrepancies"],
});
},
});
}
@@ -140,16 +134,10 @@ export function useSyncKeycloakUsers() {
}
export function useResolveAllDiscrepancies() {
const queryClient = useQueryClient();
return useMutation<ResolveAllResponse, unknown, ResolveAllRequest>({
mutationFn: async (params) => {
const { data } = await api.post("/settings/keycloak-resolve-all", params);
return data;
},
onSuccess: () => {
queryClient.removeQueries({
queryKey: ["settings", "keycloak-discrepancies"],
});
},
});
}