View Javadoc

1   /**
2    * This file Copyright (c) 2003-2010 Magnolia International
3    * Ltd.  (http://www.magnolia-cms.com). All rights reserved.
4    *
5    *
6    * This file is dual-licensed under both the Magnolia
7    * Network Agreement and the GNU General Public License.
8    * You may elect to use one or the other of these licenses.
9    *
10   * This file is distributed in the hope that it will be
11   * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
12   * implied warranty of MERCHANTABILITY or FITNESS FOR A
13   * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
14   * Redistribution, except as permitted by whichever of the GPL
15   * or MNA you select, is prohibited.
16   *
17   * 1. For the GPL license (GPL), you can redistribute and/or
18   * modify this file under the terms of the GNU General
19   * Public License, Version 3, as published by the Free Software
20   * Foundation.  You should have received a copy of the GNU
21   * General Public License, Version 3 along with this program;
22   * if not, write to the Free Software Foundation, Inc., 51
23   * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24   *
25   * 2. For the Magnolia Network Agreement (MNA), this file
26   * and the accompanying materials are made available under the
27   * terms of the MNA which accompanies this distribution, and
28   * is available at http://www.magnolia-cms.com/mna.html
29   *
30   * Any modifications to this file must keep this entire header
31   * intact.
32   *
33   */
34  package info.magnolia.module.admininterface.dialogs;
35  
36  import info.magnolia.cms.beans.config.ContentRepository;
37  import info.magnolia.cms.core.Content;
38  import info.magnolia.cms.gui.control.Button;
39  import info.magnolia.cms.gui.control.Edit;
40  import info.magnolia.cms.gui.control.Hidden;
41  import info.magnolia.cms.gui.control.Select;
42  import info.magnolia.cms.gui.dialog.DialogBox;
43  import info.magnolia.cms.gui.dialog.DialogButton;
44  import info.magnolia.cms.gui.dialog.DialogFactory;
45  import info.magnolia.cms.gui.misc.CssConstants;
46  import info.magnolia.cms.i18n.Messages;
47  import info.magnolia.cms.i18n.MessagesManager;
48  import info.magnolia.cms.util.ContentUtil;
49  import info.magnolia.module.admininterface.AdminInterfaceModule;
50  import info.magnolia.module.admininterface.config.AclTypeConfiguration;
51  import info.magnolia.module.admininterface.config.PermissionConfiguration;
52  import info.magnolia.module.admininterface.config.RepositoryConfiguration;
53  import info.magnolia.module.admininterface.config.SecurityConfiguration;
54  
55  import java.io.IOException;
56  import java.io.PrintWriter;
57  import java.io.Writer;
58  import java.util.Iterator;
59  
60  import javax.jcr.RepositoryException;
61  import javax.servlet.http.HttpServletRequest;
62  import javax.servlet.http.HttpServletResponse;
63  
64  import org.apache.commons.collections.map.ListOrderedMap;
65  import org.apache.commons.lang.StringUtils;
66  
67  
68  /**
69   * @author Fabrizio Giustina
70   * @version $Id:RolesACLPage.java 2516 2006-03-31 13:08:03Z philipp $
71   */
72  public class ACLSDialogControl extends DialogBox {
73  
74      private static final String CSS_ACL_DIV = "aclDynamicTable"; //$NON-NLS-1$
75  
76      private SecurityConfiguration securityConf = AdminInterfaceModule.getInstance().getSecurityConfiguration();
77  
78      private static String getHtmlRowInner(String dynamicTable, RepositoryConfiguration repoConf) {
79          boolean small = true;
80          Messages msgs = MessagesManager.getMessages();
81  
82          Select accessRight = new Select();
83          accessRight.setSaveInfo(false);
84          accessRight.setName("'+prefix+'AccessRight"); //$NON-NLS-1$
85          accessRight.setCssClass("mgnlDialogControlSelect"); //$NON-NLS-1$
86  
87          for (Iterator iter = repoConf.getPermissions().iterator(); iter.hasNext();) {
88              PermissionConfiguration permission = (PermissionConfiguration) iter.next();
89              accessRight.setOptions(escapeJs(permission.getI18nLabel()), Long.toString(permission.getValue())); //$NON-NLS-1$
90          }
91  
92          accessRight.setValue("' + object.accessRight + '"); //$NON-NLS-1$
93  
94          Select accessType = new Select();
95          accessType.setSaveInfo(false);
96          accessType.setName("'+prefix+'AccessType"); //$NON-NLS-1$
97          accessType.setCssClass("mgnlDialogControlSelect"); //$NON-NLS-1$
98  
99          for (Iterator iter = repoConf.getAclTypes().iterator(); iter.hasNext();) {
100             AclTypeConfiguration patternType = (AclTypeConfiguration) iter.next();
101             accessType.setOptions(escapeJs(patternType.getI18nLabel()), String.valueOf(patternType.getType())); //$NON-NLS-1$
102         }
103 
104         accessType.setValue("' + object.accessType + '"); //$NON-NLS-1$
105 
106         Edit path = new Edit();
107         path.setSaveInfo(false);
108         path.setName("'+prefix+'Path"); //$NON-NLS-1$
109         path.setValue("'+object.path+'"); //$NON-NLS-1$
110         path.setCssClass(CssConstants.CSSCLASS_EDIT);
111         path.setCssStyles("width", "100%"); //$NON-NLS-1$ //$NON-NLS-2$
112 
113         Button choose = null;
114         if(repoConf.isChooseButton()){
115             choose = new Button();
116             choose.setLabel(escapeJs(msgs.get("buttons.choose"))); //$NON-NLS-1$
117             choose.setOnclick("aclChoose(\\''+prefix+'\\',\\'" + repoConf.getName() + "\\');"); //$NON-NLS-1$ //$NON-NLS-2$
118             choose.setSmall(small);
119         }
120 
121         Button delete = new Button();
122         delete.setLabel(escapeJs(msgs.get("buttons.delete"))); //$NON-NLS-1$
123         delete.setOnclick(dynamicTable + ".del('+index+');"); //$NON-NLS-1$
124         delete.setSmall(small);
125 
126         StringBuffer html = new StringBuffer();
127         // set as table since ie/win does not support setting of innerHTML of a
128         // tr
129         html.append("<table cellpadding=\"0\" cellspacing=\"0\" width=\"100%\"><tr>"); //$NON-NLS-1$
130         html.append("<td width=\"1\" class=\"" + CssConstants.CSSCLASS_EDITWITHBUTTON + "\">").append(accessRight.getHtml()).append("</td>"); //$NON-NLS-1$
131         html.append("<td width=\"1\" class=\"mgnlDialogBoxInput\"></td>"); //$NON-NLS-1$
132 
133         // do we add the type selection dropdown?
134         if(!repoConf.getAclTypes().isEmpty()){
135             html.append("<td width=\"1\" class=\"" + CssConstants.CSSCLASS_EDITWITHBUTTON + "\">").append(accessType.getHtml()).append("</td>"); //$NON-NLS-1$
136             html.append("<td width=\"1\"></td>"); //$NON-NLS-1$
137         }
138         else {
139             html.append("<input type=\"hidden\" id=\"' + prefix + 'AccessType\" name=\"' + prefix + 'AccessType\" value=\"sub\"/>"); //$NON-NLS-1$
140         }
141 
142         html.append("<td width=\"100%\"class=\"" + CssConstants.CSSCLASS_EDITWITHBUTTON + "\">").append(path.getHtml()).append("</td>"); //$NON-NLS-1$
143         html.append("<td width=\"1\"></td>"); //$NON-NLS-1$
144 
145         if (choose != null) {
146             html.append("<td width=\"1\" class=\"" + CssConstants.CSSCLASS_EDITWITHBUTTON + "\">").append(choose.getHtml()).append("</td>"); //$NON-NLS-1$
147             html.append("<td width=\"1\"></td>"); //$NON-NLS-1$
148         }
149 
150         html.append("<td width=\"1\" class=\"" + CssConstants.CSSCLASS_EDITWITHBUTTON + "\">").append(delete.getHtml()).append("</td>"); //$NON-NLS-1$
151         html.append("</tr></table>"); //$NON-NLS-1$
152 
153         return html.toString();
154     }
155 
156     public void drawHtml(Writer w) throws IOException {
157         PrintWriter out = (PrintWriter) w;
158         this.drawHtmlPre(out);
159         renderACLS(out);
160         this.drawHtmlPost(out);
161 
162     }
163 
164     protected void renderACLS(PrintWriter out) throws IOException {
165         Messages msgs = MessagesManager.getMessages();
166         Content role = getStorageNode();
167         HttpServletRequest request = this.getRequest();
168         HttpServletResponse response = this.getResponse();
169 
170         // select the repository
171         Select repositorySelect = getRepositorySelect();
172 
173         out.print(repositorySelect.getHtml());
174         out.print("<p><p/>"); //$NON-NLS-1$
175 
176         // process with the real existing repositories
177         for (Iterator iter = securityConf.getVisibleRepositories().iterator(); iter.hasNext();) {
178             RepositoryConfiguration repositoryConf = (RepositoryConfiguration) iter.next();
179             try {
180                 writeRepositoryTable(request, response, msgs, out, role, repositoryConf);
181             }
182             catch (RepositoryException e) {
183                 throw new RuntimeException("can't list ", e);
184             }
185         }
186 
187         // out.print("<p>&nbsp;<p>&nbsp;<p>&nbsp;<input type=\"button\" onclick=\"aclChangeRepository('website')\">");
188         out.println("<script type=\"text/javascript\">aclChangeRepository('website');</script>"); //$NON-NLS-1$
189     }
190 
191     /**
192      * @param request
193      * @param out
194      * @param role
195      * @throws RepositoryException
196      * @throws IOException
197      */
198     protected void writeRepositoryTable(HttpServletRequest request,  HttpServletResponse response, Messages msgs,
199         PrintWriter out, Content role, RepositoryConfiguration repoConf) throws RepositoryException, IOException {
200         String tableName = "acl" + repoConf.getName() + "Table"; //$NON-NLS-1$ //$NON-NLS-2$
201         String dynamicTableName = "acl" + repoConf.getName() + "DynamicTable"; //$NON-NLS-1$ //$NON-NLS-2$
202         String hiddenFieldName = "acl" + repoConf.getName() + "List"; //$NON-NLS-1$ //$NON-NLS-2$
203 
204         out.println("<div id=\"acl" + repoConf.getName() + "Div\" class=\"" + CSS_ACL_DIV + "\">"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
205         out.println(new Hidden(hiddenFieldName, StringUtils.EMPTY, false).getHtml());
206 
207         // the table
208         out.println("<table id=\"" //$NON-NLS-1$
209             + tableName
210             + "\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\" width=\"100%\"><tr><td></td></tr></table>"); //$NON-NLS-1$
211 
212         // add button
213         out.println("<table width=\"100%\">"); //$NON-NLS-1$
214         DialogButton add = DialogFactory.getDialogButtonInstance(request, response, null, null);
215         add.setBoxType(DialogBox.BOXTYPE_1COL);
216         add.setConfig("buttonLabel", msgs.get("buttons.add")); //$NON-NLS-1$ //$NON-NLS-2$
217         add.setConfig("onclick", dynamicTableName + ".addNew();"); //$NON-NLS-1$ //$NON-NLS-2$
218         add.drawHtml(out);
219         out.println("</table>"); //$NON-NLS-1$
220 
221         out.println("</div>"); //$NON-NLS-1$
222 
223         out.println("<script type=\"text/javascript\">"); //$NON-NLS-1$
224         // register the repository
225         out.println("aclRepositories[aclRepositories.length]= '" + repoConf.getName() + "';"); //$NON-NLS-1$ //$NON-NLS-2$
226 
227         // make renderer function
228         out.println("function acl" + repoConf.getName() + "RenderFunction(cell, prefix, index, object)"); //$NON-NLS-1$ //$NON-NLS-2$
229         out.println("{"); //$NON-NLS-1$
230 
231         // get some debug informations
232         out.println("mgnlDebug('acl" + repoConf.getName() + "RenderFunction: prefix = ' + prefix, 'acl', object)");
233         out.println("cell.innerHTML= '" + getHtmlRowInner(dynamicTableName, repoConf) + "';\n"); //$NON-NLS-1$ //$NON-NLS-2$
234         out.println("document.getElementById(prefix + 'AccessType').value = object.accessType;\n"); //$NON-NLS-1$
235         out.println("document.getElementById(prefix + 'AccessRight').value = object.accessRight;\n"); //$NON-NLS-1$
236 
237         out.println("}"); //$NON-NLS-1$
238 
239         // create the dynamicTable
240         out.println(dynamicTableName + " = new MgnlDynamicTable('" //$NON-NLS-1$
241             + tableName
242             + "',document.getElementById('mgnlFormMain')." //$NON-NLS-1$
243             + hiddenFieldName
244             + ", aclGetNewPermissionObject, aclGetPermissionObject, acl" //$NON-NLS-1$
245             + repoConf.getName()
246             + "RenderFunction, null);"); //$NON-NLS-1$
247 
248         // add existing acls to table (by js, so the same mechanism as at
249         // adding rows can be used)
250         addExistingAclToTable(out, role, dynamicTableName, repoConf);
251 
252         out.println("</script>"); //$NON-NLS-1$
253     }
254 
255     /**
256      * @param out
257      * @param role
258      */
259     private void addExistingAclToTable(PrintWriter out, Content role, String dynamicTableName,
260         RepositoryConfiguration repoConf) {
261         // keeps acls per path
262         ACLS acls = new ACLS();
263 
264         Content aclsNode = ContentUtil.getContent(role, "acl_" + repoConf.getName()); //$NON-NLS-1$
265         if (aclsNode == null || aclsNode.getChildren().size() == 0) {
266             out.println(dynamicTableName + ".addNew();"); //$NON-NLS-1$
267             return;
268         }
269 
270         Iterator it = aclsNode.getChildren().iterator();
271         while (it.hasNext()) {
272             Content c = (Content) it.next();
273             String path = c.getNodeData("path").getString(); //$NON-NLS-1$
274             String accessRight = c.getNodeData("permissions").getString(); //$NON-NLS-1$
275             acls.register(path, Integer.valueOf(accessRight).intValue(), repoConf);
276         }
277 
278         for (Iterator iter = acls.values().iterator(); iter.hasNext();) {
279             ACL acl = (ACL) iter.next();
280             out.println(dynamicTableName + ".add({accessRight:" //$NON-NLS-1$
281                 + acl.accessRight
282                 + ",accessType:'" //$NON-NLS-1$
283                 + acl.type
284                 + "',path:'" //$NON-NLS-1$
285                 + acl.path
286                 + "'});"); //$NON-NLS-1$
287         }
288     }
289 
290     private Select getRepositorySelect() {
291         Select repositorySelect = new Select();
292         repositorySelect.setName("aclRepository"); //$NON-NLS-1$
293         repositorySelect.setCssClass("mgnlDialogControlSelect"); //$NON-NLS-1$
294         repositorySelect.setEvent("onchange", "aclChangeRepository(this.value)"); //$NON-NLS-1$ //$NON-NLS-2$
295         repositorySelect.setSaveInfo(false);
296         repositorySelect.setValue(ContentRepository.WEBSITE);
297 
298         for (Iterator iter = securityConf.getVisibleRepositories().iterator(); iter.hasNext();) {
299             RepositoryConfiguration repoConf = (RepositoryConfiguration) iter.next();
300             repositorySelect.setOptions(repoConf.getI18nLabel(), repoConf.getName());
301         }
302         return repositorySelect;
303     }
304 
305     private static String escapeJs(String value) {
306         return StringUtils.replace(value, "'", "\\'");
307     }
308 
309     /**
310      * A concrete gui acl
311      * @author Philipp Bracher
312      * @version $Revision: 32667 $ ($Author: gjoseph $)
313      */
314     protected class ACL {
315 
316         int type = 0;
317 
318         String path;
319 
320         int accessRight;
321 
322         void registerEntry(String path) {
323             if (path.equals("/*")) {
324                 type = AclTypeConfiguration.TYPE_ALL;
325             }
326             else if (path.endsWith("/*")) {
327                 type = type | AclTypeConfiguration.TYPE_SUBS;
328             }
329             else {
330                 type = type | AclTypeConfiguration.TYPE_THIS;
331             }
332         }
333     }
334 
335     /**
336      * Used to create the gui values out of the entries in the repository
337      * @author Philipp Bracher
338      * @version $Revision: 32667 $ ($Author: gjoseph $)
339      */
340     protected class ACLS extends ListOrderedMap {
341 
342         /**
343          * Register an entry
344          * @param path the not cleaned path
345          * @param accessRight the access right
346          */
347         void register(String path, int accessRight, RepositoryConfiguration repoConf) {
348             String cleanPath = repoConf.toViewPattern(path);
349 
350             String key = cleanPath + ":" + accessRight;
351             if (!this.containsKey(key)) {
352                 ACL acl = new ACL();
353                 acl.path = cleanPath;
354                 acl.accessRight = accessRight;
355                 this.put(key, acl);
356             }
357             ((ACL) this.get(key)).registerEntry(path);
358         }
359     }
360 
361 }