Problems, need help? Have a tip or advice? Post it here.
11 posts Page 1 of 2
On this same page I want to delete a page from couch on the front-end. I know it's not supported by couch but try to work around this.., it's a members only function on the page (use the members plugin).

I tried to use several variations of a form on the page
Code: Select all
<!-- delete button -->

<form method='post'>

<cms:php>       

if(isset($_POST['delbutton']))
{

$query ="DELETE couch_pages"."WHERE id = 'k_page_id'" ;
$result = mysql_query($query);
}


</cms:php>

<button name="delbutton" class="label alert" type="submit"><i class="foundicon-remove"></i></button>

</form>


<!-- delete button -->


Until now I haven't a luck with this .. or isn't it possible at all ?
I load frameworks and write bugs on top of them, after that I rearrange the code so that it looks like a cool product.
I know it's not supported by couch ..
.. or isn't it possible at all ?

It is actually possible.
However, I've chosen not to document it because deletion requires due care to be exercised while implementing. Any mistake and you'll creating vulnerabilities in your site.

To illustrate my point, let us take the very code that you posted above.
Assuming the code did work, it would have left your site wide open to the dreaded CSRF vulnerability.

You can google around for details of CSRF but to describe its effects in brief here - an attacker can trick a logged-in user to (unknowingly) submit the form you coded with any page-id to actually delete the page without even realizing what is happening.

An effective weapon against CSRF is the use of 'nonces' (arbitrary values that cannot be predicted by the attacker).

OK, so with the dangers understood, we can now see how to delete a page from the front-end.
Following is the tag that does it
Code: Select all
<cms:db_delete masterpage='template name of page to delete' page_id='id of page to delete' />

The cms:db_delete tag above is part of the frontend-form's suite of tags.

An equivalent of the form that you posted could now become -
Code: Select all
<cms:if k_is_page >

    <cms:set page_to_delete=k_page_id 'global' />

    <cms:form method='post' anchor='0' >
           
        <cms:if k_success>

            <!-- Delete the specified page -->
            <cms:db_delete masterpage=k_template_name page_id=page_to_delete />
           
            <!-- redirect to the list-page -->
            <cms:redirect "<cms:link masterpage=k_template_name />" />
           
        </cms:if>   
       
        <input type="submit" name="submit" value="Delete this page"/>
    </cms:form>

</cms:if>


Please do not use the code above without adequate CSRF protection.

Following is how we can put in the required protection in the above form -
Code: Select all
<cms:if k_is_page >

    <cms:set page_to_delete=k_page_id 'global' />

    <cms:form method='post' anchor='0' >
        <!--
            Step 1. Create a string describing the action to create the nonce for.
            Make sure that the string also contains the affected page's id.
            In this example the string would be "delete_page_277" for deleting page with id 277.
        -->
        <cms:set my_action="delete_page_<cms:show page_to_delete />" />
           
        <cms:if k_success>
            <!-- Step 3. Verify the submitted nonce -->
            <cms:validate_nonce my_action />
           
            <!-- If we are here, the nonce was verified and we can execute the action -->
            <!-- Delete the specified page -->
            <cms:db_delete masterpage=k_template_name page_id=page_to_delete />
           
            <!-- redirect to the list-page -->
            <cms:redirect "<cms:link masterpage=k_template_name />" />
           
        </cms:if>   
       
        <!--
            Step 2. Create a nonce for the action (created in step 1 above ).
            This will be submitted with the form.
        -->
        <cms:input name='nonce' type='hidden' value="<cms:create_nonce my_action />" />
       
        <input type="submit" name="submit" value="Delete this page"/>
    </cms:form>

</cms:if>

As you can see, using a nonce requires three steps -
create_nonce,
submit it with form,
finally validate_nonce upon successful form submission.

