update api users and groups and users 15
This commit is contained in:
parent
d1780b748b
commit
a7c9651690
@ -75,11 +75,11 @@ export async function GET() {
|
|||||||
|
|
||||||
console.log("Filtered users count:", filteredUsers.length);
|
console.log("Filtered users count:", filteredUsers.length);
|
||||||
|
|
||||||
// Fetch groups for each user
|
// Fetch roles for each user
|
||||||
const usersWithGroups = await Promise.all(filteredUsers.map(async (user: any) => {
|
const usersWithRoles = await Promise.all(filteredUsers.map(async (user: any) => {
|
||||||
try {
|
try {
|
||||||
const groupsResponse = await fetch(
|
const rolesResponse = await fetch(
|
||||||
`${process.env.KEYCLOAK_BASE_URL}/admin/realms/${process.env.KEYCLOAK_REALM}/users/${user.id}/groups`,
|
`${process.env.KEYCLOAK_BASE_URL}/admin/realms/${process.env.KEYCLOAK_REALM}/users/${user.id}/role-mappings/realm`,
|
||||||
{
|
{
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${tokenData.access_token}`,
|
Authorization: `Bearer ${tokenData.access_token}`,
|
||||||
@ -88,11 +88,16 @@ export async function GET() {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
let groups = [];
|
let roles = [];
|
||||||
if (groupsResponse.ok) {
|
if (rolesResponse.ok) {
|
||||||
const groupsData = await groupsResponse.json();
|
const rolesData = await rolesResponse.json();
|
||||||
groups = groupsData.map((group: any) => group.name);
|
roles = rolesData
|
||||||
console.log(`Groups for user ${user.username}:`, groups);
|
.filter((role: any) =>
|
||||||
|
!role.name.startsWith('default-roles-') &&
|
||||||
|
!['offline_access', 'uma_authorization'].includes(role.name)
|
||||||
|
)
|
||||||
|
.map((role: any) => role.name);
|
||||||
|
console.log(`Roles for user ${user.username}:`, roles);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -102,10 +107,11 @@ export async function GET() {
|
|||||||
lastName: user.lastName || '',
|
lastName: user.lastName || '',
|
||||||
email: user.email,
|
email: user.email,
|
||||||
createdTimestamp: user.createdTimestamp,
|
createdTimestamp: user.createdTimestamp,
|
||||||
roles: groups,
|
enabled: user.enabled,
|
||||||
|
roles: roles,
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Error fetching groups for user ${user.id}:`, error);
|
console.error(`Error fetching roles for user ${user.id}:`, error);
|
||||||
return {
|
return {
|
||||||
id: user.id,
|
id: user.id,
|
||||||
username: user.username,
|
username: user.username,
|
||||||
@ -113,17 +119,18 @@ export async function GET() {
|
|||||||
lastName: user.lastName || '',
|
lastName: user.lastName || '',
|
||||||
email: user.email,
|
email: user.email,
|
||||||
createdTimestamp: user.createdTimestamp,
|
createdTimestamp: user.createdTimestamp,
|
||||||
|
enabled: user.enabled,
|
||||||
roles: [],
|
roles: [],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
console.log("Final users data:", usersWithGroups.map(u => ({
|
console.log("Final users data:", usersWithRoles.map(u => ({
|
||||||
username: u.username,
|
username: u.username,
|
||||||
roles: u.roles,
|
roles: u.roles,
|
||||||
})));
|
})));
|
||||||
|
|
||||||
return NextResponse.json(usersWithGroups);
|
return NextResponse.json(usersWithRoles);
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error:", error);
|
console.error("Error:", error);
|
||||||
|
|||||||
@ -41,6 +41,8 @@ interface User {
|
|||||||
id: string;
|
id: string;
|
||||||
username: string;
|
username: string;
|
||||||
email: string;
|
email: string;
|
||||||
|
lastName: string;
|
||||||
|
firstName: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ApiError {
|
interface ApiError {
|
||||||
@ -249,22 +251,32 @@ export function GroupsTable({ userRole = [] }: GroupsTableProps) {
|
|||||||
body: JSON.stringify({ userId }),
|
body: JSON.stringify({ userId }),
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!response.ok) throw new Error("Failed to add member");
|
if (!response.ok) {
|
||||||
|
throw new Error("Failed to add member");
|
||||||
|
}
|
||||||
|
|
||||||
const user = availableUsers.find(u => u.id === userId);
|
// Update the members list
|
||||||
if (user) {
|
const updatedMember = availableUsers.find(u => u.id === userId);
|
||||||
setGroupMembers(prev => [...prev, user]);
|
if (updatedMember) {
|
||||||
|
setGroupMembers(prev => [...prev, updatedMember]);
|
||||||
setAvailableUsers(prev => prev.filter(u => u.id !== userId));
|
setAvailableUsers(prev => prev.filter(u => u.id !== userId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update the group's member count in the table
|
||||||
|
setGroups(prev => prev.map(group =>
|
||||||
|
group.id === selectedGroup.id
|
||||||
|
? { ...group, membersCount: group.membersCount + 1 }
|
||||||
|
: group
|
||||||
|
));
|
||||||
|
|
||||||
toast({
|
toast({
|
||||||
title: "Succès",
|
title: "Success",
|
||||||
description: "Membre ajouté avec succès",
|
description: "Member added successfully",
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
toast({
|
toast({
|
||||||
title: "Erreur",
|
title: "Error",
|
||||||
description: "Erreur lors de l'ajout du membre",
|
description: error instanceof Error ? error.message : "An error occurred",
|
||||||
variant: "destructive",
|
variant: "destructive",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -278,22 +290,32 @@ export function GroupsTable({ userRole = [] }: GroupsTableProps) {
|
|||||||
method: "DELETE",
|
method: "DELETE",
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!response.ok) throw new Error("Failed to remove member");
|
if (!response.ok) {
|
||||||
|
throw new Error("Failed to remove member");
|
||||||
const user = groupMembers.find(u => u.id === userId);
|
|
||||||
if (user) {
|
|
||||||
setAvailableUsers(prev => [...prev, user]);
|
|
||||||
setGroupMembers(prev => prev.filter(u => u.id !== userId));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update the members list
|
||||||
|
const removedMember = groupMembers.find(u => u.id === userId);
|
||||||
|
if (removedMember) {
|
||||||
|
setGroupMembers(prev => prev.filter(u => u.id !== userId));
|
||||||
|
setAvailableUsers(prev => [...prev, removedMember]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the group's member count in the table
|
||||||
|
setGroups(prev => prev.map(group =>
|
||||||
|
group.id === selectedGroup.id
|
||||||
|
? { ...group, membersCount: Math.max(0, group.membersCount - 1) }
|
||||||
|
: group
|
||||||
|
));
|
||||||
|
|
||||||
toast({
|
toast({
|
||||||
title: "Succès",
|
title: "Success",
|
||||||
description: "Membre retiré avec succès",
|
description: "Member removed successfully",
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
toast({
|
toast({
|
||||||
title: "Erreur",
|
title: "Error",
|
||||||
description: "Erreur lors du retrait du membre",
|
description: error instanceof Error ? error.message : "An error occurred",
|
||||||
variant: "destructive",
|
variant: "destructive",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -439,16 +461,16 @@ export function GroupsTable({ userRole = [] }: GroupsTableProps) {
|
|||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<Label>Membres actuels</Label>
|
<Label>Current Members</Label>
|
||||||
<div className="max-h-[200px] overflow-y-auto border rounded-md p-2">
|
<div className="max-h-[200px] overflow-y-auto border rounded-md p-2">
|
||||||
{groupMembers.length === 0 ? (
|
{groupMembers.length === 0 ? (
|
||||||
<p className="text-sm text-muted-foreground">Aucun membre</p>
|
<p className="text-sm text-muted-foreground">No members</p>
|
||||||
) : (
|
) : (
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
{groupMembers.map((member) => (
|
{groupMembers.map((member) => (
|
||||||
<div key={member.id} className="flex items-center justify-between p-2 hover:bg-muted rounded-md">
|
<div key={member.id} className="flex items-center justify-between p-2 hover:bg-muted rounded-md">
|
||||||
<div>
|
<div>
|
||||||
<p className="font-medium">{member.username}</p>
|
<p className="font-medium">{member.lastName} {member.firstName}</p>
|
||||||
<p className="text-sm text-muted-foreground">{member.email}</p>
|
<p className="text-sm text-muted-foreground">{member.email}</p>
|
||||||
</div>
|
</div>
|
||||||
<Button
|
<Button
|
||||||
@ -465,26 +487,28 @@ export function GroupsTable({ userRole = [] }: GroupsTableProps) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<Label>Ajouter un membre</Label>
|
<Label>Add Member</Label>
|
||||||
<div className="max-h-[200px] overflow-y-auto border rounded-md p-2">
|
<div className="max-h-[200px] overflow-y-auto border rounded-md p-2">
|
||||||
{availableUsers.length === 0 ? (
|
{availableUsers.length === 0 ? (
|
||||||
<p className="text-sm text-muted-foreground">Aucun utilisateur disponible</p>
|
<p className="text-sm text-muted-foreground">No users available</p>
|
||||||
) : (
|
) : (
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
{availableUsers.map((user) => (
|
{availableUsers
|
||||||
<div key={user.id} className="flex items-center justify-between p-2 hover:bg-muted rounded-md">
|
.sort((a, b) => (a.lastName + a.firstName).localeCompare(b.lastName + b.firstName))
|
||||||
<div>
|
.map((user) => (
|
||||||
<p className="font-medium">{user.username}</p>
|
<div key={user.id} className="flex items-center justify-between p-2 hover:bg-muted rounded-md">
|
||||||
<p className="text-sm text-muted-foreground">{user.email}</p>
|
<div>
|
||||||
|
<p className="font-medium">{user.lastName} {user.firstName}</p>
|
||||||
|
<p className="text-sm text-muted-foreground">{user.email}</p>
|
||||||
|
</div>
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="sm"
|
||||||
|
onClick={() => handleAddMember(user.id)}
|
||||||
|
>
|
||||||
|
<Plus className="h-4 w-4" />
|
||||||
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<Button
|
|
||||||
variant="ghost"
|
|
||||||
size="sm"
|
|
||||||
onClick={() => handleAddMember(user.id)}
|
|
||||||
>
|
|
||||||
<Plus className="h-4 w-4" />
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -507,12 +507,12 @@ export function UsersTable({ userRole = [] }: UsersTableProps) {
|
|||||||
<Table>
|
<Table>
|
||||||
<TableHeader>
|
<TableHeader>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableHead>Nom d'utilisateur</TableHead>
|
<TableHead>Username</TableHead>
|
||||||
<TableHead>Prénom</TableHead>
|
<TableHead>First Name</TableHead>
|
||||||
<TableHead>Nom</TableHead>
|
<TableHead>Last Name</TableHead>
|
||||||
<TableHead>Email</TableHead>
|
<TableHead>Email</TableHead>
|
||||||
<TableHead>Date d'inscription</TableHead>
|
<TableHead>Created At</TableHead>
|
||||||
<TableHead>Rôles</TableHead>
|
<TableHead>Roles</TableHead>
|
||||||
<TableHead className="text-right">Actions</TableHead>
|
<TableHead className="text-right">Actions</TableHead>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</TableHeader>
|
</TableHeader>
|
||||||
@ -526,7 +526,15 @@ export function UsersTable({ userRole = [] }: UsersTableProps) {
|
|||||||
<TableCell>
|
<TableCell>
|
||||||
{new Date(user.createdTimestamp).toLocaleDateString()}
|
{new Date(user.createdTimestamp).toLocaleDateString()}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell>{(user.roles || []).join(", ") || "-"}</TableCell>
|
<TableCell>
|
||||||
|
<div className="flex flex-wrap gap-1">
|
||||||
|
{(user.roles || []).map((role) => (
|
||||||
|
<span key={role} className="inline-flex items-center rounded-full bg-blue-50 px-2 py-1 text-xs font-medium text-blue-700 ring-1 ring-inset ring-blue-700/10">
|
||||||
|
{role}
|
||||||
|
</span>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</TableCell>
|
||||||
<TableCell className="text-right">
|
<TableCell className="text-right">
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
<DropdownMenuTrigger asChild>
|
<DropdownMenuTrigger asChild>
|
||||||
@ -695,34 +703,32 @@ export function UsersTable({ userRole = [] }: UsersTableProps) {
|
|||||||
}}>
|
}}>
|
||||||
<DialogContent>
|
<DialogContent>
|
||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
<DialogTitle>Gérer les rôles de {selectedUser?.username}</DialogTitle>
|
<DialogTitle>Manage roles for {selectedUser?.username}</DialogTitle>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<Label>Rôles</Label>
|
<Label>Available Roles</Label>
|
||||||
<div className="grid grid-cols-2 gap-2">
|
<div className="grid grid-cols-2 gap-2 max-h-[200px] overflow-y-auto border rounded-md p-2">
|
||||||
{roles.map((role) => (
|
{roles.map((role) => (
|
||||||
<div key={role.id} className="flex items-center space-x-2 p-2 rounded-md hover:bg-gray-100">
|
<div key={role.id} className="flex items-center space-x-2 p-2 rounded-md hover:bg-gray-100">
|
||||||
<input
|
<Checkbox
|
||||||
type="checkbox"
|
|
||||||
id={`manage-role-${role.id}`}
|
id={`manage-role-${role.id}`}
|
||||||
checked={formData.roles.includes(role.name)}
|
checked={formData.roles.includes(role.name)}
|
||||||
onChange={(e) => {
|
onCheckedChange={(checked) => {
|
||||||
setFormData(prev => ({
|
setFormData(prev => ({
|
||||||
...prev,
|
...prev,
|
||||||
roles: e.target.checked
|
roles: checked
|
||||||
? [...prev.roles, role.name]
|
? [...prev.roles, role.name]
|
||||||
: prev.roles.filter(r => r !== role.name)
|
: prev.roles.filter(r => r !== role.name)
|
||||||
}));
|
}));
|
||||||
}}
|
}}
|
||||||
className="h-4 w-4 text-primary focus:ring-primary"
|
|
||||||
/>
|
/>
|
||||||
<label
|
<Label
|
||||||
htmlFor={`manage-role-${role.id}`}
|
htmlFor={`manage-role-${role.id}`}
|
||||||
className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
|
className="text-sm"
|
||||||
>
|
>
|
||||||
{role.name}
|
{role.name}
|
||||||
</label>
|
</Label>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
@ -736,10 +742,10 @@ export function UsersTable({ userRole = [] }: UsersTableProps) {
|
|||||||
setFormData(prev => ({ ...prev, roles: [] }));
|
setFormData(prev => ({ ...prev, roles: [] }));
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Annuler
|
Cancel
|
||||||
</Button>
|
</Button>
|
||||||
<Button onClick={handleUpdateRoles}>
|
<Button onClick={handleUpdateRoles}>
|
||||||
Mettre à jour les rôles
|
Update Roles
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user