1
2
3
4
5
6
7
8
9
10 package com.sri.emo.controller;
11
12 import com.jcorporate.expresso.core.controller.*;
13 import com.jcorporate.expresso.core.db.DBException;
14 import com.jcorporate.expresso.core.dbobj.RowSecuredDBObject;
15 import com.jcorporate.expresso.core.misc.StringUtil;
16 import com.jcorporate.expresso.core.registry.RequestRegistry;
17 import com.jcorporate.expresso.services.dbobj.RowGroupPerms;
18 import com.jcorporate.expresso.services.dbobj.RowPermissions;
19 import com.jcorporate.expresso.services.dbobj.Setup;
20 import com.jcorporate.expresso.services.dbobj.UserGroup;
21 import com.sri.common.controller.AbstractDBController;
22 import com.sri.common.taglib.InputTag;
23 import com.sri.common.util.PermGroup;
24 import com.sri.emo.dbobj.IViewable;
25
26 import java.util.*;
27
28 /***
29 * Handle manipulation of permissions.
30 *
31 * @author larry hamel
32 */
33 public class PermissionController extends AbstractDBController {
34 /***
35 *
36 */
37 private static final long serialVersionUID = 1L;
38 public static final String PROMPT_EDIT_PERMS = "promptEditPerms";
39 public static final String DO_EDIT_PERMS = "doEditPerms";
40 public static final String PROMPT_EDIT_GROUP = "promptEditGroup";
41 public static final String DO_EDIT_GROUP = "doEditGroup";
42
43 /***
44 * Name of incoming parameter which has values for key fields of RowSecuredDBObject, delimited by bar (|).
45 */
46 public static final String KEY_FIELD_VALUES = "key";
47 public static final String OBJ_TYPE = "obj";
48 public static final String ASSOC_CHK = "assoc";
49 public static final String READ_CHK = "read";
50 public static final String WRITE_CHK = "write";
51 public static final String ADMIN_CHK = "admin";
52 public static final String VIEW_TRANS = "viewTrans";
53 public static final String DISABLED = "disabled";
54
55 /***
56 * Setup item in expresso schema for whether others (in unix sense--all other users)
57 * can read always. DEFAULT TRUE.
58 */
59 public static final String OTHERS_READ_ALWAYS = "OthersRead";
60
61 public PermissionController() {
62 State state = new State(PROMPT_EDIT_PERMS, "Prompt to edit permissions");
63 state.addRequiredParameter(KEY_FIELD_VALUES);
64 state.addRequiredParameter(OBJ_TYPE);
65 addState(state);
66
67 state = new State(DO_EDIT_PERMS, "submit editing of permissions");
68 state.addRequiredParameter(KEY_FIELD_VALUES);
69 state.addRequiredParameter(OBJ_TYPE);
70 addState(state);
71
72 state = new State(PROMPT_EDIT_GROUP, "Prompt to edit group");
73 state.addRequiredParameter(UserGroup.GROUP_NAME_FIELD);
74 addState(state);
75
76 state = new State(DO_EDIT_GROUP, "submit editing of group");
77 state.addRequiredParameter(UserGroup.GROUP_NAME_FIELD);
78 addState(state);
79
80 setInitialState(PROMPT_EDIT_PERMS);
81 }
82
83 /***
84 * Returns the title of this controller
85 *
86 * @return java.lang.String
87 */
88 public String getTitle() {
89 return ("Permission Controller");
90 }
91
92 /***
93 * Prompt for edits.
94 *
95 * @param request The ControllerRequest object.
96 * @param response The ControllerResponse object.
97 * @throws com.jcorporate.expresso.core.controller.ControllerException
98 * upon error.
99 */
100 protected void runPromptEditPermsState(final ExpressoRequest request,
101 final ExpressoResponse response) throws ControllerException, DBException {
102 try {
103 String allkeys = request.getParameter(KEY_FIELD_VALUES);
104 String objtype = request.getParameter(OBJ_TYPE);
105
106 RowSecuredDBObject obj = getObj(objtype, allkeys);
107
108
109 if (!obj.canRequesterAdministrate()) {
110 throw new ControllerException(
111 "User: " + RequestRegistry.getUser().getLoginName() + " does not have administration privileges for object of type: "
112 + obj.getClass().getName() + " with key: " + allkeys);
113 }
114
115
116 if (obj instanceof IViewable) {
117 Transition trans = ((IViewable) obj).getViewTrans();
118 trans.setName(VIEW_TRANS);
119 response.add(trans);
120 }
121
122
123 Map associatedMap = getAssociatedGroupPermsHashWithAllusers(obj);
124
125
126 List groupsOfUsersMembership = RequestRegistry.getUser().getGroupsList();
127
128
129 List groupsForListing;
130 if (request.getUserInfo().isAdmin()) {
131 List allgrps = UserGroup.getAllGroups();
132 groupsForListing = new ArrayList(allgrps.size());
133 for (Iterator iterator = allgrps.iterator(); iterator.hasNext();) {
134 UserGroup group = (UserGroup) iterator.next();
135 groupsForListing.add(group.getGroupName());
136 }
137 } else {
138 groupsForListing = new ArrayList(groupsOfUsersMembership);
139 }
140
141
142 groupsForListing.remove(UserGroup.NOT_REG_USERS_GROUP);
143 groupsForListing.remove(UserGroup.UNKNOWN_USERS_GROUP);
144
145
146 TreeMap alphaMap = new TreeMap();
147 for (Iterator iterator = groupsForListing.iterator(); iterator.hasNext();) {
148 String groupname = (String) iterator.next();
149
150 PermGroup grp = new PermGroup();
151 grp.setGroupName(groupname);
152 if (grp.canRequesterRead()) {
153 alphaMap.put(groupname, groupname);
154 }
155 }
156
157
158 alphaMap.put(UserGroup.ALL_USERS_GROUP, UserGroup.ALL_USERS_GROUP);
159
160
161 Block groupBlock = new Block(ROW_BLOCK);
162 response.add(groupBlock);
163 for (Iterator iterator = alphaMap.values().iterator(); iterator.hasNext();) {
164 String groupname = (String) iterator.next();
165 RowGroupPerms perms = (RowGroupPerms) associatedMap.get(groupname);
166 Block groupRow = null;
167 if (groupname.equals(UserGroup.ALL_USERS_GROUP)) {
168
169
170
171 if (perms == null) {
172 perms = new RowGroupPerms();
173 }
174
175 insertPrivForOTHER(obj, perms);
176
177 boolean othersReadAlways = othersReadAlways();
178 if (othersReadAlways) {
179
180 groupRow = getGroupRow(perms, groupname);
181 Input read = (Input) groupRow.getInputs().get(0);
182 read.setAttribute(DISABLED, DISABLED);
183 }
184 } else {
185 groupRow = getGroupRow(perms, groupname);
186 }
187 groupBlock.add(groupRow);
188 }
189
190
191 Transition submit = new Transition(DO_EDIT_PERMS, this);
192 submit.setLabel("Update");
193 submit.addParam(KEY_FIELD_VALUES, allkeys);
194 submit.addParam(OBJ_TYPE, obj.getClass().getName());
195 response.add(submit);
196
197
198 response.add(new Output(OBJ_TYPE, obj.getMetaData().getDescription()));
199 response.add(new Output(KEY_FIELD_VALUES, allkeys));
200 } catch (Exception e) {
201 throw new ControllerException(e);
202 }
203
204 }
205
206 /***
207 * Setup item in expresso schema for whether others (in unix sense--all
208 * other users) can read always. DEFAULT TRUE.
209 */
210 public static boolean othersReadAlways() {
211 boolean othersReadAlways = true;
212 String othersReadSetting = Setup.getValueUnrequired(OTHERS_READ_ALWAYS);
213 if (othersReadSetting != null && !StringUtil.toBoolean(othersReadSetting)) {
214 othersReadAlways = false;
215 }
216 return othersReadAlways;
217 }
218
219 /***
220 * including 'fake' Everybody reads
221 *
222 * @param obj The RowSecuredDBObject that is the source of the associated map.
223 * @return sorted map of RowGroupPerms, with group name as key
224 * @throws DBException upon RowSecured access error.
225 */
226 private Map getAssociatedGroupPermsHashWithAllusers(RowSecuredDBObject obj) throws DBException {
227
228 Map associatedMap = getAssociatedGroupPermsHash(obj);
229
230 if (associatedMap.get(UserGroup.ALL_USERS_GROUP) == null) {
231 RowGroupPerms perms = new RowGroupPerms(obj, UserGroup.ALL_USERS_GROUP);
232 insertPrivForOTHER(obj, perms);
233 associatedMap.put(UserGroup.ALL_USERS_GROUP, perms);
234 }
235 return associatedMap;
236 }
237
238 /***
239 * not including 'fake' Everybody reads
240 *
241 * @param obj The RowSecuredDBObject that is the source of the associated map.
242 * @return sorted map of RowGroupPerms, with group name as key
243 * @throws DBException upon RowSecured access error.
244 */
245 private Map getAssociatedGroupPermsHash(RowSecuredDBObject obj) throws DBException {
246 List objGroups = obj.getGroups();
247 TreeMap associatedMap = new TreeMap();
248
249 for (Iterator iterator = objGroups.iterator(); iterator.hasNext();) {
250 RowGroupPerms perms = (RowGroupPerms) iterator.next();
251 PermGroup grp = new PermGroup();
252 grp.setGroupName(perms.group());
253 if (grp.canRequesterRead()) {
254 associatedMap.put(perms.group(), perms);
255 }
256 }
257
258 return associatedMap;
259 }
260
261 /***
262 * Insert privileges for "OTHER" from the object into this group,
263 * ignoring whatever perms were in the group to begin with
264 *
265 * @param obj The RowSecuredDBobject to get perms from
266 * @param grouppermsForOthers the group permissions to insert perms into
267 * @throws DBException upon RowSecured access error.
268 */
269 private void insertPrivForOTHER(RowSecuredDBObject obj, RowGroupPerms grouppermsForOthers) throws DBException {
270 int rowperms = obj.getPermissions().permissions();
271
272 boolean isRead = (rowperms & RowPermissions.OTHERS_READ_MASK) > 0 || othersReadAlways();
273 boolean isWrite = (rowperms & RowPermissions.OTHERS_WRITE_MASK) > 0;
274 boolean isAdmin = (rowperms & RowPermissions.OTHERS_PERMISSION_MASK) > 0;
275
276 int grppermsInt = 0;
277 if (isRead) {
278 grppermsInt |= RowPermissions.GROUP_READ_MASK;
279 }
280 if (isWrite) {
281 grppermsInt |= RowPermissions.GROUP_WRITE_MASK;
282 }
283
284 if (isAdmin) {
285 grppermsInt |= RowPermissions.GROUP_PERMISSION_MASK;
286 }
287
288 grouppermsForOthers.permissions(grppermsInt);
289 }
290
291 private RowSecuredDBObject getObj(String objtype, String allkeys) throws InstantiationException,
292 IllegalAccessException, ClassNotFoundException, ControllerException, DBException {
293 RowSecuredDBObject obj = (RowSecuredDBObject) Class.forName(objtype).newInstance();
294 int numkeys = obj.getMetaData().getAllKeysMap().size();
295 String[] values = allkeys.split("//" + DELIMIT);
296 if (values.length != numkeys) {
297 throw new ControllerException(
298 "Got values: " + allkeys + " which does not correspond to number of keys expected: " + numkeys);
299 }
300 int i = 0;
301 for (Iterator iterator = obj.getKeyFieldListIterator(); iterator.hasNext();) {
302 String key = (String) iterator.next();
303 obj.setField(key, values[i]);
304 i++;
305 }
306
307 obj.retrieve();
308 return obj;
309 }
310
311 /***
312 * Get transition for editing permissions for this group.
313 *
314 * @param perms pass in permissions for already-associated groups, null for not-associated groups
315 * @param groupname The target group name.
316 * @return the Group Row with checkboxes and edit transitions.
317 * @throws DBException upon database error.
318 */
319 private Block getGroupRow(RowGroupPerms perms, String groupname) throws DBException {
320 PermGroup grp = new PermGroup();
321 grp.setGroupName(groupname);
322 grp.retrieve();
323
324 Block row = new Block(groupname);
325
326
327 row.add(getCheckbox(READ_CHK, perms != null && perms.canGroupRead()));
328 row.add(getCheckbox(WRITE_CHK, perms != null && perms.canGroupWrite()));
329 row.add(getCheckbox(ADMIN_CHK, perms != null && perms.canGroupAdministrate()));
330
331
332
333 Transition trans = new Transition(PROMPT_EDIT_GROUP, this);
334 trans.setLabel(groupname);
335 trans.addParam(KEY_FIELD_VALUES, grp.getGroupName());
336 trans.addParam(OBJ_TYPE, grp.getClass().getName());
337 trans.addParam(UserGroup.GROUP_NAME_FIELD, groupname);
338 row.add(trans);
339
340
341 if (grp.canRequesterAdministrate()) {
342 trans.setAttribute(ROW, "Y");
343 }
344
345 return row;
346 }
347
348 private Input getCheckbox(String name, boolean checked) {
349 Input input = new Input(name);
350 input.setType(InputTag.TYPE_CHECKBOX);
351 input.setDefaultValue(checked ? "Y" : "N");
352 if (checked) {
353 input.setAttribute(Input.SELECTED, "Y");
354 }
355 return input;
356 }
357
358
359 /***
360 * Do for editing single pick item.
361 *
362 * @param request The ControllerRequest object.
363 * @param response The ControllerResponse object.
364 * @throws com.jcorporate.expresso.core.controller.ControllerException
365 * upon error.
366 */
367 protected void runDoEditPermsState(final ExpressoRequest request, final ExpressoResponse response) throws
368 ControllerException {
369 try {
370 String allkeys = request.getParameter(KEY_FIELD_VALUES);
371 String objtype = request.getParameter(OBJ_TYPE);
372
373 RowSecuredDBObject obj = getObj(objtype, allkeys);
374
375
376 Map oldAssociatedMap = getAssociatedGroupPermsHash(obj);
377
378
379 Map foundPermsMap = new HashMap(oldAssociatedMap.size());
380
381
382 Iterator enumer = request.getAllParameters().keySet().iterator();
383 while (enumer.hasNext()) {
384 String grpname = null;
385 String pkey = (String) enumer.next();
386 if (pkey.startsWith(READ_CHK)) {
387 grpname = pkey.substring(READ_CHK.length());
388 Privs privs = putPrivs(foundPermsMap, grpname);
389 privs.isRead = true;
390 }
391 if (pkey.startsWith(WRITE_CHK)) {
392 grpname = pkey.substring(WRITE_CHK.length());
393 Privs privs = putPrivs(foundPermsMap, grpname);
394 privs.isWrite = true;
395 }
396 if (pkey.startsWith(ADMIN_CHK)) {
397 grpname = pkey.substring(ADMIN_CHK.length());
398 Privs privs = putPrivs(foundPermsMap, grpname);
399 privs.isAdmin = true;
400 }
401 }
402
403
404 putPrivs(foundPermsMap, UserGroup.ALL_USERS_GROUP);
405
406
407 for (Iterator iterator = foundPermsMap.keySet().iterator(); iterator.hasNext();) {
408 String grpname = (String) iterator.next();
409 Privs privs = (Privs) foundPermsMap.get(grpname);
410
411
412
413 if (grpname.equals(UserGroup.ALL_USERS_GROUP)) {
414 RowPermissions rowperms = obj.getPermissions();
415 boolean othersReadAlways = othersReadAlways();
416 if (!othersReadAlways) {
417 othersReadAlways = privs.isRead;
418 }
419
420 setRowPermsForOTHER(rowperms, othersReadAlways, privs.isWrite, privs.isAdmin);
421
422 continue;
423 }
424
425
426 RowGroupPerms perms = (RowGroupPerms) oldAssociatedMap.remove(grpname);
427 boolean isNew = false;
428 if (perms == null) {
429 isNew = true;
430 perms = new RowGroupPerms(obj.getJDBCMetaData().getTargetTable(), allkeys, grpname);
431 }
432
433 int permInt = perms.permissions();
434
435
436 setGroupPerms(privs.isRead, permInt, privs.isWrite, privs.isAdmin, perms, isNew);
437 }
438
439
440
441 for (Iterator iterator = oldAssociatedMap.values().iterator(); iterator.hasNext();) {
442 RowGroupPerms perms = (RowGroupPerms) iterator.next();
443 if (perms.find()) {
444 perms.delete(true);
445 }
446 }
447
448
449 String viewUrl = "/" + getServlet().getServletContext().getServletContextName();
450 if (obj instanceof IViewable) {
451 viewUrl = ((IViewable) obj).getViewTrans().getFullUrl();
452 }
453
454 redirectRequest(request, response, viewUrl);
455 } catch (Exception e) {
456 throw new ControllerException(e);
457 }
458 }
459
460 private Privs putPrivs(Map foundPermsMap, String groupname) {
461 Privs result = (Privs) foundPermsMap.get(groupname);
462 if (result == null) {
463 result = new Privs();
464 foundPermsMap.put(groupname, result);
465 }
466 return result;
467 }
468
469 private void setGroupPerms(boolean read,
470 int permissions,
471 boolean write,
472 boolean admin,
473 RowGroupPerms perm,
474 boolean aNew) throws DBException {
475 if (read) {
476 permissions |= RowPermissions.GROUP_READ_MASK;
477 } else {
478 permissions &= ~RowPermissions.GROUP_READ_MASK;
479 }
480
481 if (write) {
482 permissions |= RowPermissions.GROUP_WRITE_MASK;
483 } else {
484 permissions &= ~RowPermissions.GROUP_WRITE_MASK;
485 }
486
487 if (admin) {
488 permissions |= RowPermissions.GROUP_PERMISSION_MASK;
489 } else {
490 permissions &= ~RowPermissions.GROUP_PERMISSION_MASK;
491 }
492
493 perm.permissions(permissions);
494
495 if (aNew) {
496 perm.add();
497 } else {
498 perm.update(true);
499 }
500 }
501
502 /***
503 * set perms for OTHER octet
504 */
505 private void setRowPermsForOTHER(
506 RowPermissions rowperms, boolean read, boolean write, boolean admin) throws DBException {
507 int permissions;
508
509 permissions = rowperms.permissions();
510 if (read) {
511 permissions |= RowPermissions.OTHERS_READ_MASK;
512 } else {
513 permissions &= ~RowPermissions.OTHERS_READ_MASK;
514 }
515
516 if (write) {
517 permissions |= RowPermissions.OTHERS_WRITE_MASK;
518 } else {
519 permissions &= ~RowPermissions.OTHERS_WRITE_MASK;
520 }
521
522 if (admin) {
523 permissions |= RowPermissions.OTHERS_PERMISSION_MASK;
524 } else {
525 permissions &= ~RowPermissions.OTHERS_PERMISSION_MASK;
526 }
527
528 rowperms.permissions(permissions);
529 rowperms.addOrUpdate();
530 }
531
532 /***
533 * prompt editing of group; just reuses prompt edit for any RowSec object,
534 * using a PermGroup, a wrapper on UserGroup
535 *
536 * @param request The ControllerRequest object.
537 * @param response The ControllerResponse object.
538 * @throws com.jcorporate.expresso.core.controller.ControllerException
539 * upon error.
540 */
541 protected void runPromptEditGroupState(ControllerRequest request,
542 ControllerResponse response) throws ControllerException {
543 try {
544 String grpname = request.getParameter(UserGroup.GROUP_NAME_FIELD);
545 PermGroup grp = new PermGroup();
546 grp.setGroupName(grpname);
547 grp.retrieve();
548
549 request.setParameter(KEY_FIELD_VALUES, grp.getKey());
550 request.setParameter(OBJ_TYPE, grp.getClass().getName());
551 runPromptEditPermsState(request, response);
552
553 } catch (Exception e) {
554 throw new ControllerException(e);
555 }
556 }
557 }