1 package com.randomnoun.common.security.impl;
2
3
4
5
6
7 import java.io.IOException;
8 import java.util.*;
9
10 import org.apache.log4j.Logger;
11 import org.springframework.dao.DataIntegrityViolationException;
12 import org.springframework.jdbc.core.*;
13
14 import com.randomnoun.common.CamelCaser;
15 import com.randomnoun.common.Struct;
16 import com.randomnoun.common.Text;
17 import com.randomnoun.common.jexl.sql.SqlGenerator;
18 import com.randomnoun.common.security.Permission;
19 import com.randomnoun.common.security.SecurityContext;
20 import com.randomnoun.common.security.SecurityLoader;
21 import com.randomnoun.common.security.User;
22 import com.randomnoun.common.security.impl.ResourceCriteriaImpl;
23 import com.randomnoun.common.security.impl.SpringSecurityLoaderImpl;
24 import com.randomnoun.common.spring.StringRowMapper;
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53 public class SpringSecurityLoaderImpl
54 implements SecurityLoader
55 {
56
57
58 public static final Logger logger = Logger.getLogger(SpringSecurityLoaderImpl.class);
59
60
61 private Map<String, Object> properties = null;
62
63
64 private static final int PERMISSION_USER = 1;
65
66 private static final int PERMISSION_ROLE = 2;
67
68 private static final int PERMISSION_NONE = 3;
69
70
71 public final static String INIT_JDBCTEMPLATE = "jdbcTemplate";
72
73
74
75
76
77 public final static String INIT_DATABASE_VENDOR = "databaseVendor";
78
79
80
81 public final static String INIT_CASE_INSENSITIVE_OBJ = "caseInsensitiveObj";
82
83
84 public final CamelCaser roleCamelCaser = new CamelCaser("roleId,roleName,description");
85
86
87 public final CamelCaser userCamelCaser = new CamelCaser("userId,name");
88
89
90 public final CamelCaser permissionCamelCaser = new CamelCaser("roleName,userId,activityName,resourceName,resourceCriteria");
91
92
93 public final CamelCaser auditCamelCaser = new CamelCaser("userId,auditTime,auditDescription,resourceCriteria,authorised,authoriserId,authoriseTime");
94
95
96
97
98
99
100
101 private String userTable() {
102 return "users";
103 }
104
105
106 private String userRoleTable() {
107 return "userRole";
108 }
109
110
111 private String roleTable() {
112 return "roleTable";
113 }
114
115
116 private String securityTable() {
117 return "securityTable";
118 }
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146 private String getDatabaseVendor() {
147 return (String) properties.get(INIT_DATABASE_VENDOR);
148 }
149
150
151
152
153
154
155 private boolean getCaseInsensitive() {
156
157 return ((Boolean) properties.get(INIT_CASE_INSENSITIVE_OBJ)).booleanValue();
158 }
159
160
161
162
163
164
165
166
167 private String lowerSql(String lhs) {
168 if (getCaseInsensitive()) {
169 String vendor = getDatabaseVendor();
170 if (vendor.equals(SqlGenerator.DATABASE_DB2)) {
171 return "LOWER(" + lhs + ")";
172 } else if (vendor.equals(SqlGenerator.DATABASE_ORACLE)) {
173 return "LOWER(" + lhs + ")";
174 } else if (vendor.equals(SqlGenerator.DATABASE_SQLSERVER)) {
175 return "LOWER(" + lhs + ")";
176 } else if (vendor.equals(SqlGenerator.DATABASE_MYSQL)) {
177 return "LOWER(" + lhs + ")";
178 } else {
179 throw new IllegalStateException("Case-insensitivity security contexts" +
180 " not supported for database type '" + vendor + "'");
181 }
182 } else {
183 return lhs;
184 }
185 }
186
187
188 private String lower(String value) {
189 if (getCaseInsensitive()) {
190 return value.toLowerCase();
191 } else {
192 return value;
193 }
194 }
195
196
197
198
199
200
201
202
203 private Object toSequenceType(long var) {
204 String vendor = getDatabaseVendor();
205 if (vendor.equals(SqlGenerator.DATABASE_JET)) {
206 return new Integer((int) var);
207 } else {
208 return new Long(var);
209 }
210 }
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225 public void initialise(Map<String, Object> properties)
226 {
227 this.properties = properties;
228
229
230 if (properties.get(INIT_JDBCTEMPLATE)==null) { throw new NullPointerException("null INIT_JDBCTEMPLATE"); }
231 if (properties.get(INIT_DATABASE_VENDOR)==null) { throw new NullPointerException("null INIT_DATABASE_VENDOR"); }
232 String vendor = (String) properties.get(INIT_DATABASE_VENDOR);
233 if (!(vendor.equals(SqlGenerator.DATABASE_DB2) ||
234 vendor.equals(SqlGenerator.DATABASE_ORACLE) ||
235 vendor.equals(SqlGenerator.DATABASE_SQLSERVER) ||
236 vendor.equals(SqlGenerator.DATABASE_MYSQL) ||
237 vendor.equals(SqlGenerator.DATABASE_JET))) {
238 throw new IllegalArgumentException("Invalid INIT_DATABASE_VENDOR property '" + vendor + "'");
239 }
240
241
242
243
244
245
246
247
248
249
250 String caseInsensitive = (String) properties.get(SecurityContext.INIT_CASE_INSENSITIVE);
251 if (Text.isBlank(caseInsensitive)) {
252 caseInsensitive = "false";
253 }
254 properties.put(INIT_CASE_INSENSITIVE_OBJ, Boolean.valueOf(caseInsensitive));
255
256
257
258
259
260
261
262
263
264 }
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279 public List<Permission> loadAllRolePermissions()
280 throws IOException
281 {
282 JdbcTemplate jt = (JdbcTemplate)properties.get("jdbcTemplate");
283 String loadAllRolePermissionsSql =
284 "SELECT roleName, activityName, resourceName, resourceCriteria " +
285 "FROM " + roleTable() + ", " + securityTable() + ", permission, resources " +
286 "WHERE " +
287 " (" + securityTable() + ".roleId = " + roleTable() + ".roleId) " +
288 " AND " + "(" + securityTable() + ".permissionId = permission.permissionId) " +
289 " AND " + "(permission.resourceId = resources.resourceId)";
290 List<Object> sqlParams = new ArrayList<Object>(2);
291 List<Map<String, Object>> list = jt.query(loadAllRolePermissionsSql,
292 sqlParams.toArray(),
293 new ColumnMapRowMapper());
294 if (logger.isDebugEnabled()) {
295 logger.debug(Struct.structuredListToString("loadAllRolePermissions", list));
296 }
297 permissionCamelCaser.renameList(list);
298 return convertPermissionList(list, PERMISSION_ROLE);
299 }
300
301
302
303
304
305
306
307
308
309
310
311 public List<Permission> loadUserPermissions(User user)
312 throws IOException
313 {
314 JdbcTemplate jt = (JdbcTemplate) properties.get("jdbcTemplate");
315
316 String sqlPermissions =
317 "SELECT activityName, resourceName, resourceCriteria " +
318 "FROM " + securityTable() + ", permission, resources " +
319 "WHERE " +
320 " " + securityTable() + ".roleId IS NULL " +
321 " AND (" + lowerSql(securityTable() + ".userId") + " = ?) " +
322 " AND (" + securityTable() + ".permissionId = permission.permissionId) " +
323 " AND (permission.resourceId = resources.resourceId) ORDER BY resourceName, activityName";
324 List<Object> sqlParams = new ArrayList<Object>(2);
325 sqlParams.add(lower(user.getUsername()));
326 List<Map<String, Object>> list = jt.query(sqlPermissions, sqlParams.toArray(), new ColumnMapRowMapper());
327
328 if (logger.isDebugEnabled()) {
329 logger.debug(Struct.structuredListToString("loadAllUserPermissions [2]", list));
330 }
331 permissionCamelCaser.renameList(list);
332 return convertPermissionList(list, PERMISSION_USER);
333 }
334
335
336
337
338
339
340
341
342
343 public List<String> loadUserRoles(User user)
344 {
345 JdbcTemplate jt = (JdbcTemplate)properties.get("jdbcTemplate");
346 String sql = "SELECT roleName " +
347 " FROM " + roleTable() + "," + userRoleTable() +
348 " WHERE " +
349 roleTable() + ".roleId = " + userRoleTable() + ".roleId " +
350 " AND " + lowerSql(userRoleTable() + ".userId") + " = ?";
351 logger.debug("loadRolesForUser: " + sql + "; " + user.getUsername());
352 List<Object> sqlParams = new ArrayList<Object>(3);
353 sqlParams.add(lower(user.getUsername()));
354 List<String> list = jt.query(sql, sqlParams.toArray(), new StringRowMapper());
355 return list;
356 }
357
358
359
360
361
362
363
364
365 public List<Permission> loadRolePermissions(String role)
366 {
367 JdbcTemplate jt = (JdbcTemplate)properties.get("jdbcTemplate");
368 long roleId = findRoleIdByName(role);
369 String sql =
370 "SELECT roleName, activityName, resourceName, resourceCriteria " +
371 "FROM " + roleTable() + ", " + securityTable() + ", permission, resources " +
372 "WHERE " +
373 " (" + securityTable() + ".roleId = ?) " +
374 " AND (" + roleTable() + ".roleId = " + securityTable() + ".roleId) " +
375 " AND (" + securityTable() + ".permissionId = permission.permissionId) " +
376 " AND (permission.resourceId = resources.resourceId) " +
377 " ORDER BY resourceName, activityName";
378 List<Object> sqlParams = new ArrayList<Object>(2);
379 sqlParams.add(toSequenceType(roleId));
380 List<Map<String, Object>> list = jt.query(sql, sqlParams.toArray(), new ColumnMapRowMapper());
381 permissionCamelCaser.renameList(list);
382 return convertPermissionList(list, PERMISSION_ROLE);
383 }
384
385
386
387
388
389
390
391
392
393
394
395
396 public List<Permission> loadUserRolePermissions(User user)
397 {
398 JdbcTemplate jt = (JdbcTemplate) properties.get("jdbcTemplate");
399 String sql ="SELECT activityName, resourceName, resourceCriteria " +
400 "FROM " + securityTable() + ", " + roleTable() + ", permission, resources " +
401 "WHERE (" + securityTable() + ".roleId IN (" +
402 "SELECT " + userRoleTable() + ".roleId " +
403 "FROM " + userRoleTable() + ", " + roleTable() +
404 " WHERE " + userRoleTable() + ".roleId = " + roleTable() + ".roleId " +
405 " AND " + lowerSql("userId") + " = ?)) " +
406 " AND (" + securityTable() + ".permissionId = permission.permissionId) " +
407 " AND (permission.resourceId = resources.resourceId)";
408 List<Object> sqlParams = new ArrayList<Object>(2);
409 sqlParams.add(user.getUsername());
410 List<Map<String, Object>> list = jt.query(sql, sqlParams.toArray(), new ColumnMapRowMapper());
411
412
413
414 ArrayList<Map<String, Object>> list2 = new ArrayList<Map<String, Object>>();
415 for (int x = 0; x < list.size(); x++) {
416 Map<String, Object> row = list.get(x);
417 if (!list2.contains(row)) {
418 list2.add(row);
419 }
420 }
421 permissionCamelCaser.renameList(list2);
422 return convertPermissionList(list2, PERMISSION_NONE);
423
424 }
425
426
427
428
429
430
431
432 public List<Permission> loadAllPermissions()
433 {
434 JdbcTemplate jt = (JdbcTemplate)properties.get("jdbcTemplate");
435 String sql =
436 "SELECT activityName, resourceName" +
437 " FROM permission, resources " +
438 " WHERE " +
439 " permission.resourceId = resources.resourceId " +
440 "ORDER BY resourceName, activityName";
441 List<Object> sqlParams = new ArrayList<Object>(2);
442 List<Map<String, Object>> list = jt.query(sql, sqlParams.toArray(), new ColumnMapRowMapper());
443 permissionCamelCaser.renameList(list);
444 return convertPermissionList(list, PERMISSION_NONE);
445 }
446
447
448
449
450
451
452
453
454
455
456
457 private List<Permission> convertPermissionList(List<Map<String, Object>> list, int permissionType)
458 {
459 String resourceType;
460 String expressionString;
461 Permission permission;
462 List<Permission> result = new ArrayList<Permission>(list.size());
463
464 for (Iterator<Map<String, Object>> i = list.iterator(); i.hasNext(); ) {
465 Map<String, Object> map = i.next();
466 resourceType = (String) map.get("resourceName");
467 expressionString = (String) map.get("resourceCriteria");
468 ResourceCriteriaImpl resourceCriteriaImpl = null;
469 if (expressionString != null && !expressionString.equals("")) {
470 try {
471 resourceCriteriaImpl = new ResourceCriteriaImpl(expressionString);
472 } catch (Exception ce) {
473 throw new DataIntegrityViolationException(
474 "Invalid criteria found in SECURITY.RESOURCECRITERIA: '" +
475 expressionString + "'", ce);
476 }
477 }
478
479 if (permissionType == PERMISSION_ROLE) {
480 permission = new Permission((String)map.get("roleName"),
481 (String)map.get("activityName"), resourceType, resourceCriteriaImpl);
482 } else if (permissionType == PERMISSION_USER) {
483 User user = new User();
484 user.setUsername((String) map.get("userId"));
485 permission = new Permission( user,
486 (String)map.get("activityName"), resourceType, resourceCriteriaImpl);
487 } else if (permissionType == PERMISSION_NONE) {
488 permission = new Permission((String)map.get("activityName"), resourceType);
489
490 } else {
491 throw new IllegalArgumentException("Unknown permission type '" + permissionType + "'");
492 }
493 result.add(permission);
494 }
495 return result;
496 }
497
498
499 public User loadUser(long userId) throws IOException {
500 throw new IOException("loadUser() not implemented");
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521 }
522
523
524
525
526
527
528
529
530
531
532
533 public List<User> loadAllUsers()
534 throws IOException
535 {
536 JdbcTemplate jt = (JdbcTemplate)properties.get("jdbcTemplate");
537 String sql =
538 "SELECT " + userTable() + ".userId " +
539 " FROM " + userTable();
540 List<String> list = jt.query(sql, new StringRowMapper());
541 List<User> result = new ArrayList<User>(list.size());
542 for (Iterator<String> i = list.iterator(); i.hasNext(); ) {
543 String username = (String) i.next();
544 User user = new User();
545 user.setUsername(username);
546 result.add(user);
547 }
548 return result;
549 }
550
551
552
553
554
555
556
557 public List<String> loadAllResources() {
558 JdbcTemplate jt = (JdbcTemplate)properties.get("jdbcTemplate");
559 String sql =
560 "SELECT resourceName " +
561 "FROM resources ";
562 List<Object> sqlParams = new ArrayList<Object>(2);
563 List<String> list = jt.query(sql, sqlParams.toArray(), new StringRowMapper());
564 return list;
565 }
566
567
568
569
570
571
572
573
574
575 public List<String> loadAllActivities(String resourceName)
576 {
577 JdbcTemplate jt = (JdbcTemplate)properties.get("jdbcTemplate");
578 String sql =
579 "SELECT activityName " +
580 "FROM permission, resources " +
581 "WHERE " +
582 " resourceName = ? " +
583 " AND permission.resourceId = resources.resourceId ";
584 List<Object> sqlParams = new ArrayList<Object>(3);
585 sqlParams.add(resourceName);
586 List<String> list = jt.query(sql, sqlParams.toArray(), new StringRowMapper());
587 return list;
588 }
589
590
591
592
593
594
595
596
597 public List<String> loadAllRoles()
598 {
599 JdbcTemplate jt = (JdbcTemplate)properties.get("jdbcTemplate");
600 String sql = "SELECT roleName " +
601 " FROM " + roleTable();
602 List<Object> sqlParams = new ArrayList<Object>(2);
603 List<String> list = jt.query(sql, sqlParams.toArray(), new StringRowMapper());
604 return list;
605 }
606
607
608
609
610
611 public List<Map<String, Object>> loadAllRoleDetails()
612 {
613 logger.debug("SpringSecurityLoaderImpl.loadAllRoleDetails(): 1. Entering");
614 JdbcTemplate jt = (JdbcTemplate) properties.get("jdbcTemplate");
615 String sql =
616 "SELECT roleId, roleName, description" +
617 " FROM " + roleTable();
618 List<Object> sqlParams = new ArrayList<Object>(2);
619 List<Map<String,Object>> list = jt.queryForList(sql, sqlParams.toArray());
620 roleCamelCaser.renameList(list);
621 return list;
622 }
623
624
625
626
627 public List<Map<String, Object>> loadAllUserDetails()
628 {
629 JdbcTemplate jt = (JdbcTemplate) properties.get("jdbcTemplate");
630 String sql = "SELECT userId, name " +
631 " FROM " + userTable();
632 List<Object> sqlParams = new ArrayList<Object>(1);
633 List<Map<String,Object>> list = jt.queryForList(sql, sqlParams.toArray());
634 userCamelCaser.renameList(list);
635 return list;
636 }
637
638
639
640
641
642
643
644 private long findRoleIdByName(String role)
645 {
646 try {
647 JdbcTemplate jt = (JdbcTemplate) properties.get("jdbcTemplate");
648 logger.debug("findRoleIdByName('" + role + "') called");
649 String tablename = roleTable();
650 String sql =
651 "SELECT roleId " +
652 "FROM " + tablename +
653 " WHERE roleName = ? ";
654 List<Object> sqlParams = new ArrayList<Object>(3);
655 sqlParams.add(role);
656 long key = jt.queryForObject(sql, sqlParams.toArray(), Long.class);
657 logger.debug("findRoleIdByName('" + role + "') returning " + key);
658 return key;
659 } catch (org.springframework.dao.IncorrectResultSizeDataAccessException irsdae) {
660 throw (IllegalArgumentException) new IllegalArgumentException(
661 "Could not find role '" + role + "' in " + roleTable()).initCause(irsdae);
662 }
663 }
664
665
666
667
668
669
670 public void resetSecurityContext() {
671
672 }
673
674 public void saveUserRolesAndPermissions(User user, List<String> roles, List<Permission> userPermissions) throws IOException
675 {
676 throw new UnsupportedOperationException("not implemented");
677 }
678
679 public void saveRolePermissions(String role, List<Permission> rolePermissions)
680 throws IOException
681 {
682 throw new UnsupportedOperationException("not implemented");
683 }
684
685
686
687 }
688