Fix documents migration + fix show/download files using resources

#2326
pull/2715/head
Julio Montoya 7 years ago
parent a5f2e2263e
commit f5d0592029
  1. 12
      config/routes.yaml
  2. 16
      config/services.yaml
  3. 8
      main/document/document.php
  4. 11
      main/document/show_content.php
  5. 5
      public/courses.php
  6. 80
      src/CoreBundle/Controller/ResourceController.php
  7. 2
      src/CoreBundle/Entity/Resource/AbstractResource.php
  8. 5
      src/CoreBundle/Entity/Resource/ResourceFile.php
  9. 5
      src/CoreBundle/Entity/Resource/ResourceLink.php
  10. 38
      src/CoreBundle/Security/Authorization/Voter/ResourceNodeVoter.php
  11. 2
      src/CourseBundle/Resources/config/routing.yml
  12. 201
      tests/scripts/migrate_item_property.php

@ -20,12 +20,12 @@ sonata_user_admin_security_logout:
# Resources
app_document:
resource: |
alias: app.document
path: /resource/documents
form: Chamilo\CoreBundle\Form\Type\DocumentType
type: sylius.resource
#app_document:
# resource: |
# alias: app.document
# path: /resource/documents
# form: Chamilo\CoreBundle\Form\Type\DocumentType
# type: sylius.resource
app_document_index:
path: /courses/{course}/resource/documents/

@ -46,14 +46,14 @@ services:
sylius_settings:
driver: doctrine/orm
sylius_resource:
resources:
app.document:
templates: ChamiloCoreBundle:Document
classes:
controller: Chamilo\CoreBundle\Controller\ResourceController
model: Chamilo\CourseBundle\Entity\CDocument
repository: Chamilo\CoreBundle\Repository\ResourceRepository
#sylius_resource:
# resources:
# app.document:
# templates: ChamiloCoreBundle:Document
# classes:
# controller: Chamilo\CoreBundle\Controller\ResourceController
# model: Chamilo\CourseBundle\Entity\CDocument
# repository: Chamilo\CoreBundle\Repository\ResourceRepository
#
#sonata.media.provider.private:

