feat: Enhance API interactions and user entity configuration

This commit is contained in:
olli 2025-11-08 11:10:57 +01:00
parent fcfda9d9be
commit 465515191f
5 changed files with 51 additions and 13 deletions

View File

@ -229,11 +229,31 @@ const errors = ref({});
const fetchUsers = async () => { const fetchUsers = async () => {
loading.value = true; loading.value = true;
try { try {
const response = await fetch('/api/users'); const response = await fetch('/api/users', {
credentials: 'same-origin',
headers: {
'Accept': 'application/ld+json'
}
});
if (!response.ok) {
const errorText = await response.text();
console.error('API Error:', response.status, errorText);
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json(); const data = await response.json();
users.value = data['hydra:member'] || data;
// API Platform JSON-LD uses 'member' (hydra:member becomes 'member' in JS)
users.value = data.member || data['hydra:member'] || [];
} catch (error) { } catch (error) {
toast.add({ severity: 'error', summary: 'Fehler', detail: 'Benutzer konnten nicht geladen werden', life: 3000 }); console.error('Error fetching users:', error);
toast.add({
severity: 'error',
summary: 'Fehler',
detail: 'Benutzer konnten nicht geladen werden: ' + error.message,
life: 5000
});
} finally { } finally {
loading.value = false; loading.value = false;
} }
@ -297,7 +317,11 @@ const saveUser = async () => {
const response = await fetch(url, { const response = await fetch(url, {
method, method,
headers: { 'Content-Type': 'application/json' }, credentials: 'same-origin',
headers: {
'Content-Type': 'application/ld+json',
'Accept': 'application/ld+json'
},
body: JSON.stringify(payload) body: JSON.stringify(payload)
}); });
@ -328,7 +352,8 @@ const deleteUser = async () => {
deleting.value = true; deleting.value = true;
try { try {
const response = await fetch(`/api/users/${userToDelete.value.id}`, { const response = await fetch(`/api/users/${userToDelete.value.id}`, {
method: 'DELETE' method: 'DELETE',
credentials: 'same-origin'
}); });
if (!response.ok) throw new Error('Fehler beim Löschen'); if (!response.ok) throw new Error('Fehler beim Löschen');

View File

@ -1,7 +1,11 @@
api_platform: api_platform:
title: Hello API Platform title: myCRM API
version: 1.0.0 version: 1.0.0
defaults: defaults:
stateless: true stateless: false
cache_headers: cache_headers:
vary: ['Content-Type', 'Authorization', 'Origin'] vary: ['Content-Type', 'Authorization', 'Origin']
formats:
jsonld: ['application/ld+json']
json: ['application/json']
html: ['text/html']

View File

@ -1,5 +1,6 @@
framework: framework:
asset_mapper: asset_mapper:
enabled: false
# The paths to make available to the asset mapper. # The paths to make available to the asset mapper.
paths: paths:
- assets/ - assets/
@ -8,4 +9,5 @@ framework:
when@prod: when@prod:
framework: framework:
asset_mapper: asset_mapper:
enabled: false
missing_import_mode: warn missing_import_mode: warn

View File

@ -8,7 +8,7 @@ use Symfony\Component\Routing\Attribute\Route;
class HomeController extends AbstractController class HomeController extends AbstractController
{ {
#[Route('/{reactRouting}', name: 'app_home', requirements: ['reactRouting' => '(?!login|logout|api).*'], defaults: ['reactRouting' => null], priority: -1)] #[Route('/{reactRouting}', name: 'app_home', requirements: ['reactRouting' => '(?!login|logout|api|bundles).*'], defaults: ['reactRouting' => null], priority: -1)]
public function index(): Response public function index(): Response
{ {
return $this->render('base.html.twig'); return $this->render('base.html.twig');

View File

@ -21,11 +21,11 @@ use Symfony\Component\Serializer\Annotation\Groups;
#[ORM\UniqueConstraint(name: 'UNIQ_IDENTIFIER_EMAIL', fields: ['email'])] #[ORM\UniqueConstraint(name: 'UNIQ_IDENTIFIER_EMAIL', fields: ['email'])]
#[ApiResource( #[ApiResource(
operations: [ operations: [
new GetCollection(), new GetCollection(stateless: false),
new Get(), new Get(stateless: false),
new Post(security: "is_granted('ROLE_ADMIN')"), new Post(security: "is_granted('ROLE_ADMIN')", stateless: false),
new Put(security: "is_granted('ROLE_ADMIN') or object == user"), new Put(security: "is_granted('ROLE_ADMIN') or object == user", stateless: false),
new Delete(security: "is_granted('ROLE_ADMIN')") new Delete(security: "is_granted('ROLE_ADMIN')", stateless: false)
], ],
normalizationContext: ['groups' => ['user:read']], normalizationContext: ['groups' => ['user:read']],
denormalizationContext: ['groups' => ['user:write']] denormalizationContext: ['groups' => ['user:write']]
@ -204,10 +204,17 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
return trim($this->firstName . ' ' . $this->lastName); return trim($this->firstName . ' ' . $this->lastName);
} }
#[Groups(['user:read', 'user:write'])]
public function isActive(): bool public function isActive(): bool
{ {
return $this->isActive; return $this->isActive;
} }
// Alias for Symfony Serializer (which expects get* prefix)
public function getIsActive(): bool
{
return $this->isActive;
}
public function setIsActive(bool $isActive): static public function setIsActive(bool $isActive): static
{ {