Answers.Body: <p>Thanks to <strong>@RobinSchambach</strong> advices, I was able to find a safe solution to handle this permission problematic.</p>
  
  <p>This is possible using two main addings:</p>
  
  <ul>
  <li>Register a <strong>new custom permission</strong> from the plugin
  
  <ul>
  <li><em>This prevents user from be able to access other users assets</em></li>
  </ul></li>
  <li>Add a <strong>custom User field</strong> on the assets to assign ownership ;
  
  <ul>
  <li><em>Using this we can verify that it was uploaded from user requesting the file deletion</em></li>
  </ul></li>
  </ul>
  
  <p><strong>In the plugin Service:</strong></p>
  
  <pre><code>public function linkUserToAssets($assets = [])
  {
      $currentUser = Craft::$app-&gt;getUser()-&gt;getIdentity();
      if ($currentUser &amp;&amp; Craft::$app-&gt;request-&gt;getIsSiteRequest()
          &amp;&amp; Craft::$app-&gt;request-&gt;getIsPost()) {
          foreach ($assets-&gt;all() as $asset) {
              if (isset($asset-&gt;id) &amp;&amp; !empty($asset-&gt;id)) {
                  $asset = Craft::$app-&gt;assets-&gt;getAssetById($asset-&gt;id);
                  if (isset($asset-&gt;assetsOwner)) {
                      $asset-&gt;assetsOwner = [$currentUser-&gt;id];
                      Craft::$app-&gt;elements-&gt;saveElement($asset);
                  }
              }
          }
      }
  }
  </code></pre>
  
  <p>This adds a function to call before each entry is saved, to assign the user's ownership on entry's assets using the <code>assetsOwner</code> custom field.</p>
  
  <p><strong>In the plugin Module:</strong></p>
  
  <pre><code>Event::on(
      UserPermissions::class,
      UserPermissions::EVENT_REGISTER_PERMISSIONS,
      function(RegisterUserPermissionsEvent $event) {
          $event-&gt;permissions['User'] = [
              'deleteOwnAssets' =&gt; [
                  'label' =&gt; 'Delete Own Assets'
              ],
          ];
      }
  );
  </code></pre>
  
  <p>This adds a custom permission in the CP which should be added to group of users who will perform this action.</p>
  
  <p><strong>In the plugin Controller:</strong></p>
  
  <pre><code>public function actionDeleteAsset()
  {
      $currentUser = Craft::$app-&gt;getUser()-&gt;getIdentity();
      if ($currentUser) {
          $request = Craft::$app-&gt;getRequest();
          $assetId = $request-&gt;getBodyParam('assetId');
          $asset = Craft::$app-&gt;getAssets()-&gt;getAssetById($assetId);
  
          if ($asset-&gt;assetsOwner[0]-&gt;id !== $currentUser-&gt;id || !Craft::$app-&gt;user-&gt;checkPermission('deleteOwnAssets')) {
              return $this-&gt;asErrorJson(Craft::t('app', self::TEXT_PERMISSION_REQUIRED));
          }
      }
  }
  </code></pre>
  
  <p>This deletes requested assets if the current user was the owner of the asset (using <code>assetsOwner</code> custom field) and has the required custom permission (in this case, <code>deleteOwnAssets</code>).</p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2018-09-25T10:28:28.953Z
