1. Project Clover database Sat Feb 2 2019 06:45:20 CET
  2. Package com.xpn.xwiki.web

File DeleteAction.java

 

Coverage histogram

../../../../img/srcFileCovDistChart8.png
56% of files have more coverage

Code metrics

34
92
11
1
278
191
34
0.37
8.36
11
3.09

Classes

Class Line # Actions
DeleteAction 50 92 0% 34 36
0.7372262573.7%
 

Contributing tests

No tests hitting this source file were found.

Source view

1    /*
2    * See the NOTICE file distributed with this work for additional
3    * information regarding copyright ownership.
4    *
5    * This is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU Lesser General Public License as
7    * published by the Free Software Foundation; either version 2.1 of
8    * the License, or (at your option) any later version.
9    *
10    * This software is distributed in the hope that it will be useful,
11    * but WITHOUT ANY WARRANTY; without even the implied warranty of
12    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13    * Lesser General Public License for more details.
14    *
15    * You should have received a copy of the GNU Lesser General Public
16    * License along with this software; if not, write to the Free
17    * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18    * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
19    */
20    package com.xpn.xwiki.web;
21   
22    import java.util.Arrays;
23    import java.util.Collections;
24    import java.util.List;
25   
26    import org.apache.commons.lang3.StringUtils;
27    import org.xwiki.job.Job;
28    import org.xwiki.job.JobException;
29    import org.xwiki.job.JobExecutor;
30    import org.xwiki.model.reference.DocumentReference;
31    import org.xwiki.model.reference.EntityReference;
32    import org.xwiki.refactoring.job.EntityRequest;
33    import org.xwiki.refactoring.job.PermanentlyDeleteRequest;
34    import org.xwiki.refactoring.job.RefactoringJobs;
35    import org.xwiki.refactoring.script.RefactoringScriptService;
36    import org.xwiki.script.service.ScriptService;
37   
38    import com.xpn.xwiki.XWiki;
39    import com.xpn.xwiki.XWikiContext;
40    import com.xpn.xwiki.XWikiException;
41    import com.xpn.xwiki.api.DeletedDocument;
42    import com.xpn.xwiki.doc.XWikiDeletedDocument;
43    import com.xpn.xwiki.doc.XWikiDocument;
44   
45    /**
46    * Action for delete document to recycle bin and for delete documents from recycle bin.
47    *
48    * @version $Id: 08feff9d6f9c71e3eac3b74b1b6358747fa084de $
49    */
 
