Mercurial Hosting > nabble
comparison src/nabble/view/web/catalog/ChangeParent.jtp @ 0:7ecd1a4ef557
add content
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Thu, 21 Mar 2019 19:15:52 -0600 |
parents | |
children | 18cf4872fd7f |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:7ecd1a4ef557 |
---|---|
1 <% | |
2 package nabble.view.web.catalog; | |
3 | |
4 import fschmidt.db.DbDatabase; | |
5 import fschmidt.util.java.HtmlUtils; | |
6 import fschmidt.util.servlet.AuthorizingServlet; | |
7 import nabble.model.Message; | |
8 import nabble.model.ModelException; | |
9 import nabble.model.Node; | |
10 import nabble.model.Person; | |
11 import nabble.model.Site; | |
12 import nabble.model.User; | |
13 import nabble.model.export.Export; | |
14 import nabble.view.lib.Jtp; | |
15 import nabble.view.lib.Permissions; | |
16 import nabble.view.lib.Shared; | |
17 import nabble.view.web.template.UrlMapperNamespace; | |
18 import org.slf4j.Logger; | |
19 import org.slf4j.LoggerFactory; | |
20 | |
21 import javax.servlet.ServletException; | |
22 import javax.servlet.http.HttpServlet; | |
23 import javax.servlet.http.HttpServletRequest; | |
24 import javax.servlet.http.HttpServletResponse; | |
25 import java.io.IOException; | |
26 import java.io.PrintWriter; | |
27 | |
28 | |
29 public class ChangeParent extends HttpServlet implements AuthorizingServlet { | |
30 private static final Logger logger = LoggerFactory.getLogger(ChangeParent.class); | |
31 | |
32 public String getAuthorizationKey(HttpServletRequest request) throws ServletException { | |
33 return Jtp.getReadAuthorizationKey( Jtp.getSiteNotNull(request).getNode(Jtp.getLong(request,"forum")) ); | |
34 } | |
35 | |
36 public boolean authorize(String key,HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException { | |
37 return Jtp.authorizeForRead(key,request,response); | |
38 } | |
39 | |
40 protected void service(HttpServletRequest request, HttpServletResponse response) | |
41 throws ServletException, IOException | |
42 { | |
43 PrintWriter out = response.getWriter(); | |
44 String forumId = request.getParameter("forum"); | |
45 Node forum = forumId == null? null : Jtp.getSiteNotNull(request).getNode(Long.valueOf(forumId)); | |
46 | |
47 if (forum == null) | |
48 return; | |
49 | |
50 Person visitor = Jtp.getVisitor(request, response); | |
51 boolean isSiteAdmin = visitor instanceof User && Permissions.isInGroup((User) visitor, Permissions.ADMINISTRATORS_GROUP); | |
52 | |
53 boolean allowed = Jtp.canBeRemovedBy(forum,visitor); | |
54 if (!allowed) { | |
55 Jtp.login("Only administrators can proceed in this area.", request, response); | |
56 return; | |
57 } | |
58 | |
59 String errorMsg = null; | |
60 String action = request.getParameter("action"); | |
61 String option = request.getParameter("option"); | |
62 String url = request.getParameter("url"); | |
63 if ("set".equals(action) && "POST".equals(request.getMethod())) { | |
64 if ("provide-url".equals(option)) | |
65 errorMsg = setParent(forum, url, request, response); | |
66 else if ("merge".equals(option)) | |
67 errorMsg = merge(forum, visitor, isSiteAdmin, response); | |
68 else if ("delete-root".equals(option)) | |
69 errorMsg = deleteRoot(forum, visitor, response); | |
70 else if ("create-parent".equals(option)) | |
71 errorMsg = createParent(forum, (User)visitor, request, response); | |
72 if (errorMsg == null) | |
73 return; | |
74 } | |
75 | |
76 Node currentParent = forum.getParent(); | |
77 %> | |
78 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | |
79 <html> | |
80 <head> | |
81 <% Shared.title(request, response, "Parent Options"); %> | |
82 <script type="text/javascript"> | |
83 $(document).ready(function() { | |
84 function handleFocus() { | |
85 $('#url,#name,#description,#type').attr('disabled','y'); | |
86 var id = $(':radio').filter('[checked]').attr('id'); | |
87 if (id == 'choose-parent') { | |
88 $('#url').removeAttr('disabled').focus(); | |
89 } else if (id == 'create-parent') { | |
90 $('#name,#description,#type').removeAttr('disabled').focus(); | |
91 $('#name').focus(); | |
92 } | |
93 }; | |
94 handleFocus(); | |
95 $(':radio').click(handleFocus); | |
96 }); | |
97 </script> | |
98 <style type="text/css"> | |
99 div.field-title { | |
100 font-weight:bold; | |
101 font-size:110%; | |
102 padding-bottom:.1em; | |
103 margin-top: 1.7em; | |
104 } | |
105 span.disabled { | |
106 font-size:90%; | |
107 font-weight:normal; | |
108 margin-left:1em | |
109 } | |
110 </style> | |
111 </head> | |
112 <body> | |
113 <% Shared.minHeader(request,response, forum); %> | |
114 <% Shared.editHeader(forum.getSubjectHtml(), "Parent Options", out); %> | |
115 <% Shared.errorMessage(request, response, errorMsg, null); %> | |
116 <form id="parent-form" method="post" action="/catalog/ChangeParent.jtp" accept-charset="UTF-8"> | |
117 <input type="hidden" name="action" value="set" /> | |
118 <input type="hidden" name="forum" value="<%=forum.getId()%>" /> | |
119 | |
120 <div class="second-font field-title"> | |
121 <input type="radio" id="choose-parent" name="option" value="provide-url" <%=option == null || "provide-url".equals(option)? "checked='y'" : ""%>/> | |
122 <label for="choose-parent">Set a New Parent</label> | |
123 </div> | |
124 <div class="weak-color" style="margin-left:1.9em"> | |
125 Enter the permalink of the new parent:<br/> | |
126 <input id="url" name="url" size="60" value="<%=Jtp.hideNull(url)%>"/> | |
127 </div> | |
128 | |
129 <% boolean isDisabled = !isSiteAdmin || currentParent == null || !Jtp.canBeDeletedBy(forum,visitor); %> | |
130 <div class="second-font field-title"> | |
131 <input type="radio" <%=isDisabled?"disabled":""%> id="merge" name="option" value="merge" <%="merge".equals(option)? "checked='y'" : ""%>/> | |
132 <label for="merge" <%=isDisabled?"class='weak-color'":""%>>Merge into <%=Jtp.parentName(forum)%></label> | |
133 <%=isDisabled? "<span class='disabled important'>/ Not Applicable</span>":""%> | |
134 </div> | |
135 <div class="weak-color" style="margin-left:1.9em"> | |
136 Delete this <%=Jtp.viewName(forum).toLowerCase()%> and move its contents to the <%=Jtp.parentName(forum).toLowerCase()%>. <br/> | |
137 </div> | |
138 | |
139 <% isDisabled = !forum.isRoot() || forum.getChildCount() != 1; %> | |
140 <% Node child = isDisabled? null : forum.getChildren().get(0, 1).get(0); %> | |
141 <% isDisabled = child != null && child.getKind() == Node.Kind.POST? true : isDisabled; %> | |
142 <div class="second-font field-title"> | |
143 <input type="radio" <%=isDisabled?"disabled":""%> id="delete-root" name="option" value="delete-root" <%="delete-root".equals(option)? "checked='y'" : ""%>/> | |
144 <label for="delete-root" <%=isDisabled?"class='weak-color'":""%>>Make Child the New Root</label> | |
145 <%=isDisabled? "<span class='disabled important'>/ Not Applicable</span>":""%> | |
146 </div> | |
147 <div class="weak-color" style="margin-left:1.9em"> | |
148 Delete this <%=Jtp.viewName(forum).toLowerCase()%> and make <%=child == null? "the single child" : child.getSubjectHtml() %> the new root. <br/> | |
149 </div> | |
150 | |
151 <% isDisabled = forum.getParent() != null; %> | |
152 <div class="second-font field-title"> | |
153 <input type="radio" id="create-parent" name="option" value="create-parent" <%="create-parent".equals(option)? "checked='y'" : ""%> <%=isDisabled?"disabled":""%>/> | |
154 <label <%=isDisabled?"class='weak-color'":""%> for="create-parent">Create a New Parent</label> | |
155 <%=isDisabled? "<span class='disabled important'>/ Not Applicable</span>":""%> | |
156 </div> | |
157 <div class="weak-color" style="margin-left:1.9em"> | |
158 <table> | |
159 <tr> | |
160 <td>Name:</td> | |
161 <td><input id="name" <%=isDisabled?"disabled":""%> name="name" size="30" value="<%=Jtp.hideNull(request.getParameter("name"))%>" /></td> | |
162 </tr> | |
163 <tr> | |
164 <td>Type:</td> | |
165 <td> | |
166 <select id="type" name="type"> | |
167 <option value="<%=Node.Type.FORUM%>">Forum</option> | |
168 <option value="<%=Node.Type.CATEGORY%>">Category</option> | |
169 <option value="<%=Node.Type.BOARD%>">Board</option> | |
170 <option value="<%=Node.Type.MIXED%>">Mixed</option> | |
171 <option value="<%=Node.Type.GALLERY%>">Gallery</option> | |
172 <option value="<%=Node.Type.BLOG%>">Blog</option> | |
173 <option value="<%=Node.Type.NEWS%>">Newspaper</option> | |
174 </select> | |
175 </td> | |
176 </tr> | |
177 </table> | |
178 <div style="margin: .5em 0"> | |
179 Description:<br/> | |
180 <textarea id="description" <%=isDisabled?"disabled":""%> name="description" style="width:30em;height:10em"><%=Jtp.hideNull(request.getParameter("description"))%></textarea> | |
181 </div> | |
182 </div> | |
183 | |
184 <div style="margin-top:1.4em"> | |
185 <input type="submit" name="save" value="Save Changes" /> or <a href="<%=Jtp.path(forum)%>">Cancel</a> | |
186 </div> | |
187 </form> | |
188 | |
189 <% Shared.footer(request, response); %> | |
190 <% Shared.analytics(request,response); %> | |
191 </body> | |
192 </html> | |
193 <% | |
194 } | |
195 | |
196 private static String setParent(Node app, String url, HttpServletRequest request, HttpServletResponse response) | |
197 throws IOException, ServletException | |
198 { | |
199 if (url == null || url.trim().length() == 0 || !url.startsWith("http://")) { | |
200 return "You must provide a valid link."; | |
201 } else { | |
202 url = Jtp.noCid(url); | |
203 Node parent = UrlMapperNamespace.getNodeFromUrl(url); | |
204 if (parent == null || parent.getKind()!=Node.Kind.APP || !parent.getSite().equals(app.getSite())) { | |
205 if (Export.isValidExportServer(url)) { | |
206 // Send to export confirmation page | |
207 response.sendRedirect("/catalog/ExportConfirmation.jtp?node="+app.getId()+"&url="+HtmlUtils.urlEncode(url)); | |
208 return null; | |
209 } else { | |
210 return "The link you provided is not a valid Nabble application."; | |
211 } | |
212 } else if (parent.getSite().equals(app.getSite()) && parent.getAncestors().contains(app)) { | |
213 return "Circular relationship is not allowed."; | |
214 } else { | |
215 DbDatabase db = app.getSite().getDb(); | |
216 db.beginTransaction(); | |
217 try { | |
218 Node forumCopy = app.getGoodCopy(); | |
219 forumCopy.changeParent(parent); | |
220 forumCopy.update(); | |
221 db.commitTransaction(); | |
222 | |
223 forumCopy = forumCopy.getGoodCopy(); | |
224 Shared.javascriptRedirect(request, response, Jtp.url(forumCopy), null, true); | |
225 return null; | |
226 } catch(ModelException.NodeLoop e) { | |
227 if (parent.equals(app)) | |
228 return "The new parent cannot be the forum itself."; | |
229 else | |
230 return "The new parent cannot be a descendant of the current forum (circular relationship)."; | |
231 } catch (ModelException e) { | |
232 logger.error("",e); | |
233 return "You cannot move this forum here because: "+e.getMessage(); | |
234 } finally { | |
235 db.endTransaction(); | |
236 } | |
237 } | |
238 } | |
239 } | |
240 | |
241 private static String merge(Node app, Person visitor, boolean isSiteAdmin, HttpServletResponse response) | |
242 throws IOException, ServletException | |
243 { | |
244 if (isSiteAdmin || Jtp.canBeDeletedBy(app,visitor)) { | |
245 DbDatabase db = app.getSite().getDb(); | |
246 db.beginTransaction(); | |
247 try { | |
248 app = app.getGoodCopy(); | |
249 Node parent = app.getParent(); | |
250 for (Node child : app.getChildren()) { | |
251 child.changeParent(parent); | |
252 } | |
253 app.getGoodCopy().deleteMessageOrNode(); | |
254 db.commitTransaction(); | |
255 response.sendRedirect(Jtp.path(parent)); | |
256 return null; | |
257 } catch (ModelException e) { | |
258 return e.getMessage(); | |
259 } finally { | |
260 db.endTransaction(); | |
261 } | |
262 } else { | |
263 return "You don't have privileges to delete and merge this sub-forum"; | |
264 } | |
265 } | |
266 | |
267 private static String deleteRoot(Node app, Person visitor, HttpServletResponse response) | |
268 throws IOException, ServletException | |
269 { | |
270 if (Jtp.canBeDeletedBy(app,visitor)) { | |
271 DbDatabase db = app.getSite().getDb(); | |
272 db.beginTransaction(); | |
273 try { | |
274 Site site = app.getSite(); | |
275 site.deleteRootNode(); | |
276 db.commitTransaction(); | |
277 response.sendRedirect(site.getBaseUrl()); | |
278 return null; | |
279 } catch (ModelException e) { | |
280 return e.getMessage(); | |
281 } finally { | |
282 db.endTransaction(); | |
283 } | |
284 } else { | |
285 return "You don't have privileges to make the child a new root"; | |
286 } | |
287 } | |
288 | |
289 private static String createParent(Node app, User user, HttpServletRequest request, HttpServletResponse response) | |
290 throws IOException, ServletException | |
291 { | |
292 DbDatabase db = app.getSite().getDb(); | |
293 db.beginTransaction(); | |
294 try { | |
295 String name = request.getParameter("name"); | |
296 if (name == null || name.trim().length() == 0) | |
297 return "Please enter a valid name"; | |
298 String description = request.getParameter("description"); | |
299 String type = request.getParameter("type"); | |
300 Node parent = user.newRootNode(Node.Kind.APP, name, description, Message.Format.TEXT, app.getSite(),type); | |
301 Jtp.addPinnedChild(parent, app.getGoodCopy()); | |
302 db.commitTransaction(); | |
303 response.sendRedirect(Jtp.path(parent)); | |
304 return null; | |
305 } catch (ModelException e) { | |
306 return e.getMessage(); | |
307 } finally { | |
308 db.endTransaction(); | |
309 } | |
310 } | |
311 } | |
312 %> |