Dav: Introduce access control inside de dav controller

This commit is contained in:
2023-09-15 22:21:56 +02:00
parent 3fe870ba71
commit a57e6c0cc9
9 changed files with 419 additions and 22 deletions

View File

@@ -14,15 +14,16 @@ namespace Chill\DocStoreBundle\Controller;
use Chill\DocStoreBundle\Dav\Request\PropfindRequestAnalyzer;
use Chill\DocStoreBundle\Dav\Response\DavResponse;
use Chill\DocStoreBundle\Entity\StoredObject;
use Chill\DocStoreBundle\Security\Authorization\StoredObjectRoleEnum;
use Chill\DocStoreBundle\Security\Guard\JWTDavTokenProviderInterface;
use Chill\DocStoreBundle\Service\StoredObjectManagerInterface;
use DateTimeInterface;
use Lexik\Bundle\JWTAuthenticationBundle\Services\JWTTokenManagerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Templating\EngineInterface;
final readonly class WebdavController
{
@@ -31,8 +32,8 @@ final readonly class WebdavController
public function __construct(
private \Twig\Environment $engine,
private StoredObjectManagerInterface $storedObjectManager,
private Security $security,
private ?JWTTokenManagerInterface $JWTTokenManager = null,
private Security $security,
private ?JWTDavTokenProviderInterface $davTokenProvider = null,
) {
$this->requestAnalyzer = new PropfindRequestAnalyzer();
}
@@ -42,12 +43,7 @@ final readonly class WebdavController
*/
public function open(StoredObject $storedObject): Response
{
$accessToken = $this->JWTTokenManager?->createFromPayload($this->security->getUser(), [
'UserCanWrite' => true,
'UserCanAttend' => true,
'UserCanPresent' => true,
'fileId' => $storedObject->getUuid(),
]);
$accessToken = $this->davTokenProvider?->createToken($storedObject, StoredObjectRoleEnum::EDIT);
return new DavResponse($this->engine->render('@ChillDocStore/Webdav/open_in_browser.html.twig', [
'stored_object' => $storedObject, 'access_token' => $accessToken,
@@ -59,6 +55,10 @@ final readonly class WebdavController
*/
public function getDirectory(StoredObject $storedObject, string $access_token): Response
{
if (!$this->security->isGranted(StoredObjectRoleEnum::SEE->value, $storedObject)) {
throw new AccessDeniedHttpException();
}
return new DavResponse(
$this->engine->render('@ChillDocStore/Webdav/directory.html.twig', [
'stored_object' => $storedObject,
@@ -72,11 +72,16 @@ final readonly class WebdavController
*/
public function optionsDirectory(StoredObject $storedObject): Response
{
if (!$this->security->isGranted(StoredObjectRoleEnum::SEE->value, $storedObject)) {
throw new AccessDeniedHttpException();
}
$response = (new DavResponse(""))
->setEtag($this->storedObjectManager->etag($storedObject))
;
$response->headers->add(['Allow' => 'OPTIONS,GET,HEAD,DELETE,PROPFIND,PUT,PROPPATCH,COPY,MOVE,REPORT,PATCH,POST,TRACE']);
//$response->headers->add(['Allow' => 'OPTIONS,GET,HEAD,DELETE,PROPFIND,PUT,PROPPATCH,COPY,MOVE,REPORT,PATCH,POST,TRACE']);
$response->headers->add(['Allow' => 'OPTIONS,GET,HEAD,DELETE,PROPFIND,PUT']);
return $response;
}
@@ -86,6 +91,10 @@ final readonly class WebdavController
*/
public function propfindDirectory(StoredObject $storedObject, string $access_token, Request $request): Response
{
if (!$this->security->isGranted(StoredObjectRoleEnum::SEE->value, $storedObject)) {
throw new AccessDeniedHttpException();
}
$depth = $request->headers->get('depth');
if ("0" !== $depth && "1" !== $depth) {
@@ -119,6 +128,10 @@ final readonly class WebdavController
*/
public function getDocument(StoredObject $storedObject): Response
{
if (!$this->security->isGranted(StoredObjectRoleEnum::SEE->value, $storedObject)) {
throw new AccessDeniedHttpException();
}
return (new DavResponse($this->storedObjectManager->read($storedObject)))
->setEtag($this->storedObjectManager->etag($storedObject));
}
@@ -128,6 +141,10 @@ final readonly class WebdavController
*/
public function headDocument(StoredObject $storedObject): Response
{
if (!$this->security->isGranted(StoredObjectRoleEnum::SEE->value, $storedObject)) {
throw new AccessDeniedHttpException();
}
$response = new DavResponse("");
$response->headers->add(
@@ -146,19 +163,15 @@ final readonly class WebdavController
*/
public function optionsDocument(StoredObject $storedObject): Response
{
if (!$this->security->isGranted(StoredObjectRoleEnum::SEE->value, $storedObject)) {
throw new AccessDeniedHttpException();
}
$response = (new DavResponse(""))
->setEtag($this->storedObjectManager->etag($storedObject))
;
$response->headers->add(['Allow' => /*sprintf(
'%s, %s, %s, %s, %s',
Request::METHOD_OPTIONS,
Request::METHOD_GET,
Request::METHOD_HEAD,
Request::METHOD_PUT,
'PROPFIND'
) */ 'OPTIONS,GET,HEAD,DELETE,PROPFIND,PUT,PROPPATCH,COPY,MOVE,REPORT,PATCH,POST,TRACE'
]);
$response->headers->add(['Allow' => 'OPTIONS,GET,HEAD,DELETE,PROPFIND,PUT']);
return $response;
}
@@ -168,6 +181,10 @@ final readonly class WebdavController
*/
public function propfindDocument(StoredObject $storedObject, string $access_token, Request $request): Response
{
if (!$this->security->isGranted(StoredObjectRoleEnum::SEE->value, $storedObject)) {
throw new AccessDeniedHttpException();
}
[$properties, $lastModified, $etag, $length] = $this->parseDavRequest($request->getContent(), $storedObject);
$response = new DavResponse(
@@ -198,6 +215,10 @@ final readonly class WebdavController
*/
public function putDocument(StoredObject $storedObject, Request $request): Response
{
if (!$this->security->isGranted(StoredObjectRoleEnum::EDIT->value, $storedObject)) {
throw new AccessDeniedHttpException();
}
$this->storedObjectManager->write($storedObject, $request->getContent());
return (new DavResponse("", Response::HTTP_NO_CONTENT));