Sunday, March 1, 2015

Symfony 2 hari 13: Pengaman form

Artikel ini dirunut berdasarkan Jobeet Tutorial, yang dibuat oleh Fabien Potencier, untuk Symfony 1.4.

Amankan form dengan token

Untuk melakukan pengamanan form, kita dapat menggunakan token pada setiap formnya. Untuk menambahkan token edit file Job.orm.yml dan tambahkan script berikut:

src/Ibw/JobeetBundle/Resources/config/doctrine/Job.orm.yml

# ...
  lifecycleCallbacks:
     prePersist: [ setTokenValue, preUpload, setCreatedAtValue, setExpiresAtValue ]
     # ...
Kemudian seperti biasa jalankan perintah entities untuk mengupdate schema entity kita.
php app/console doctrine:generate:entities IbwJobeetBundle

Selanjutnya tambahkan method token di Job entity kita:

src/Ibw/JobeetBundle/Entity/Job.php
 // ...
    public function setTokenValue()
    {
        if(!$this->getToken()) {
            $this->token = sha1($this->getEmail().rand(11111, 99999));
        }
    }
    // ...
Sekarang kamu dapat menghapus field token yang ada di form karena token tersebut akan tergenerate secara otomatis oleh method yang kita buat barusan.


src/Ibw/JobeetBundle/Form/JobType.php
// ...
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('category')
            ->add('type', 'choice', array('choices' => Job::getTypes(), 'expanded' => true))
            ->add('company')
            ->add('file', 'file', array('label' => 'Company logo', 'required' => false))
            ->add('url')
            ->add('position')
            ->add('location')
            ->add('description')
            ->add('how_to_apply', null, array('label' => 'How to apply?'))
            ->add('is_public', null, array('label' => 'Public?'))
            ->add('email')
        ;
    }
// ...

Hapus juga yang di edit.orm.yml dan new.orm.yml 

src/Ibw/JobeetBundle/Resources/views/Job/new.html.twig
<!-- ... -->
<tr>
    <th>{{ form_label(form.token) }}</th>
    <td>
        {{ form_errors(form.token) }}
        {{ form_widget(form.token) }}
    </td>
</tr>
<!-- ... -->

src/Ibw/JobeetBundle/Resources/views/Job/edit.html.twig
<!-- ... -->
<tr>
    <th>{{ form_label(edit_form.token) }}</th>
    <td>
        {{ form_errors(edit_form.token) }}
        {{ form(edit_form.token) }}
    </td>
</tr>
<!-- ... -->
Hapus juga yang di validation file:
src/Ibw/JobeetBundle/Resources/config/validation.yml
# ...
    # ...
    token:
        - NotBlank: ~

Ok sekarang kita dapat mengganti default parameter $id untuk menampilkan, mengedit, dan menghapus jadi datanya lebih aman. Edit file routingnya.

src/Ibw/JobeetBundle/Resources/config/routing/job.yml  
 
# ...
ibw_job_edit:
    pattern:  /{token}/edit
    defaults: { _controller: "IbwJobeetBundle:Job:edit" }
ibw_job_update:
    pattern:  /{token}/update
    defaults: { _controller: "IbwJobeetBundle:Job:update" }
    requirements: { _method: post|put }
ibw_job_delete:
    pattern:  /{token}/delete
    defaults: { _controller: "IbwJobeetBundle:Job:delete" }
    requirements: { _method: post|delete }
Untuk itu kita juga harus mengubah parameter $id di method-method yang ada di controller:
src/Ibw/JobeetBundle/Controller/JobController.php
// ...
class JobController extends Controller
{
    // ...
    public function editAction($token)
    {
        $em = $this->getDoctrine()->getManager();
        $entity = $em->getRepository('IbwJobeetBundle:Job')->findOneByToken($token);
        if (!$entity) {
            throw $this->createNotFoundException('Unable to find Job entity.');
        }
        $editForm = $this->createForm(new JobType(), $entity);
        $deleteForm = $this->createDeleteForm($token);
        return $this->render('IbwJobeetBundle:Job:edit.html.twig', array(
            'entity'      => $entity,
            'edit_form'   => $editForm->createView(),
            'delete_form' => $deleteForm->createView(),
        ));
    }  
    public function updateAction(Request $request, $token)
    {
        $em = $this->getDoctrine()->getManager();
        $entity = $em->getRepository('IbwJobeetBundle:Job')->findOneByToken($token);
        if (!$entity) {
            throw $this->createNotFoundException('Unable to find Job entity.');
        }
        $editForm   = $this->createForm(new JobType(), $entity);
        $deleteForm = $this->createDeleteForm($token);
        $editForm->bind($request);
        if ($editForm->isValid()) {
            $em->persist($entity);
            $em->flush();
            return $this->redirect($this->generateUrl('ibw_job_edit', array('token' => $token)));
        }
        return $this->render('IbwJobeetBundle:Job:edit.html.twig', array(
            'entity'      => $entity,
            'edit_form'   => $editForm->createView(),
            'delete_form' => $deleteForm->createView(),
        ));
    }
    public function deleteAction(Request $request, $token)
    {
        $form = $this->createDeleteForm($token);
        $form->bind($request);
        if ($form->isValid()) {
            $em = $this->getDoctrine()->getManager();
            $entity = $em->getRepository('IbwJobeetBundle:Job')->findOneByToken($token);
            if (!$entity) {
                throw $this->createNotFoundException('Unable to find Job entity.');
            }
            $em->remove($entity);
            $em->flush();
        }
        return $this->redirect($this->generateUrl('ibw_job'));
    }
    /**
     * Creates a form to delete a Job entity by id.
     *
     * @param mixed $id The entity id
     *
     * @return Symfony\Component\Form\Form The form
     */
    private function createDeleteForm($token)
    {
        return $this->createFormBuilder(array('token' => $token))
            ->add('token', 'hidden')
            ->getForm()
        ;
    }
}

Dan di template show.html.twig serta edit.html.twig sesuaikan parameter $idnya dengan $token seperti yang lainnya:
src/Ibw/JobeetBundle/Resources/views/Job/show.html.twig
 
<a href="{{ path('ibw_job_edit', {'token': entity.token}) }}">


src/Ibw/JobeetBundle/Resources/views/Job/edit.html.twig
<form action="{{ path('ibw_job_update', {'token': entity.token}) }}" method="post" {{ form_enctype(edit_form) }}>
Bammm... sekarang semua route sudah lebih aman karena menggunakan token dan tidak lagi menggunakan parameter $id 
   

No comments:

Post a Comment