@ -40,6 +40,7 @@ $actionsRight = '';
$action = isset($_REQUEST['action']) ? $_REQUEST['action'] : '';
$allowUseTool = false;
if ($allowDownloadDocumentsByApiKey) {
try {
if ($action != 'download') {
@ -329,6 +330,13 @@ switch ($action) {
// Launch event
Event::event_download($document_data['url']);
$publicPath = api_get_path(WEB_PUBLIC_PATH);
$courseCode = api_get_course_id();
$path = $document_data['path'];
$url = $publicPath."courses/$courseCode/document$path";
header("Location: $url");
exit;
// Check visibility of document and paths
if (!($isAllowedToEdit || $groupMemberWithUploadRights) &&
!DocumentManager::is_visible_by_id($document_id, $courseInfo, $sessionId, api_get_user_id())

@ -44,6 +44,17 @@ if (empty($document_data)) {
api_not_allowed(true);
}
$publicPath = api_get_path(WEB_PUBLIC_PATH);
// http://localhost/chamilo2/courses/ABC/document/aa.html
$courseCode = api_get_course_id();
$path = $document_data['path'];
$type = 'show';
$url = $publicPath."courses/$courseCode/document$path?type=$type";
header("Location: $url");
exit;
$header_file = $document_data['path'];
$name_to_show = cut($header_file, 80);

@ -4,13 +4,14 @@
require_once '../main/inc/global.inc.php';
/**
* Redirects "courses/ABC/document/my_file.html" to the symfony Resourcecontroller see:
* Redirects "courses/ABC/document/my_file.html" to the symfony ResourceController see:
* src/CoreBundle/Controller/ResourceController.php.
*/
$publicPath = api_get_path(WEB_PUBLIC_PATH);
// http://localhost/chamilo2/courses/ABC/document/aa.html
$courseCode = Security::remove_XSS($_GET['courseCode']);
$path = Security::remove_XSS($_GET['url']);
$url = $publicPath."courses/$courseCode/document/$path";
$type = Security::remove_XSS($_GET['type']) ?? 'show';
$url = $publicPath."courses/$courseCode/document/$path?type=$type";
header("Location: $url");
exit;

@ -9,6 +9,7 @@ use APY\DataGridBundle\Grid\Export\CSVExport;
use APY\DataGridBundle\Grid\Export\ExcelExport;
use APY\DataGridBundle\Grid\Grid;
use APY\DataGridBundle\Grid\Source\Entity;
use Chamilo\CoreBundle\Entity\Resource\ResourceNode;
use Chamilo\CoreBundle\Entity\Resource\ResourceRight;
use Chamilo\CoreBundle\Repository\ResourceRepository;
use Chamilo\CoreBundle\Security\Authorization\Voter\ResourceNodeVoter;
@ -17,13 +18,16 @@ use Chamilo\CourseBundle\Controller\CourseControllerTrait;
use Chamilo\CourseBundle\Entity\CDocument;
use Chamilo\CourseBundle\Repository\CDocumentRepository;
use FOS\RestBundle\View\View;
use Sonata\MediaBundle\Provider\MediaProviderInterface;
use Sylius\Bundle\ResourceBundle\Controller\ResourceController as BaseResourceController;
use Sylius\Bundle\ResourceBundle\Event\ResourceControllerEvent;
use Sylius\Component\Resource\Exception\UpdateHandlingException;
use Sylius\Component\Resource\ResourceActions;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
/**
* Class ResourceController.
@ -32,7 +36,8 @@ use Symfony\Component\HttpKernel\Exception\HttpException;
*
* @package Chamilo\CoreBundle\Controller
*/
class ResourceController extends BaseResourceController implements CourseControllerInterface
//class ResourceController extends BaseResourceController implements CourseControllerInterface
class ResourceController extends BaseController implements CourseControllerInterface
{
use CourseControllerTrait;
@ -400,6 +405,79 @@ class ResourceController extends BaseResourceController implements CourseControl
*/
public function showAction(Request $request): Response
{
$file = $request->get('file');
$type = $request->get('type');
if (empty($type)) {
$type = 'show';
}
$documentRepo = $this->getDoctrine()->getRepository('ChamiloCourseBundle:CDocument');
$criteria = [
'path' => "/$file",
'course' => $this->getCourse(),
];
$document = $documentRepo->findOneBy($criteria);
if (empty($document)) {
throw new NotFoundHttpException();
}
/** @var ResourceNode $resourceNode */
$resourceNode = $document->getResourceNode();
$this->denyAccessUnlessGranted(
ResourceNodeVoter::VIEW,
$resourceNode,
'Unauthorised access to resource'
);
$resourceFile = $resourceNode->getResourceFile();
$media = $resourceFile->getMedia();
$format = MediaProviderInterface::FORMAT_REFERENCE;
if ($media) {
switch ($type) {
case 'show':
/** @var \Sonata\MediaBundle\Provider\ImageProvider $provider */
$provider = $this->get('sonata.media.pool')->getProvider($media->getProviderName());
$reference = $provider->getReferenceFile($media);
$filename = sprintf('%s/%s',
$provider->getFilesystem()->getAdapter()->getDirectory(),
$provider->generatePrivateUrl($media, $format)
);
//var_dump($provider->generatePublicUrl($media, $format));
//var_dump($filename);
return new BinaryFileResponse($filename);
exit;
return $this->render('@SonataMedia/Media/view.html.twig', [
'media' => $media,
'formats' => $this->get('sonata.media.pool')->getFormatNamesByContext($media->getContext()),
'format' => $format,
]);
break;
case 'download':
$provider = $this->get('sonata.media.pool')->getProvider($media->getProviderName());
$response = $provider->getDownloadResponse($media, $format, $this->get('sonata.media.pool')->getDownloadMode($media));
return $response;
break;
}
}
throw new NotFoundHttpException();
var_dump($resourceFile->getMedia()->getName());
$configuration = $this->requestConfigurationFactory->create($this->metadata, $request);
$this->isGrantedOr403($configuration, ResourceActions::SHOW);

@ -48,7 +48,7 @@ abstract class AbstractResource implements ResourceInterface
/**
* @return ResourceNode
*/
public function getResourceNode()
public function getResourceNode(): ResourceNode
{
return $this->resourceNode;
}

@ -3,6 +3,7 @@
namespace Chamilo\CoreBundle\Entity\Resource;
use Chamilo\MediaBundle\Entity\Media;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
@ -337,7 +338,7 @@ class ResourceFile
}
/**
* @return mixed
* @return Media
*/
public function getMedia()
{
@ -345,7 +346,7 @@ class ResourceFile
}
/**
* @param mixed $media
* @param Media $media
*
* @return ResourceFile
*/

@ -173,6 +173,11 @@ class ResourceLink implements ResourceInterface
return $this;
}
public function getResourceRight()
{
return $this->resourceRight;
}
/**
* @return int
*/

@ -6,6 +6,8 @@ namespace Chamilo\CoreBundle\Security\Authorization\Voter;
use Chamilo\CoreBundle\Entity\Course;
use Chamilo\CoreBundle\Entity\Resource\ResourceLink;
use Chamilo\CoreBundle\Entity\Resource\ResourceNode;
use Chamilo\CoreBundle\Entity\Resource\ResourceRight;
use Zend\Permissions\Acl\Resource\GenericResource as SecurityResource;
use Chamilo\CoreBundle\Entity\Session;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Security\Acl\Permission\MaskBuilder;
@ -100,7 +102,11 @@ class ResourceNodeVoter extends Voter
}
/**
* {@inheritdoc}
* @param string $attribute
* @param ResourceNode $resourceNode
* @param TokenInterface $token
*
* @return bool
*/
protected function voteOnAttribute($attribute, $resourceNode, TokenInterface $token): bool
{
@ -132,7 +138,7 @@ class ResourceNodeVoter extends Voter
$courseCode = $request->get('course');
$sessionId = $request->get('session');
$links = $resourceNode->getLinks();
$links = $resourceNode->getResourceLinks();
$linkFound = false;
/** @var ResourceLink $link */
@ -171,7 +177,7 @@ class ResourceNodeVoter extends Voter
// Check if resource was sent to a course
if ($linkCourse instanceof Course && !empty($courseCode)) {
$course = $this->container->get('chamilo_core.manager.course')->findOneByCode($courseCode);
$course = $this->container->get('chamilo_core.entity.manager.course_manager')->findOneByCode($courseCode);
if ($course instanceof Course &&
$linkCourse->getCode() === $course->getCode()
) {
@ -187,14 +193,34 @@ class ResourceNodeVoter extends Voter
}
// Getting rights from the link
$rightFromResourceLink = $link->getRights();
$rightFromResourceLink = $link->getResourceRight();
if ($rightFromResourceLink->count()) {
// Taken rights from the link
$rights = $rightFromResourceLink;
} else {
// Taken the rights from the default tool
$rights = $link->getResourceNode()->getTool()->getToolResourceRight();
//$rights = $link->getResourceNode()->getTool()->getToolResourceRight();
//$rights = $link->getResourceNode()->getResourceType()->getTool()->getToolResourceRight();
// By default the rights are:
// teacher: CRUD
// student: read
$readerMask = self::getReaderMask();
$editorMask = self::getEditorMask();
$resourceRight = new ResourceRight();
$resourceRight
->setMask($editorMask)
->setRole(self::ROLE_CURRENT_COURSE_TEACHER)
;
$rights[] = $resourceRight;
$resourceRight = new ResourceRight();
$resourceRight
->setMask($readerMask)
->setRole(self::ROLE_CURRENT_COURSE_STUDENT)
;
$rights[] = $resourceRight;
}
// Asked mask
@ -230,7 +256,7 @@ class ResourceNodeVoter extends Voter
$acl->addRole($admin);
// Adds a resource
$resource = new Resource($link);
$resource = new SecurityResource($link);
$acl->addResource($resource);
// Role and permissions settings

@ -10,7 +10,7 @@ core_tool:
core_tool_document:
path: /courses/{course}/document/{file}
defaults:
_controller: ChamiloCoreBundle:Resource:getDocument
_controller: ChamiloCoreBundle:Resource:show
requirements:
file: .+ # allow "/" in {file}

@ -13,7 +13,23 @@ use Chamilo\CoreBundle\Security\Authorization\Voter\ResourceNodeVoter;
require_once __DIR__.'/../../main/inc/global.inc.php';
$sql = "SELECT * FROM c_item_property WHERE tool = 'document' LIMIT 10";
$sql = "SELECT
d.id,
d.c_id,
d.session_id,
i.to_group_id,
i.to_user_id,
i.iid,
insert_user_id,
insert_date,
lastedit_date,
tool,
visibility
FROM c_item_property i
INNER JOIN c_document d
ON (d.iid = i.ref AND i.c_id = d.c_id)
WHERE i.tool = 'document' AND filetype <> 'folder' AND d.c_id = 4
ORDER BY d.path LIMIT 10";
$result = Database::query($sql);
$fs = Container::$container->get('oneup_flysystem.courses_filesystem');
@ -22,6 +38,9 @@ $em = Database::getManager();
$resourceType = $em->getRepository('ChamiloCoreBundle:Resource\ResourceType')->findOneBy(['name' => 'document']);
$coursePath = api_get_path(SYS_PATH).'app/courses/';
$mediaManager = Container::$container->get('sonata.media.manager.media');
$documentManager = $em->getRepository('ChamiloCourseBundle:CDocument');
$contextManager = Container::$container->get('sonata.classification.manager.context');
$defaultContext = $contextManager->findOneBy(['id' => 'default']);
while ($row = Database::fetch_array($result, 'ASSOC')) {
$itemIid = $row['iid'];
@ -29,20 +48,31 @@ while ($row = Database::fetch_array($result, 'ASSOC')) {
$sessionId = $row['session_id'];
$groupId = $row['to_group_id'];
$toUserId = $row['to_user_id'];
$documentId = $row['id'];
$toUser = api_get_user_entity($toUserId);
$author = api_get_user_entity($row['insert_user_id']);
if (empty($author)) {
error_log("User does not exists in the DB ".$row['insert_user_id']);
continue;
}
$createdAt = api_get_utc_datetime($row['insert_date'], true, true);
$lastUpdatedAt = api_get_utc_datetime($row['lastedit_date'], true, true);
$course = api_get_course_entity($courseId);
$session = api_get_course_entity($sessionId);
if (empty($course)) {
error_log("Course does not exists in the DB $courseId");
continue;
}
$session = api_get_session_entity($sessionId);
$group = api_get_group_entity($groupId);
switch ($row['tool']) {
case 'document':
$documentData = DocumentManager::get_document_data_by_id($row['ref'], $course->getCode(), $sessionId);
var_dump($documentData);
$documentData = DocumentManager::get_document_data_by_id($documentId, $course->getCode(), $sessionId);
//var_dump($documentData);
if (!$documentData) {
//$documentData = DocumentManager::get_document_data_by_id($row['ref'], $course->getCode(), $sessionId);
error_log("Skipped item property iid #$itemIid");
@ -50,103 +80,114 @@ while ($row = Database::fetch_array($result, 'ASSOC')) {
}
$folderPath = $course->getDirectory().'/document/'.$documentData['path'];
$file = $coursePath.$folderPath;
switch ($documentData['filetype']) {
case 'folder':
//$fs->createDir($folderPath);
/*$node = new ResourceNode();
$node
->setName($documentData['title'])
->setDescription('')
->setCreator($author)
->setResourceType($resourceType)
->setCreatedAt($createdAt)
->setUpdatedAt($lastUpdatedAt)
;
$em->persist($node);
$em->flush();*/
break;
case 'file':
//$stream = fopen($file, 'r+');
//$fs->writeStream($folderPath, $stream);
//fclose($stream);
$document = $documentManager->find($documentData['iid']);
var_dump('Parsing document iid #'.$document->getIid());
/** @var Media $media */
$media = $mediaManager->create();
//$media = new Media();
$media->setName($documentData['title']);
$fileName = basename($documentData['path']);
$extension = pathinfo($fileName, PATHINFO_EXTENSION);
$media->setSize($documentData['size']);
$media->setContext('default');
$media->setProviderName('sonata.media.provider.image');
var_dump($file);
$provider = 'sonata.media.provider.image';
if (!in_array($extension, ['jpeg', 'jpg', 'gif', 'png'])) {
$provider = 'sonata.media.provider.file';
}
$media->setProviderName($provider);
$media->setEnabled(true);
$stdFile = new Std
$media->setBinaryContent(file_get_contents($file));
$media->setBinaryContent($file);
$mediaManager->save($media, true);
$resourceFile = new ResourceFile();
$resourceFile->setMedia($media);
$resourceFile->setName($documentData['title']);
$em->persist($resourceFile);
$node = new ResourceNode();
$node
->setName($documentData['title'])
->setDescription($documentData['comment'] ?? '')
->setResourceFile($resourceFile)
->setCreator($author)
->setResourceType($resourceType)
->setCreatedAt($createdAt)
->setUpdatedAt($lastUpdatedAt)
;
$em->persist($node);
$document->setResourceNode($node);
$em->persist($document);
$em->flush();
$rights = [];
switch ($row['visibility']) {
case '0':
$newVisibility = ResourceLink::VISIBILITY_DRAFT;
$readerMask = ResourceNodeVoter::getReaderMask();
$editorMask = ResourceNodeVoter::getEditorMask();
$resourceRight = new ResourceRight();
$resourceRight
->setMask($editorMask)
->setRole(ResourceNodeVoter::ROLE_CURRENT_COURSE_TEACHER)
;
$rights[] = $resourceRight;
break;
case '1':
$newVisibility = ResourceLink::VISIBILITY_PUBLISHED;
break;
case '2':
$newVisibility = ResourceLink::VISIBILITY_DELETED;
break;
}
$link = new ResourceLink();
$link
->setCourse($course)
->setSession($session)
->setGroup($group)
->setUser($toUser)
->setResourceNode($node)
->setVisibility($newVisibility)
;
if (!empty($rights)) {
foreach ($rights as $right) {
$link->addResourceRight($right);
}
}
break;
}
$em->persist($link);
$em->flush();
continue;
$file = new ResourceFile();
$file
->setHash('')
->setName($documentData['title'])
->setOriginalFilename(basename($documentData['path']))
->setSize($documentData['size'])
;
$node = new ResourceNode();
$node
->setName($documentData['title'])
->setDescription($documentData['comment'])
->setResourceFile($file)
->setCreator($author)
->setResourceFile($file)
->setResourceType($resourceType)
->setCreatedAt($createdAt)
->setUpdatedAt($lastUpdatedAt)
;
$em->persist($node);
$em->flush();
$rights = [];
switch ($row['visibility']) {
case '0':
$newVisibility = ResourceLink::VISIBILITY_DRAFT;
$readerMask = ResourceNodeVoter::getReaderMask();
$editorMask = ResourceNodeVoter::getEditorMask();
$resourceRight = new ResourceRight();
$resourceRight
->setMask($editorMask)
->setRole(ResourceNodeVoter::ROLE_CURRENT_COURSE_TEACHER)
;
$rights[] = $resourceRight;
break;
case '1':
$newVisibility = ResourceLink::VISIBILITY_PUBLISHED;
break;
case '2':
$newVisibility = ResourceLink::VISIBILITY_DELETED;
break;
}
$link = new ResourceLink();
$link
->setCourse($course)
->setSession($session)
->setGroup($group)
->setUser($toUser)
->setResourceNode($node)
->setVisibility($newVisibility)
;
if (!empty($rights)) {
foreach ($rights as $right) {
$link->addResourceRight($right);
}
}
$em->persist($link);
$em->flush();
break;
}
}

Loading…
Cancel
Save