View Javadoc
1   /**
2    * This file Copyright (c) 2016-2018 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.security.app.tools.permission;
35  
36  import info.magnolia.cms.security.AccessDeniedException;
37  import info.magnolia.cms.security.Group;
38  import info.magnolia.cms.security.Permission;
39  import info.magnolia.cms.security.Role;
40  import info.magnolia.cms.security.SecuritySupport;
41  import info.magnolia.cms.security.User;
42  import info.magnolia.cms.security.auth.ACL;
43  import info.magnolia.i18nsystem.SimpleTranslator;
44  import info.magnolia.security.app.tools.AbstractSecurityToolPresenter;
45  import info.magnolia.security.app.tools.SecurityToolView;
46  import info.magnolia.ui.api.context.UiContext;
47  import info.magnolia.ui.dialog.formdialog.FormBuilder;
48  import info.magnolia.ui.framework.tools.FormToolActionExecutor;
49  
50  import java.util.Arrays;
51  import java.util.Collections;
52  import java.util.Iterator;
53  import java.util.List;
54  
55  import javax.inject.Inject;
56  
57  import org.apache.commons.lang3.StringEscapeUtils;
58  
59  import com.google.common.collect.HashBasedTable;
60  import com.google.common.collect.Table;
61  import com.vaadin.v7.data.Container;
62  import com.vaadin.v7.data.Item;
63  import com.vaadin.v7.data.util.BeanItem;
64  import com.vaadin.v7.data.util.HierarchicalContainer;
65  
66  /**
67   * The security tools help verifying the system's security setup and ACLs.
68   */
69  public class PermissionToolPresenter extends AbstractSecurityToolPresenter {
70  
71      private final SecuritySupport securitySupport;
72      private final SimpleTranslator i18n;
73      private PermissionViewOption viewOption;
74  
75      @Inject
76      public PermissionToolPresenter(SecurityToolView view, FormBuilder formBuilder, FormToolActionExecutor actionExecutor,
77                                     UiContext uiContext, SecuritySupport securitySupport, SimpleTranslator i18n) {
78          super(view, formBuilder, actionExecutor, uiContext);
79          this.securitySupport = securitySupport;
80          this.i18n = i18n;
81      }
82  
83      @Override
84      protected Item getItem() {
85          viewOption = new PermissionViewOption();
86          return new BeanItem<>(viewOption);
87      }
88  
89      @Override
90      protected Container.Hierarchical buildContainer() throws AccessDeniedException {
91          container = new HierarchicalContainer();
92          container.addContainerProperty(VALUE_ID, String.class, "");
93  
94          Iterator<String> iterGroups = Collections.emptyIterator();
95          Iterator<String> iterRoles = Collections.emptyIterator();
96          switch (viewOption.getType()) {
97          case GROUP:
98              Group group = securitySupport.getGroupManager().getGroup(viewOption.getName());
99              if (group == null) {
100                 return null;
101             }
102             iterGroups = group.getGroups().iterator();
103             iterRoles = group.getRoles().iterator();
104             break;
105         case USER:
106             User user = securitySupport.getUserManager().getUser(viewOption.getName());
107             if (user == null) {
108                 return null;
109             }
110             iterGroups = user.getGroups().iterator();
111             iterRoles = user.getRoles().iterator();
112             break;
113         default:
114             break;
115         }
116 
117         boolean withPermissions = DumpMode.WITH_PERMISSIONS.equals(viewOption.getDumpMode());
118         getGroupRole(iterGroups, withPermissions, null);
119         getRole(iterRoles, withPermissions, null);
120 
121         // Resolve parent tree node
122         for (Object itemId : container.getItemIds()) {
123             container.setChildrenAllowed(itemId, container.getChildren(itemId) != null && container.getChildren(itemId).size() > 0);
124         }
125 
126         return container;
127     }
128 
129     @Override
130     protected String getErrorMessage() {
131         String errorKey = String.format("security.permissionsTab.%s.error", viewOption.getType().name().toLowerCase());
132         return i18n.translate(errorKey, StringEscapeUtils.escapeHtml4(viewOption.getName()));
133     }
134 
135     /**
136      * Finding and adding subgroups to container.
137      */
138     private void getGroupRole(Iterator<String> iterGroup, boolean withPermissions, Object parentId) throws AccessDeniedException {
139         while (iterGroup.hasNext()) {
140             String groupName = iterGroup.next();
141             Group group = securitySupport.getGroupManager().getGroup(groupName);
142             if (group != null) {
143                 Object itemId = addContainerItem(VALUE_ID, getGroupRepresentation(group.getName()), parentId);
144 
145                 getGroupRole(group.getGroups().iterator(), withPermissions, itemId);
146                 getRole(group.getRoles().iterator(), withPermissions, itemId);
147             } else {
148                 addContainerItem(VALUE_ID, getGroupRepresentation(groupName), parentId);
149             }
150         }
151     }
152 
153     /**
154      * Finding and adding roles to container.
155      */
156     private void getRole(Iterator<String> iterRoles, boolean withPermissions, Object parentId) {
157         while (iterRoles.hasNext()) {
158             Role role = securitySupport.getRoleManager().getRole(iterRoles.next());
159             Object itemId = addContainerItem(VALUE_ID, getRoleRepresentation(role), parentId);
160             if (withPermissions) {
161                 getPermission(role.getName(), itemId);
162             }
163         }
164     }
165 
166     /**
167      * Finding and adding permissions to container.
168      */
169     private void getPermission(String role, Object parentId) {
170         Iterator<ACL> iterPermission = securitySupport.getRoleManager().getACLs(role).values().iterator();
171         while (iterPermission.hasNext()) {
172             ACL acl = iterPermission.next();
173             for (Permission permission : acl.getList()) {
174                 addContainerItem(VALUE_ID, getPermissionRepresentation(permission, acl.getName()), parentId);
175             }
176         }
177     }
178 
179     private String getGroupRepresentation(String groupName) {
180         return i18n.translate("security.tools.results.group", groupName);
181     }
182 
183     private String getRoleRepresentation(Role role) {
184         return i18n.translate("security.tools.results.role", role.getName());
185     }
186 
187     private String getPermissionRepresentation(Permission permission, String repoName) {
188         return i18n.translate("security.tools.results.permission", new String[] { getPermissionAsName(repoName, permission), repoName, permission.getPattern().getPatternString() });
189     }
190 
191     /**
192      * Mapping permission to name.
193      */
194     private String getPermissionAsName(String repoName, Permission permission) {
195         String messageKeyName;
196 
197         if (!REPO_NAMES.contains(repoName)) {
198             repoName = "";
199         }
200         messageKeyName = PERMISSION_MESSAGES.get(repoName, permission.getPermissions());
201 
202         if (messageKeyName == null) {
203             return ("(" + permission.getPermissions() + ") unknown ");
204         }
205 
206         return i18n.translate(messageKeyName);
207     }
208 
209 
210     private static final List<String> REPO_NAMES = Arrays.asList("uri", "forum");
211     private static final Table<String, Long, String> PERMISSION_MESSAGES = HashBasedTable.create();
212 
213     static {
214         PERMISSION_MESSAGES.put("uri", 0L, "roles.permission.deny");
215         PERMISSION_MESSAGES.put("uri", Permission.READ, "roles.permission.get");
216         PERMISSION_MESSAGES.put("uri", Permission.ALL, "roles.permission.getAndPost");
217 
218         PERMISSION_MESSAGES.put("forum", 0L, "roles.permission.deny");
219         PERMISSION_MESSAGES.put("forum", Permission.READ, "roles.permission.readOnly");
220         PERMISSION_MESSAGES.put("forum", Permission.WRITE, "roles.permission.post");
221         PERMISSION_MESSAGES.put("forum", 75L, "roles.permission.moderate");
222         PERMISSION_MESSAGES.put("forum", 79L, "roles.permission.moderateAndDelete");
223         PERMISSION_MESSAGES.put("forum", 111L, "roles.permission.admin");
224 
225         PERMISSION_MESSAGES.put("", 0L, "roles.permission.deny");
226         PERMISSION_MESSAGES.put("", Permission.READ, "roles.permission.readOnly");
227         PERMISSION_MESSAGES.put("", Permission.ALL, "roles.permission.readWrite");
228     }
229 
230     /**
231      * Options for permission tools.
232      */
233     public static class PermissionViewOption extends AbstractSecurityToolPresenter.ViewOption {
234         private DumpType type;
235         private DumpMode dumpMode;
236 
237         public DumpType getType() {
238             return type;
239         }
240 
241         public void setType(DumpType type) {
242             this.type = type;
243         }
244 
245         public DumpMode getDumpMode() {
246             return dumpMode;
247         }
248 
249         public void setDumpMode(DumpMode dumpMode) {
250             this.dumpMode = dumpMode;
251         }
252     }
253 
254     /**
255      * Type is used to query permissions for.
256      */
257     public enum DumpType {
258         USER, GROUP
259     }
260 
261     /**
262      * Mode of querying permissions.
263      */
264     public enum DumpMode {
265         WITH_PERMISSIONS, WITHOUT_PERMISSIONS
266     }
267 
268 }