View Javadoc

1   /**
2    * This file Copyright (c) 2003-2011 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.core.Content;
37  import info.magnolia.cms.gui.control.Button;
38  import info.magnolia.cms.gui.control.Edit;
39  import info.magnolia.cms.gui.control.Hidden;
40  import info.magnolia.cms.gui.control.Select;
41  import info.magnolia.cms.gui.dialog.DialogBox;
42  import info.magnolia.cms.gui.dialog.DialogButton;
43  import info.magnolia.cms.gui.dialog.DialogFactory;
44  import info.magnolia.cms.gui.misc.CssConstants;
45  import info.magnolia.cms.i18n.Messages;
46  import info.magnolia.cms.i18n.MessagesManager;
47  import info.magnolia.cms.util.ContentUtil;
48  import info.magnolia.module.admininterface.AdminInterfaceModule;
49  import info.magnolia.module.admininterface.config.AclTypeConfiguration;
50  import info.magnolia.module.admininterface.config.PermissionConfiguration;
51  import info.magnolia.module.admininterface.config.RepositoryConfiguration;
52  import info.magnolia.module.admininterface.config.SecurityConfiguration;
53  import info.magnolia.repository.RepositoryConstants;
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     @Override
157     public void drawHtml(Writer w) throws IOException {
158         PrintWriter out = (PrintWriter) w;
159         this.drawHtmlPre(out);
160         renderACLS(out);
161         this.drawHtmlPost(out);
162 
163     }
164 
165     protected void renderACLS(PrintWriter out) throws IOException {
166         Messages msgs = MessagesManager.getMessages();
167         Content role = getStorageNode();
168         HttpServletRequest request = this.getRequest();
169         HttpServletResponse response = this.getResponse();
170 
171         // select the repository
172         Select repositorySelect = getRepositorySelect();
173 
174         out.print(repositorySelect.getHtml());
175         out.print("<p><p/>"); //$NON-NLS-1$
176 
177         // process with the real existing repositories
178         for (Iterator iter = securityConf.getVisibleRepositories().iterator(); iter.hasNext();) {
179             RepositoryConfiguration repositoryConf = (RepositoryConfiguration) iter.next();
180             try {
181                 writeRepositoryTable(request, response, msgs, out, role, repositoryConf);
182             }
183             catch (RepositoryException e) {
184                 throw new RuntimeException("can't list ", e);
185             }
186         }
187 
188         // out.print("<p>&nbsp;<p>&nbsp;<p>&nbsp;<input type=\"button\" onclick=\"aclChangeRepository('website')\">");
189         out.println("<script type=\"text/javascript\">aclChangeRepository('website');</script>"); //$NON-NLS-1$
190     }
191 
192     /**
193      * @param request
194      * @param out
195      * @param role
196      * @throws RepositoryException
197      * @throws IOException
198      */
199     protected void writeRepositoryTable(HttpServletRequest request,  HttpServletResponse response, Messages msgs,
200         PrintWriter out, Content role, RepositoryConfiguration repoConf) throws RepositoryException, IOException {
201         String tableName = "acl" + repoConf.getName() + "Table"; //$NON-NLS-1$ //$NON-NLS-2$
202         String dynamicTableName = "acl" + repoConf.getName() + "DynamicTable"; //$NON-NLS-1$ //$NON-NLS-2$
203         String hiddenFieldName = "acl" + repoConf.getName() + "List"; //$NON-NLS-1$ //$NON-NLS-2$
204 
205         out.println("<div id=\"acl" + repoConf.getName() + "Div\" class=\"" + CSS_ACL_DIV + "\">"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
206         out.println(new Hidden(hiddenFieldName, StringUtils.EMPTY, false).getHtml());
207 
208         // the table
209         out.println("<table id=\"" //$NON-NLS-1$
210             + tableName
211             + "\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\" width=\"100%\"><tr><td></td></tr></table>"); //$NON-NLS-1$
212 
213         // add button
214         out.println("<table width=\"100%\">"); //$NON-NLS-1$
215         DialogButton add = DialogFactory.getDialogButtonInstance(request, response, null, null);
216         add.setBoxType(DialogBox.BOXTYPE_1COL);
217         add.setConfig("buttonLabel", msgs.get("buttons.add")); //$NON-NLS-1$ //$NON-NLS-2$
218         add.setConfig("onclick", dynamicTableName + ".addNew();"); //$NON-NLS-1$ //$NON-NLS-2$
219         add.drawHtml(out);
220         out.println("</table>"); //$NON-NLS-1$
221 
222         out.println("</div>"); //$NON-NLS-1$
223 
224         out.println("<script type=\"text/javascript\">"); //$NON-NLS-1$
225         // register the repository
226         out.println("aclRepositories[aclRepositories.length]= '" + repoConf.getName() + "';"); //$NON-NLS-1$ //$NON-NLS-2$
227 
228         // make renderer function
229         out.println("function acl" + repoConf.getName() + "RenderFunction(cell, prefix, index, object)"); //$NON-NLS-1$ //$NON-NLS-2$
230         out.println("{"); //$NON-NLS-1$
231 
232         // get some debug informations
233         out.println("mgnlDebug('acl" + repoConf.getName() + "RenderFunction: prefix = ' + prefix, 'acl', object)");
234         out.println("cell.innerHTML= '" + getHtmlRowInner(dynamicTableName, repoConf) + "';\n"); //$NON-NLS-1$ //$NON-NLS-2$
235         out.println("document.getElementById(prefix + 'AccessType').value = object.accessType;\n"); //$NON-NLS-1$
236         out.println("document.getElementById(prefix + 'AccessRight').value = object.accessRight;\n"); //$NON-NLS-1$
237 
238         out.println("}"); //$NON-NLS-1$
239 
240         // create the dynamicTable
241         out.println(dynamicTableName + " = new MgnlDynamicTable('" //$NON-NLS-1$
242             + tableName
243             + "',document.getElementById('mgnlFormMain')." //$NON-NLS-1$
244             + hiddenFieldName
245             + ", aclGetNewPermissionObject, aclGetPermissionObject, acl" //$NON-NLS-1$
246             + repoConf.getName()
247             + "RenderFunction, null);"); //$NON-NLS-1$
248 
249         // add existing acls to table (by js, so the same mechanism as at
250         // adding rows can be used)
251         addExistingAclToTable(out, role, dynamicTableName, repoConf);
252 
253         out.println("</script>"); //$NON-NLS-1$
254     }
255 
256     /**
257      * @param out
258      * @param role
259      */
260     private void addExistingAclToTable(PrintWriter out, Content role, String dynamicTableName,
261         RepositoryConfiguration repoConf) {
262         // keeps acls per path
263         ACLS acls = new ACLS();
264 
265         Content aclsNode = ContentUtil.getContent(role, "acl_" + repoConf.getName()); //$NON-NLS-1$
266         if (aclsNode == null || aclsNode.getChildren().size() == 0) {
267             out.println(dynamicTableName + ".addNew();"); //$NON-NLS-1$
268             return;
269         }
270 
271         Iterator it = aclsNode.getChildren().iterator();
272         while (it.hasNext()) {
273             Content c = (Content) it.next();
274             String path = c.getNodeData("path").getString(); //$NON-NLS-1$
275             String accessRight = c.getNodeData("permissions").getString(); //$NON-NLS-1$
276             acls.register(path, Integer.valueOf(accessRight).intValue(), repoConf);
277         }
278 
279         for (Iterator iter = acls.values().iterator(); iter.hasNext();) {
280             ACL acl = (ACL) iter.next();
281             out.println(dynamicTableName + ".add({accessRight:" //$NON-NLS-1$
282                 + acl.accessRight
283                 + ",accessType:'" //$NON-NLS-1$
284                 + acl.type
285                 + "',path:'" //$NON-NLS-1$
286                 + acl.path
287                 + "'});"); //$NON-NLS-1$
288         }
289     }
290 
291     private Select getRepositorySelect() {
292         Select repositorySelect = new Select();
293         repositorySelect.setName("aclRepository"); //$NON-NLS-1$
294         repositorySelect.setCssClass("mgnlDialogControlSelect"); //$NON-NLS-1$
295         repositorySelect.setEvent("onchange", "aclChangeRepository(this.value)"); //$NON-NLS-1$ //$NON-NLS-2$
296         repositorySelect.setSaveInfo(false);
297         repositorySelect.setValue(RepositoryConstants.WEBSITE);
298 
299         for (Iterator iter = securityConf.getVisibleRepositories().iterator(); iter.hasNext();) {
300             RepositoryConfiguration repoConf = (RepositoryConfiguration) iter.next();
301             repositorySelect.setOptions(repoConf.getI18nLabel(), repoConf.getName());
302         }
303         return repositorySelect;
304     }
305 
306     private static String escapeJs(String value) {
307         return StringUtils.replace(value, "'", "\\'");
308     }
309 
310     /**
311      * A concrete gui acl
312      * @author Philipp Bracher
313      * @version $Revision: 50687 $ ($Author: dlipp $)
314      */
315     protected class ACL {
316 
317         int type = 0;
318 
319         String path;
320 
321         int accessRight;
322 
323         void registerEntry(String path) {
324             if (path.equals("/*")) {
325                 type = AclTypeConfiguration.TYPE_ALL;
326             }
327             else if (path.endsWith("/*")) {
328                 type = type | AclTypeConfiguration.TYPE_SUBS;
329             }
330             else {
331                 type = type | AclTypeConfiguration.TYPE_THIS;
332             }
333         }
334     }
335 
336     /**
337      * Used to create the gui values out of the entries in the repository
338      * @author Philipp Bracher
339      * @version $Revision: 50687 $ ($Author: dlipp $)
340      */
341     protected class ACLS extends ListOrderedMap {
342 
343         /**
344          * Register an entry
345          * @param path the not cleaned path
346          * @param accessRight the access right
347          */
348         void register(String path, int accessRight, RepositoryConfiguration repoConf) {
349             String cleanPath = repoConf.toViewPattern(path);
350 
351             String key = cleanPath + ":" + accessRight;
352             if (!this.containsKey(key)) {
353                 ACL acl = new ACL();
354                 acl.path = cleanPath;
355                 acl.accessRight = accessRight;
356                 this.put(key, acl);
357             }
358             ((ACL) this.get(key)).registerEntry(path);
359         }
360     }
361 
362 }