50    public class DeleteAction extends XWikiAction
51    {
52    /** confirm parameter name. */
53    protected static final String CONFIRM_PARAM = "confirm";
54   
55    protected static final String ACTION_NAME = "delete";
56   
57    protected static final String ASYNC_PARAM = "async";
58   
59    protected static final String RECYCLED_DOCUMENT_ID_PARAM = "id";
60   
61    protected static final String EMPTY_RECYCLE_BIN = "emptybin";
62   
 
63  156 toggle private boolean isAsync(XWikiRequest request)
64    {
65  156 return "true".equals(request.get(ASYNC_PARAM));
66    }
67   
 
68  38 toggle private boolean doesAffectChildren(XWikiRequest request, DocumentReference documentReference)
69    {
70    // Security check: we do not "affect children" of a terminal document
71  38 return StringUtils.isNotEmpty(request.getParameter("affectChildren"))
72    && "WebHome".equals(documentReference.getName());
73    }
74   
 
75  151 toggle @Override
76    public boolean action(XWikiContext context) throws XWikiException
77    {
78  151 XWikiRequest request = context.getRequest();
79   
80    // If confirm=1 then delete the page. If not, the render action will go to the "delete" page so that the
81    // user can confirm. That "delete" page will then call the delete action again with confirm=1.
82  151 if (!"1".equals(request.getParameter(CONFIRM_PARAM))) {
83  17 return true;
84    }
85   
86    // CSRF prevention
87  134 if (!csrfTokenCheck(context)) {
88  0 return false;
89    }
90   
91  134 boolean redirected = delete(context);
92   
93  134 if (!redirected) {
94    // If a xredirect param is passed then redirect to the page specified instead of going to the default
95    // confirmation page.
96  69 String redirect = Utils.getRedirect(request, null);
97  69 if (redirect != null) {
98  1 sendRedirect(context.getResponse(), redirect);
99  1 redirected = true;
100    }
101    }
102   
103  134 return !redirected;
104    }
105   
 
106  45 toggle @Override
107    public String render(XWikiContext context) throws XWikiException
108    {
109  45 XWikiRequest request = context.getRequest();
110  45 XWikiDocument doc = context.getDoc();
111  45 String sindex = request.getParameter(RECYCLED_DOCUMENT_ID_PARAM);
112  45 boolean recycleIdIsValid = false;
113  45 if (sindex != null) {
114  0 long index = Long.parseLong(sindex);
115  0 if (context.getWiki().getRecycleBinStore().getDeletedDocument(index, context, true) != null) {
116  0 recycleIdIsValid = true;
117    }
118    }
119   
120  45 if ("1".equals(request.getParameter(CONFIRM_PARAM))) {
121  28 return "deleted";
122    }
123  17 if (doc.isNew() && !recycleIdIsValid) {
124  2 return Utils.getPage(request, "docdoesnotexist");
125    }
126   
127  15 return ACTION_NAME;
128    }
129   
 
130  94 toggle protected boolean delete(XWikiContext context) throws XWikiException
131    {
132  94 XWiki xwiki = context.getWiki();
133  94 XWikiRequest request = context.getRequest();
134  94 XWikiResponse response = context.getResponse();
135  94 XWikiDocument doc = context.getDoc();
136   
137  94 String sindex = request.getParameter(RECYCLED_DOCUMENT_ID_PARAM);
138  94 String emptyBin = request.getParameter(EMPTY_RECYCLE_BIN);
139   
140  94 if ("true".equals(emptyBin)) {
141  0 return deleteAllFromRecycleBin(context);
142  94 } else if (sindex != null && xwiki.hasRecycleBin(context)) {
143  2 deleteFromRecycleBin(Long.parseLong(sindex), context);
144  2 return true;
145  92 } else if (doc.isNew()) {
146    // Redirect the user to the view template so that he gets the "document doesn't exist" dialog box.
147  54 sendRedirect(response, Utils.getRedirect("view", context));
148  54 return true;
149    } else {
150    // Delete to recycle bin.
151  38 return deleteToRecycleBin(context);
152    }
153    }
154   
 
155  0 toggle private boolean deleteAllFromRecycleBin(XWikiContext context) throws XWikiException
156    {
157  0 RefactoringScriptService refactoring =
158    (RefactoringScriptService) Utils.getComponent(ScriptService.class, "refactoring");
159  0 PermanentlyDeleteRequest deleteRequest = refactoring.getRequestFactory()
160    .createPermanentlyDeleteRequest(Collections.emptyList());
161  0 deleteRequest.setInteractive(isAsync(context.getRequest()));
162  0 deleteRequest.setCheckAuthorRights(false);
163   
164  0 try {
165  0 JobExecutor jobExecutor = Utils.getComponent(JobExecutor.class);
166  0 Job job = jobExecutor.execute(RefactoringJobs.PERMANENTLY_DELETE, deleteRequest);
167   
168  0 if (isAsync(context.getRequest())) {
169  0 List<String> jobId = job.getRequest().getId();
170  0 sendRedirect(context.getResponse(),
171    Utils.getRedirect("view", "xpage=delete&jobId=" + serializeJobId(jobId), context));
172   
173    // A redirect has been performed.
174  0 return true;
175    }
176   
177    // Otherwise...
178  0 try {
179  0 job.join();
180    } catch (InterruptedException e) {
181  0 throw new XWikiException("Failed to delete all from the recycle bin", e);
182    }
183   
184    // No redirect has been performed.
185  0 return false;
186   
187    } catch (JobException e) {
188  0 throw new XWikiException("Failed to schedule the delete all from recycle bin job", e);
189    }
190    }
191   
 
192  2 toggle private void deleteFromRecycleBin(long index, XWikiContext context) throws XWikiException
193    {
194  2 XWiki xwiki = context.getWiki();
195  2 XWikiResponse response = context.getResponse();
196  2 XWikiDocument doc = context.getDoc();
197   
198  2 XWikiDeletedDocument dd = xwiki.getRecycleBinStore().getDeletedDocument(index, context, true);
199    // If the document hasn't been previously deleted (i.e. it's not in the deleted document store) then
200    // don't try to delete it and instead redirect to the view page.
201  2 if (dd != null) {
202  2 DeletedDocument ddapi = new DeletedDocument(dd, context);
203  2 if (!ddapi.canDelete()) {
204  0 throw new XWikiException(XWikiException.MODULE_XWIKI_ACCESS, XWikiException.ERROR_XWIKI_ACCESS_DENIED,
205    "You are not allowed to delete a document from the trash "
206    + "immediately after it has been deleted from the wiki");
207    }
208  2 if (!dd.getFullName().equals(doc.getFullName())) {
209  0 throw new XWikiException(XWikiException.MODULE_XWIKI_APP, XWikiException.ERROR_XWIKI_APP_URL_EXCEPTION,
210    "The specified trash entry does not match the current document");
211    }
212  2 xwiki.getRecycleBinStore().deleteFromRecycleBin(index, context, true);
213    }
214  2 sendRedirect(response, Utils.getRedirect("view", context));
215    }
216   
 
217  38 toggle private boolean deleteToRecycleBin(XWikiContext context) throws XWikiException
218    {
219  38 XWikiRequest request = context.getRequest();
220  38 XWikiDocument doc = context.getDoc();
221   
222  38 EntityReference documentReference =
223  38 doesAffectChildren(request, doc.getDocumentReference()) ? doc.getDocumentReference()
224    .getLastSpaceReference() : doc.getTranslatedDocument(context).getDocumentReferenceWithLocale();
225   
226  38 return deleteToRecycleBin(documentReference, context);
227    }
228   
 
229  78 toggle protected boolean deleteToRecycleBin(EntityReference entityReference, XWikiContext context) throws XWikiException
230    {
231  78 Job deleteJob = startDeleteJob(entityReference, context);
232   
233    // If the user have asked for an asynchronous delete action...
234  78 if (isAsync(context.getRequest())) {
235  9 List<String> jobId = deleteJob.getRequest().getId();
236    // We don't redirect to the delete action because by the time the redirect request reaches the server the
237    // specified entity may be already deleted and the current user may not have the delete right anymore (e.g.
238    // the current user is no longer the creator).
239  9 sendRedirect(context.getResponse(),
240    Utils.getRedirect("view", "xpage=delete&jobId=" + serializeJobId(jobId), context));
241   
242    // A redirect has been performed.
243  9 return true;
244    }
245   
246    // Otherwise...
247  69 try {
248  69 deleteJob.join();
249    } catch (InterruptedException e) {
250  0 throw new XWikiException(String.format("Failed to delete [%s]", entityReference), e);
251    }
252   
253    // No redirect has been performed.
254  69 return false;
255    }
256   
 
257  9 toggle private String serializeJobId(List<String> jobId)
258    {
259  9 return StringUtils.join(jobId, "/");
260    }
261   
 
262  78 toggle private Job startDeleteJob(EntityReference entityReference, XWikiContext context) throws XWikiException
263    {
264  78 RefactoringScriptService refactoring =
265    (RefactoringScriptService) Utils.getComponent(ScriptService.class, "refactoring");
266  78 EntityRequest deleteRequest = refactoring.getRequestFactory()
267    .createDeleteRequest(Arrays.asList(entityReference));
268  78 deleteRequest.setInteractive(isAsync(context.getRequest()));
269  78 deleteRequest.setCheckAuthorRights(false);
270   
271  78 try {
272  78 JobExecutor jobExecutor = Utils.getComponent(JobExecutor.class);
273  78 return jobExecutor.execute(RefactoringJobs.DELETE, deleteRequest);
274    } catch (JobException e) {
275  0 throw new XWikiException(String.format("Failed to schedule the delete job for [%s]", entityReference), e);
276    }
277    }
278    }