I want to check the entity variable and check if it is allowed to delete the entity. For example if the owner entity of the association is linked to another entity, I want to make the deletion impossible.
I've looked in the documentation of api-platform bu I could not find any help regarding my problems. Either you give the right to delete or not. I could not find how to control it (equivalent to validation for POST, PUT and PATCH).
You can use the access control feature of Api-Platform and Symfony Expression Language to achieve what you want. This way you can write pretty complex expressions.
I hope this example makes it clear.
user is the currently logged in user.
object is the resource user is trying to delete.
/**
* #ApiResource(
* itemOperations={
* "delete"={
* "access_control"="is_granted('ROLE_USER') and object.getUsers().contains(user),
* }
* }
* )
*/
class Entity
{
/**
* #var ArrayCollection
*
* #ORM\OneToMany(targetEntity="User", inversedBy="entities")
* #ORM\JoinTable(name="entity_users")
*/
private $users;
/**
* #return ArrayCollection
*/
public function getUsers(): ArrayCollection
{
return $this->users;
}
}
In this case only users who are stored in users Array of Entity can delete this resource.
Related
currently i'm struggle with the identifier because i not need it.
i only need an get request without anything and returning some system infos.
/**
* #ApiResource(
* itemOperations={
* "info"={
* "method"="GET",
* "path"="/system/info",
* "controller"=GetInfo::class,
* "read"=false
* }
* },
* collectionOperations={
*
* }
* )
*/
thats my current config but it always requires an identifier.
It sounds as if you're after not an ApiPlatform resource, but simply a standard endpoint.
Have a look at this documentation from Symfony on how to define a route.
To me it sounds like you're after something like this:
config/routes.yaml
system_info:
path: /system/info
method: GET
controller: App\System\Info
With controller:
namespace App\System;
class Info
{
public function __invoke(): JsonResponse
{
return new JsonResponse(['pc' => 'master race']);
}
}
Remember that ApiPlatform is supposed to be working with Resources (aka: DTO's and Entities), and as you're use-case does not do either, you end up struggling to make it work.
Oke, so I have the following use case. On some of my entities I use a file entity for example with the organization logo.
Now I want users to post either a link (I will then async get the file) or a base64 has of the file. But when the user does a get I want to present an JSON representation of the file entity (that also includes size, a thumbnail link etc).
The current setup that I have is two different properties on my entity, one for reading and one for posting with different logic. And then an event listener that handels the logic. That’s all fine and all but it causes the user to post a postLogo property in their json file, I would hower like them to post to a logo property in their json file.
Is there an annotation that I can use (for example name on ApiProperty) to achieve this or do I need to override the serializer?
/**
* #var File The logo of this organisation
*
* #ORM\ManyToOne(targetEntity="File")
* #ApiProperty(
* attributes={
* "openapi_context"={
* "type"="#/components/schemas/File"
* }
* }
* )
* #Groups({"read"})
*/
public $logo;
/**
* #var string The logo of this organisation, a logo can iether be posted as a valid url to that logo or a base64 reprecentation of that logo.
*
* #ApiProperty(
* attributes={
* "openapi_context"={
* "type"="url or base64"
* }
* }
* )
* #Groups({"write"})
*/
public $postLogo;
You can add a setter with a SerializedName annotation. Something like this should work
/**
* #Groups({"write"})
* #SerializedName("logo")
*
*/
public function setPostLogo($value)
{
$this->postLogo = $value;
}
I'm following the example / documentation closely trying to set up a resource that only its owner can access, and I get this error:
"hydra:description": "Notice: Undefined property:
ApiPlatform\Core\Bridge\Doctrine\Orm\Paginator::$owner",
JWT authentication per se seems to work fine.
my resource is defined like this:
/**
* #ORM\Entity
* #ApiResource(
* attributes={"access_control"="is_granted('ROLE_USER') and object.owner == user"},
* collectionOperations={"get"},
* itemOperations={"get"},
* )
*/
Security and user provider and everything is set up exactly as in the api-platform or Symfony documentation.
The property owner is defined as:
/**
* #var User The owner
*
* #ORM\ManyToOne(targetEntity=User::class)
*/
public $owner;
What am I doing wrong?
I think this would work on your itemOperation GET, but not on your collectionOperation. The reason is that "object" in this case will the the collection of User objects, which is represented as the Paginator class.
#ahaaje is correct.
But you can still achieve what you're looking for by implementing an "extension". This would allow you to filter the collection with only items that belong to your user.
Official documentation is here.
I have created extbase extension, there for some reason I need to create object manually in create action.
My create action looks like this,
/**
* action create
*
* #return void
*/
public function createAction() {
$newObj = new \TYPO3\Myext\Domain\Model\Modelname();
$newObj->setMyval('value');
$this->myrepository->add($newObj);
}
Here the problem is its not validating for require field, captcha etc even if I mention #validate NotEmpty in model.
So how to make the validation of manually created object ?
It should throw error to form like out-of-the-box features.
Thank you.
Out of the box validation is only triggered on constructing model objects from GET/POST parameters according to your controller actions signature.
It should look something like this:
/**
* action create
* #param \TYPO3\Myext\Domain\Model\Modelname $newObject
* #return void
*/
public function createAction(\TYPO3\Myext\Domain\Model\Modelname $newObject) {
$this->myrepository->add($newObj);
}
Take a look at the extension_builder, create a model and let the new/create action be generated for you. That will give you a good example on the create action as well as on the new action where the form is being rendered.
I want to add routes dynamically. I am storing tree of documents in database. Based on document's position in that tree i can generate url for specific document. Problem is, whenever I add document to that tree, I have to clean cache because url matcher is precached. But if I clean cache inside controller by deleting of content of cache directory error is thrown. Is there any way, how to solve it?
more problem specification:
I need more routes to create, because based on documents type, its called specific controller and action (even with specific parameters). In tree item entity i store url_part and some parameters to create particular route (like controller and action), then parameters, which are passed to that controller. Entity has method getRoute() which knows how to build route from its data. Then i have for example page document, it is entity called page and it has relation to tree item (i did not wanted to mess with inheritance). When i create page, it knows how to fill data for related tree item. Problem is, when i create page, its not unvalidated cache with existing routes. I wanna have routes cached, so after creating page i wanna reset cached routes.
Why do you want to generate routes dynamically? Can't you create a single route with a pattern which allows slashes?
I've made a similar CMS using Symfony2 before, and I used StofDoctrineExtensionsBundle (have a look at Tree and Sluggable).
My Document entity had the following fields to support tree structure:
/**
* #Gedmo\TreeLeft
* #ORM\Column(name="`left`", type="integer")
*/
private $left;
/**
* #Gedmo\TreeLevel
* #ORM\Column(name="level", type="integer")
*/
private $level;
/**
* #Gedmo\TreeRight
* #ORM\Column(name="`right`", type="integer")
*/
private $right;
/**
* #Gedmo\TreeRoot
* #ORM\Column(name="root", type="integer", nullable=true)
*/
private $root;
/**
* #Gedmo\TreeParent
* #ORM\ManyToOne(targetEntity="Page", inversedBy="children")
* #ORM\JoinColumn(name="parent_id", referencedColumnName="id", onDelete="SET NULL")
*/
private $parent;
/**
* #ORM\OneToMany(targetEntity="Page", mappedBy="parent")
* #ORM\OrderBy({"left" = "ASC"})
*/
private $children;
And a slug field which reflected the hierarchy:
/**
* #var string $slug
*
* #ORM\Column(name="slug", type="string", length=255, unique=true)
* #Gedmo\Slug(handlers={
* #Gedmo\SlugHandler(class="Gedmo\Sluggable\Handler\TreeSlugHandler", options={
* #Gedmo\SlugHandlerOption(name="parentRelationField", value="parent"),
* #Gedmo\SlugHandlerOption(name="separator", value="/")
* })
* }, fields={"title"})
*/
private $slug;
Isn't this what you're looking for?