The code above will delete the page the form is used upon.
Usually, we offer the deletion facility from a page that lists all cloned-pages (as in Couch's admin-panel). The general outline will remain the same but do let us know if you have doubts about anything.

Hope this helps.
Hi KK,

Thank you for the very,very detailed explanation.... this works like a dream.

You can google around for details of CSRF


I did and try to understand if it would make a difference by using the members plugin.
I use this somewhere on some pages after a member is logged-in ( and <cms:member_check_login /> on top of the page). Isn't the use of :

Code: Select all
<cms:db_delete masterpage='template name of page to delete' page_id='id of page to delete' />


Already protected by then ?

Thanks again.
I load frameworks and write bugs on top of them, after that I rearrange the code so that it looks like a cool product.
KK wrote: Usually, we offer the deletion facility from a page that lists all cloned-pages (as in Couch's admin-panel). The general outline will remain the same but do let us know if you have doubts about anything.

Hm.... I tried for a few hours yesterday, I'm trying this morning again, but it seems I can't make it to work in list view :(
More exactly what should be changed in the above code in order to use it for delete pages from list view?
Thank you.
@atisz, could you please post the code you are trying to use?
Thanks.
KK wrote: @atisz, could you please post the code you are trying to use?
Thanks.

Thank you KK for the quick reply! Of course. This is the latest try, I have tried a lot of combinations, as you can see I'm testing with a certain page id to avoid accidentally deleting of another page. I feel as I'm so far away from the working solution :(
Code: Select all
<cms:pages masterpage='members/documents.php' custom_field="idfolder=id(<cms:show k_page_id />)" show_future_entries='1'>

   <cms:form
          masterpage=k_template_name
          mode='edit'
          page_id=k_page_id
          method='post'
          anchor='0'
       >

      <cms:if k_success>
                  <!-- Delete the specified page -->
                  <cms:db_delete masterpage=k_template_name k_page_id='367' />         
           </cms:if>

      <input type="submit" name="submit" value="Delete page"/>
       </cms:form>

</cms:pages>
atisz wrote: <cms:db_delete masterpage=k_template_name k_page_id='367' />

<cms:db_delete masterpage='template name of page to delete' page_id='id of page to delete' />
trendoman wrote:
atisz wrote: <cms:db_delete masterpage=k_template_name k_page_id='367' />

<cms:db_delete masterpage='template name of page to delete' page_id='id of page to delete' />


Thanks trendoman, but I have tried that way too, without any luck.
Code: Select all
<cms:db_delete masterpage='members/documents.php' page_id='367' />
@atisz,
Please make sure to use <cms:input type="submit" /> (instead of a plain <input>) in a form that has no other cms:inputs else the k_success condition will not be triggered.

Following is some sample *working* code. Please adapt it to your need -
Code: Select all
<cms:pages masterpage=k_template_name show_future_entries='1'>

   <h3><cms:show k_page_title /></h3>
   
   <cms:form
          masterpage=k_template_name
          mode='edit'
          page_id=k_page_id
          method='post'
          anchor='0'
       >

      <cms:if k_success>
              <!-- Delete the specified page -->
              <cms:db_delete masterpage=k_template_name page_id=k_page_id />
             
              <!-- and then redirect -->
              <cms:redirect k_template_link />
       </cms:if>

      <cms:input type="submit" name="submit" value="Delete page"/>
  </cms:form>

</cms:pages>

As a side-note, since you are using the delete within a data-bound form, you can use the <cms:db_delete_form /> tag instead of <cms:db_delete /> as follows -
Code: Select all
<cms:if k_success>
      <!-- Delete the specified page -->
      <cms:db_delete_form />
     
      <!-- and then redirect -->
      <cms:redirect k_template_link />
</cms:if>

Notice above that we did not have to specify the template name and page ID as <cms:db_delete_form /> will automatically pick those up from its parent databound form.

For any one chancing upon this thread and wondering why we have not used the nonce so vociferously advocated in the initial replies, the answer is that in this case the delete statement is enclosed within a databound form that, by default, already outputs the nonce so it won't be necessary to do it explicitly.

Hope it helps.
Bingo! Thank you KK for helping me out on this! The problem was the use of simple "input" instead of "cms:input", as it can be found here http://www.couchcms.com/forum/viewtopic.php?p=13980#p13980. You should probably make the correction on that post, as it's referenced a lot on the Couch forum ;) I was concentrating on "masterpage" and "page id" part of the code, so without you mentioning the "cms:input" part I would never realize what the real problem was.
Thank you again, everytime it's a real pleasure to work with Couch CMS!
11 posts Page 1 of 2
cron