[ all classes ]
[ com.acciente.oacc ]
Coverage Summary for Class: ResourcePermissions (com.acciente.oacc)
Class | Method, % | Line, % |
---|---|---|
ResourcePermissions | 100% (8/ 8) | 93.4% (57/ 61) |
ResourcePermissions$ResourcePermissionImpl | 100% (13/ 13) | 86.2% (50/ 58) |
total | 100% (21/ 21) | 89.9% (107/ 119) |
1 /*
2 * Copyright 2009-2018, Acciente LLC
3 *
4 * Acciente LLC licenses this file to you under the
5 * Apache License, Version 2.0 (the "License"); you
6 * may not use this file except in compliance with the
7 * License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in
12 * writing, software distributed under the License is
13 * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
14 * OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing
16 * permissions and limitations under the License.
17 */
18 package com.acciente.oacc;
19
20 import java.io.Serializable;
21 import java.util.ArrayList;
22 import java.util.Collections;
23 import java.util.HashMap;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.concurrent.ConcurrentHashMap;
27 import java.util.concurrent.ConcurrentMap;
28
29 public class ResourcePermissions {
30 // constants for the important system permissions with pre-defined semantics
31 private static final SysPermission SYSPERMISSION_INHERIT = new SysPermission(-101, "*INHERIT");
32 public static final String INHERIT = SYSPERMISSION_INHERIT.getPermissionName();
33 private static final SysPermission SYSPERMISSION_IMPERSONATE = new SysPermission(-102, "*IMPERSONATE");
34 public static final String IMPERSONATE = SYSPERMISSION_IMPERSONATE.getPermissionName();
35 private static final SysPermission SYSPERMISSION_RESET_CREDENTIALS = new SysPermission(-103, "*RESET-CREDENTIALS");
36 public static final String RESET_CREDENTIALS = SYSPERMISSION_RESET_CREDENTIALS.getPermissionName();
37 private static final SysPermission SYSPERMISSION_DELETE = new SysPermission(-104, "*DELETE");
38 public static final String DELETE = SYSPERMISSION_DELETE.getPermissionName();
39 private static final SysPermission SYSPERMISSION_QUERY = new SysPermission(-105, "*QUERY");
40 public static final String QUERY = SYSPERMISSION_QUERY.getPermissionName();
41
42 private static final Map<String, SysPermission> sysPermissionsByName;
43 private static final Map<Long, String> sysPermissionNamesById;
44 private static final List<String> sysPermissionNames;
45 private static final ConcurrentMap<String, ResourcePermission> ungrantablePermissionByName;
46 private static final ConcurrentMap<String, ResourcePermission> grantablePermissionByName;
47
48 static {
49 sysPermissionsByName = new HashMap<>();
50 sysPermissionsByName.put(INHERIT, SYSPERMISSION_INHERIT);
51 sysPermissionsByName.put(IMPERSONATE, SYSPERMISSION_IMPERSONATE);
52 sysPermissionsByName.put(RESET_CREDENTIALS, SYSPERMISSION_RESET_CREDENTIALS);
53 sysPermissionsByName.put(DELETE, SYSPERMISSION_DELETE);
54 sysPermissionsByName.put(QUERY, SYSPERMISSION_QUERY);
55
56 sysPermissionNamesById = new HashMap<>(sysPermissionsByName.size());
57 for (SysPermission sysPermission : sysPermissionsByName.values()) {
58 sysPermissionNamesById.put(sysPermission.getSystemPermissionId(), sysPermission.getPermissionName());
59 }
60
61 sysPermissionNames = Collections.unmodifiableList(new ArrayList<>(sysPermissionNamesById.values()));
62
63 ungrantablePermissionByName = new ConcurrentHashMap<>();
64 grantablePermissionByName = new ConcurrentHashMap<>();
65 }
66
67 public static List<String> getSysPermissionNames() {
68 return sysPermissionNames;
69 }
70
71 public static String getSysPermissionName(long systemPermissionId) {
72 final String sysPermissionName = sysPermissionNamesById.get(systemPermissionId);
73
74 if (sysPermissionName == null) {
75 throw new IllegalArgumentException("Invalid system permission ID: " + systemPermissionId);
76 }
77
78 return sysPermissionName;
79 }
80
81 /**
82 * Creates a new resource permission of the specified name without
83 * the option to grant the permission to another resource
84 *
85 * @param permissionName the name of the permission
86 * @return a resource permission
87 */
88 public static ResourcePermission getInstance(String permissionName) {
89 permissionName = getCanonicalPermissionName(permissionName);
90
91 ResourcePermission resourcePermission = ungrantablePermissionByName.get(permissionName);
92
93 if (resourcePermission == null) {
94 resourcePermission = new ResourcePermissionImpl(permissionName, false);
95 final ResourcePermission cachedInstance = ungrantablePermissionByName.putIfAbsent(permissionName, resourcePermission);
96 if (cachedInstance != null) {
97 resourcePermission = cachedInstance;
98 }
99 }
100
101 return resourcePermission;
102 }
103
104 /**
105 * Creates a new resource permission of the specified name, but
106 * with the option to grant the permission to another resource
107 *
108 * @param permissionName the name of the permission
109 * @return a resource permission
110 */
111 public static ResourcePermission getInstanceWithGrantOption(String permissionName) {
112 permissionName = getCanonicalPermissionName(permissionName);
113
114 ResourcePermission resourcePermission = grantablePermissionByName.get(permissionName);
115
116 if (resourcePermission == null) {
117 resourcePermission = new ResourcePermissionImpl(permissionName, true);
118 final ResourcePermission cachedInstance = grantablePermissionByName.putIfAbsent(permissionName, resourcePermission);
119 if (cachedInstance != null) {
120 resourcePermission = cachedInstance;
121 }
122 }
123
124 return resourcePermission;
125 }
126
127 public static ResourcePermission getInstance(ResourcePermission resourcePermission) {
128 if (resourcePermission instanceof ResourcePermissions.ResourcePermissionImpl) {
129 return resourcePermission;
130 }
131
132 final ResourcePermission verifiedPermission;
133
134 if (resourcePermission.isWithGrantOption()) {
135 verifiedPermission = getInstanceWithGrantOption(resourcePermission.getPermissionName());
136 }
137 else {
138 verifiedPermission = getInstance(resourcePermission.getPermissionName());
139 }
140
141 // validate system permission name and id matched
142 if (resourcePermission.isSystemPermission() &&
143 verifiedPermission.getSystemPermissionId() != resourcePermission.getSystemPermissionId()){
144 throw new IllegalArgumentException("Invalid system permission id for resource permission: " + resourcePermission);
145 }
146
147 return verifiedPermission;
148 }
149
150 private static String getCanonicalPermissionName(String permissionName) {
151 if (permissionName == null) {
152 throw new IllegalArgumentException("A permission name is required");
153 }
154
155 permissionName = permissionName.trim();
156
157 if (permissionName.isEmpty()) {
158 throw new IllegalArgumentException("A permission name is required");
159 }
160 return permissionName;
161 }
162
163 static class ResourcePermissionImpl implements ResourcePermission, Serializable {
164 private static final long serialVersionUID = 1L;
165
166 // permission data
167 private final long systemPermissionId;
168 private final String permissionName;
169 private final boolean withGrantOption;
170
171 private ResourcePermissionImpl(String permissionName,
172 boolean withGrantOption) {
173 assertPermissionNameSpecified(permissionName);
174
175 permissionName = permissionName.trim();
176
177 if (permissionName.startsWith("*")) {
178 SysPermission sysPermission = getSysPermission(permissionName);
179
180 this.systemPermissionId = sysPermission.getSystemPermissionId();
181 this.permissionName = sysPermission.getPermissionName();
182 }
183 else {
184 this.systemPermissionId = 0;
185 this.permissionName = permissionName.intern();
186 }
187
188 this.withGrantOption = withGrantOption;
189 }
190
191 @Override
192 public boolean isSystemPermission() {
193 return systemPermissionId != 0;
194 }
195
196 @Override
197 public String getPermissionName() {
198 return permissionName;
199 }
200
201 @Override
202 public long getSystemPermissionId() {
203 if (!isSystemPermission()) {
204 throw new IllegalArgumentException("No system permission ID may be retrieved for user permission: " + permissionName + ", please check your code");
205 }
206
207 return systemPermissionId;
208 }
209
210 @Override
211 public boolean isWithGrantOption() {
212 return withGrantOption;
213 }
214
215 @Override
216 public boolean isGrantableFrom(ResourcePermission other) {
217 if (other == null) {
218 return false;
219 }
220
221 if (!other.isWithGrantOption()) {
222 return false;
223 }
224
225 return this.equalsIgnoreGrantOption(other);
226 }
227
228 @Override
229 public boolean equals(Object other) {
230 if (this == other) {
231 return true;
232 }
233 if (other == null || getClass() != other.getClass()) {
234 return false;
235 }
236
237 ResourcePermissionImpl otherResourcePermission = (ResourcePermissionImpl) other;
238
239 if (!permissionName.equals(otherResourcePermission.permissionName)) {
240 return false;
241 }
242 if (withGrantOption != otherResourcePermission.withGrantOption) {
243 return false;
244 }
245
246 return true;
247 }
248
249 @Override
250 public boolean equalsIgnoreGrantOption(Object other) {
251 if (this == other) {
252 return true;
253 }
254 if (other == null || getClass() != other.getClass()) {
255 return false;
256 }
257
258 ResourcePermissionImpl otherResourcePermission = (ResourcePermissionImpl) other;
259
260 if (!permissionName.equals(otherResourcePermission.permissionName)) {
261 return false;
262 }
263
264 return true;
265 }
266
267 @Override
268 public int hashCode() {
269 int result = permissionName.hashCode();
270 result = 31 * result + (withGrantOption ? 1 : 0);
271 return result;
272 }
273
274 @Override
275 public String toString() {
276 return withGrantOption ? permissionName + " /G" : permissionName;
277 }
278
279 // private helper methods
280
281 private void assertPermissionNameSpecified(String permissionName) {
282 if (permissionName == null || permissionName.trim().isEmpty()) {
283 throw new IllegalArgumentException("A permission name is required");
284 }
285 }
286
287 // private static helper method to convert a sys permission name to a sys permission object
288
289 private static SysPermission getSysPermission(String permissionName) {
290 if (permissionName == null) {
291 throw new IllegalArgumentException("A system permission name is required");
292 }
293
294 final String trimmedPermissionName = permissionName.trim();
295
296 if (trimmedPermissionName.isEmpty()) {
297 throw new IllegalArgumentException("A system permission name is required");
298 }
299
300 final SysPermission sysPermission = sysPermissionsByName.get(trimmedPermissionName);
301
302 if (sysPermission == null) {
303 throw new IllegalArgumentException("Invalid system permission name: " + trimmedPermissionName);
304 }
305
306 return sysPermission;
307 }
308 }
309 }