Procházet zdrojové kódy

Make sure packages can not be added to a vendor namespace unless the user has access to it, fixes #163

Jordi Boggiano před 10 roky
rodič
revize
f90aa171cd

+ 4 - 2
src/Packagist/WebBundle/Controller/WebController.php

@@ -424,13 +424,13 @@ class WebController extends Controller
         $package->setEntityRepository($this->getDoctrine()->getRepository('PackagistWebBundle:Package'));
         $package->setRouter($this->get('router'));
         $form = $this->createForm(new PackageType, $package);
+        $user = $this->getUser();
+        $package->addMaintainer($user);
 
         if ('POST' === $req->getMethod()) {
             $form->bind($req);
             if ($form->isValid()) {
                 try {
-                    $user = $this->getUser();
-                    $package->addMaintainer($user);
                     $em = $this->getDoctrine()->getManager();
                     $em->persist($package);
                     $em->flush();
@@ -457,6 +457,8 @@ class WebController extends Controller
         $package->setEntityRepository($this->getDoctrine()->getRepository('PackagistWebBundle:Package'));
         $package->setRouter($this->get('router'));
         $form = $this->createForm(new PackageType, $package);
+        $user = $this->getUser();
+        $package->addMaintainer($user);
 
         $response = array('status' => 'error', 'reason' => 'No data posted.');
         $req = $this->getRequest();

+ 19 - 0
src/Packagist/WebBundle/Entity/Package.php

@@ -33,6 +33,7 @@ use Composer\Repository\Vcs\GitHubDriver;
  *     }
  * )
  * @Assert\Callback(methods={"isPackageUnique"})
+ * @Assert\Callback(methods={"isVendorWritable"})
  * @Assert\Callback(methods={"isRepositoryValid"}, groups={"Update", "Default"})
  * @author Jordi Boggiano <j.boggiano@seld.be>
  */
@@ -248,6 +249,24 @@ class Package
         } catch (\Doctrine\ORM\NoResultException $e) {}
     }
 
+    public function isVendorWritable(ExecutionContextInterface $context)
+    {
+        try {
+            $vendor = $this->getVendor();
+            if ($vendor && $this->entityRepository->isVendorTaken($vendor, reset($this->maintainers))) {
+                $context->addViolationAt(
+                    'repository',
+                    'The vendor is already taken by someone else. '
+                        . 'You may ask them to add your package and give you maintainership access. '
+                        . 'The packages already in that vendor namespace can be found at '
+                        . '<a href="'.$this->router->generate('view_vendor', array('vendor' => $vendor)).'">'.$vendor.'</a>',
+                    array(),
+                    null
+                );
+            }
+        } catch (\Doctrine\ORM\NoResultException $e) {}
+    }
+
     /**
      * Get id
      *

+ 25 - 0
src/Packagist/WebBundle/Entity/PackageRepository.php

@@ -300,6 +300,31 @@ class PackageRepository extends EntityRepository
         return $qb;
     }
 
+    public function isVendorTaken($vendor, User $user)
+    {
+        $query = $this->getEntityManager()
+            ->createQuery(
+                "SELECT p.name, m.id user_id
+                FROM Packagist\WebBundle\Entity\Package p
+                JOIN p.maintainers m
+                WHERE p.name LIKE :vendor")
+            ->setParameters(array('vendor' => $vendor.'/%'));
+
+        $rows = $query->getArrayResult();
+        if (!$rows) {
+            return false;
+        }
+
+        foreach ($rows as $row) {
+            if ($row['user_id'] === $user->getId()) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+
     private function addFilters(QueryBuilder $qb, array $filters)
     {
         foreach ($filters as $name => $value) {