Answers.Text: You'll likely receive deprecation errors with that code and there are a few "mistakes"/useless calls. If you want we can talk in detail at Slack about it
Answers.UserDisplayName: Robin Schambach
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2018-09-25T10:15:27.860Z
Answers.LastActivityDate: 2018-09-25T10:15:27.860Z
Answers.UserDisplayName: Romain P.
Body: <p>I have a front-end form where logged users can upload and delete their personal files.</p>
  
  <p>These users have the strict minimum permissions required to interact with this form. They can only Create, Publish and Delete their own entries in the section where the form create these entries.</p>
  
  <p>In order to be able to delete these files from Craft (and not from only the field they're linked in this entry), I have created this custom action in a module:</p>
  
  <pre><code>&lt;?php
  
  namespace modules\mymodule\controllers;
  
  use Craft;
  use craft\web\Controller;
  use craft\elements\Asset;
  
  class DefaultController extends Controller
  {
  
      public function actionDeleteAsset()
      {
          $this-&gt;requireAcceptsJson();
          $this-&gt;requireLogin();
  
          $currentUser = Craft::$app-&gt;getUser()-&gt;getIdentity();
          if (!$currentUser) {
              return $this-&gt;asErrorJson(Craft::t('app', 'Only a logged in user can delete an asset.'));
          } else {
              $request = Craft::$app-&gt;getRequest();
              $assetId = $request-&gt;getParam('assetId', '');
              $asset = Craft::$app-&gt;getAssets()-&gt;getAssetById($assetId);
  
              if (!empty($asset)) {
                  if (!Craft::$app-&gt;getUser()-&gt;checkPermission('deleteFilesAndFoldersInVolume:' . $asset-&gt;volumeId)) {
                      return $this-&gt;asErrorJson(Craft::t('app', 'You don\'t have permission to delete this asset.'));
                  } else {
                      Craft::$app-&gt;getElements()-&gt;deleteElementById($asset-&gt;id, Asset::class);
                      return $this-&gt;asJson([
                          'success' =&gt; true
                      ]);
                  }
              } else {
                  return $this-&gt;asErrorJson(Craft::t('app', 'This asset does not exists or has already been deleted.'));
              }
          }
      }
  
  }
  </code></pre>
  
  <p>The problem is that <code>Craft::$app-&gt;getUser()-&gt;checkPermission('deleteFilesAndFoldersInVolume:' . $asset-&gt;volumeId)</code>is not entirely appropriate:</p>
  
  <ul>
  <li>I need to add Volume permissions (View volume + Remove files and
  folders) to these users to allow them to delete their assets from the
  front-end form ;</li>
  <li>By adding these permissions, they have access to
  other users' assets, which is a security problem ;</li>
  </ul>
  
  <p>So how can I check if user has the permissions to delete only his own assets? In other words, this user can only interact with the assets he has uploaded.</p>
  
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2018-09-08T21:54:13.417Z
Comments.Text: Why don't you just include a custom permission in your plugin?
Comments.UserDisplayName: Robin Schambach
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2018-09-10T07:50:53.687Z
Comments.Text: I didn't know it was possible. But even with custom permissions, how would you handle that? It seems that there is no user information I can get from the Asset element. So it means that I would have to create one custom different permission per user, and attach it to the file when the user use the front-end form. This would be a lot ot custom permissions for a website that would handle thousands of users, no?
Comments.UserDisplayName: Romain P.
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2018-09-10T08:09:42.530Z
Comments.Text: Just include one single permission if a user is able to delete an asset or not and include a `users` field to the asset and relate it to all users that may delete it. If the user is not related to the asset -> he can't delete it
Comments.UserDisplayName: Robin Schambach
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2018-09-11T10:46:13.377Z
Comments.Text: Thank you, I will go in this way and integrate it asap. So I'm gonna add a hook on user registration / use of the front-end form to attach the custom permission (https://docs.craftcms.com/v2/plugins/hooks-reference.html#general-hooks), then I will populate a custom field on file upload. I'll update my question / answer later here.
Comments.UserDisplayName: Romain P.
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2018-09-11T11:02:28.383Z
Comments.Text: There are no hooks in Craft 3, only events but yes
Comments.UserDisplayName: Robin Schambach
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2018-09-25T10:20:24.547Z
Comments.Text: @RobinSchambach, I have now posted my answer thanks to your advices.
Comments.UserDisplayName: Romain P.
Tags: <plugin-development><assets><frontend-form><delete>
Title: Plugin development: how can I check if user has the permissions to delete only his own assets?
ThreadText: # Plugin development: how can I check if user has the permissions to delete only his own assets?
  
  (Asked by: username_0 on 2018-09-07)
  
  I have a front-end form where logged users can upload and delete their personal files.
  
  These users have the strict minimum permissions required to interact with this form. They can only Create, Publish and Delete their own entries in the section where the form create these entries.
  
  In order to be able to delete these files from Craft (and not from only the field they're linked in this entry), I have created this custom action in a module:
  
  ```
  <?php
  
  namespace modules\mymodule\controllers;
  
  use Craft;
  use craft\web\Controller;
  use craft\elements\Asset;
  
  class DefaultController extends Controller
  {
  
      public function actionDeleteAsset()
      {
          $this->requireAcceptsJson();
          $this->requireLogin();
  
          $currentUser = Craft::$app->getUser()->getIdentity();
          if (!$currentUser) {
              return $this->asErrorJson(Craft::t('app', 'Only a logged in user can delete an asset.'));
          } else {
              $request = Craft::$app->getRequest();
              $assetId = $request->getParam('assetId', '');
              $asset = Craft::$app->getAssets()->getAssetById($assetId);
  
              if (!empty($asset)) {
                  if (!Craft::$app->getUser()->checkPermission('deleteFilesAndFoldersInVolume:' . $asset->volumeId)) {
                      return $this->asErrorJson(Craft::t('app', 'You don\'t have permission to delete this asset.'));
                  } else {
                      Craft::$app->getElements()->deleteElementById($asset->id, Asset::class);
                      return $this->asJson([
                          'success' => true
                      ]);
                  }
              } else {
                  return $this->asErrorJson(Craft::t('app', 'This asset does not exists or has already been deleted.'));
              }
          }
      }
  
  }
  
  ```
  
  The problem is that `Craft::$app->getUser()->checkPermission('deleteFilesAndFoldersInVolume:' . $asset->volumeId)`is not entirely appropriate:
  
  * I need to add Volume permissions (View volume + Remove files and
    folders) to these users to allow them to delete their assets from the
    front-end form ;
  * By adding these permissions, they have access to
    other users' assets, which is a security problem ;
  
  So how can I check if user has the permissions to delete only his own assets? In other words, this user can only interact with the assets he has uploaded.
  
  **Tags:** plugin-development, assets, frontend-form, delete
  
  > **Comments:**
  > **username_1**: Why don't you just include a custom permission in your plugin?  
  > **username_0**: I didn't know it was possible. But even with custom permissions, how would you handle that? It seems that there is no user information I can get from the Asset element. So it means that I would have to create one custom different permission per user, and attach it to the file when the user use the front-end form. This would be a lot ot custom permissions for a website that would handle thousands of users, no?  
  > **username_1**: Just include one single permission if a user is able to delete an asset or not and include a `users` field to the asset and relate it to all users that may delete it. If the user is not related to the asset -> he can't delete it  
  > **username_0**: Thank you, I will go in this way and integrate it asap. So I'm gonna add a hook on user registration / use of the front-end form to attach the custom permission (https://docs.craftcms.com/v2/plugins/hooks-reference.html#general-hooks), then I will populate a custom field on file upload. I'll update my question / answer later here.  
  > **username_1**: There are no hooks in Craft 3, only events but yes  
  > **username_0**: @username_1, I have now posted my answer thanks to your advices.  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_0 on 2018-09-25. Score: 1
  
  Thanks to **@username_1** advices, I was able to find a safe solution to handle this permission problematic.
  
  This is possible using two main addings:
  
  * Register a **new custom permission** from the plugin
    + *This prevents user from be able to access other users assets*
  * Add a **custom User field** on the assets to assign ownership ;
    + *Using this we can verify that it was uploaded from user requesting the file deletion*
  
  **In the plugin Service:**
  
  ```
  public function linkUserToAssets($assets = [])
  {
      $currentUser = Craft::$app->getUser()->getIdentity();
      if ($currentUser && Craft::$app->request->getIsSiteRequest()
          && Craft::$app->request->getIsPost()) {
          foreach ($assets->all() as $asset) {
              if (isset($asset->id) && !empty($asset->id)) {
                  $asset = Craft::$app->assets->getAssetById($asset->id);
                  if (isset($asset->assetsOwner)) {
                      $asset->assetsOwner = [$currentUser->id];
                      Craft::$app->elements->saveElement($asset);
                  }
              }
          }
      }
  }
  
  ```
  
  This adds a function to call before each entry is saved, to assign the user's ownership on entry's assets using the `assetsOwner` custom field.
  
  **In the plugin Module:**
  
  ```
  Event::on(
      UserPermissions::class,
      UserPermissions::EVENT_REGISTER_PERMISSIONS,
      function(RegisterUserPermissionsEvent $event) {
          $event->permissions['User'] = [
              'deleteOwnAssets' => [
                  'label' => 'Delete Own Assets'
              ],
          ];
      }
  );
  
  ```
  
  This adds a custom permission in the CP which should be added to group of users who will perform this action.
  
  **In the plugin Controller:**
  
  ```
  public function actionDeleteAsset()
  {
      $currentUser = Craft::$app->getUser()->getIdentity();
      if ($currentUser) {
          $request = Craft::$app->getRequest();
          $assetId = $request->getBodyParam('assetId');
          $asset = Craft::$app->getAssets()->getAssetById($assetId);
  
          if ($asset->assetsOwner[0]->id !== $currentUser->id || !Craft::$app->user->checkPermission('deleteOwnAssets')) {
              return $this->asErrorJson(Craft::t('app', self::TEXT_PERMISSION_REQUIRED));
          }
      }
  }
  
  ```
  
  This deletes requested assets if the current user was the owner of the asset (using `assetsOwner` custom field) and has the required custom permission (in this case, `deleteOwnAssets`).
  
  > **Comments:**
  > **username_1**: You'll likely receive deprecation errors with that code and there are a few "mistakes"/useless calls. If you want we can talk in detail at Slack about it  
  
  ---
  
  