1 64 65 package com.jcorporate.expresso.core.dbobj; 66 67 import com.jcorporate.expresso.core.cache.CacheException; 68 import com.jcorporate.expresso.core.cache.CacheManager; 69 import com.jcorporate.expresso.core.cache.CacheSystem; 70 import com.jcorporate.expresso.core.controller.ControllerRequest; 71 import com.jcorporate.expresso.core.dataobjects.Securable; 72 import com.jcorporate.expresso.core.db.DBConnection; 73 import com.jcorporate.expresso.core.db.DBException; 74 import com.jcorporate.expresso.core.i18n.Messages; 75 import com.jcorporate.expresso.core.misc.StringUtil; 76 import com.jcorporate.expresso.core.security.User; 77 import com.jcorporate.expresso.kernel.util.ClassLocator; 78 import com.jcorporate.expresso.kernel.util.FastStringBuffer; 79 import com.jcorporate.expresso.services.dbobj.DBObjSecurity; 80 import com.jcorporate.expresso.services.dbobj.DefaultUserInfo; 81 import com.jcorporate.expresso.services.dbobj.GroupMembers; 82 import com.jcorporate.expresso.services.dbobj.UserGroup; 83 import org.apache.log4j.Logger; 84 85 import java.util.ArrayList ; 86 import java.util.Enumeration ; 87 import java.util.Iterator ; 88 import java.util.Vector ; 89 90 91 98 public abstract class SecuredDBObject 99 extends DBObject implements Securable { 100 101 106 public static final int SYSTEM_ACCOUNT = -1; 107 108 113 public static final String SYSTEM_ACCOUNT_NAME = "SYSTEM"; 114 115 118 protected static final String CACHE_NAME = SecuredDBObject.class.getName() 119 + ".securityCache"; 120 121 124 protected static final long CACHE_TTY = 60 * 1000 * 30; 125 126 130 public static final String ADD = "A"; 131 132 135 public static final String DELETE = "D"; 136 137 140 public static final String SEARCH = "S"; 141 142 145 public static final String UPDATE = "U"; 146 147 150 public static final String [] ALL_FUNCTIONS = {ADD, DELETE, SEARCH, UPDATE}; 151 152 private static Logger log = Logger.getLogger(SecuredDBObject.class); 153 154 158 159 160 161 162 private int uid = SYSTEM_ACCOUNT; 163 164 165 168 public SecuredDBObject() 169 throws DBException { 170 super(); 171 172 } 173 174 180 public SecuredDBObject(DBConnection newConnection) 181 throws DBException { 182 this(newConnection, newConnection.getDataContext()); 183 } 184 185 203 public SecuredDBObject(DBConnection newConnection, String setupTablesContext) 204 throws DBException { 205 super(newConnection, setupTablesContext); 206 } 207 208 209 215 public SecuredDBObject(ControllerRequest request) 216 throws DBException { 217 this(request.getUid()); 218 setDataContext(request.getDataContext()); 219 } 220 221 222 228 public void setRequestingUid(int newUid) { 229 uid = newUid; 230 } 231 232 240 public int getRequestingUid() { 241 return uid; 242 } 243 244 245 255 public SecuredDBObject(int newUid) 256 throws DBException { 257 super(); 258 setRequestingUid(newUid); 259 } 260 261 262 273 public SecuredDBObject(DBConnection theConnection, int theUser) 274 throws DBException { 275 super(theConnection); 276 setRequestingUid(theUser); 277 } 278 279 280 288 public SecuredDBObject(RequestContext request) 289 throws DBException { 290 setRequestingUid(request.getUid()); 295 setDataContext(request.getDBName()); 296 setLocale(request.getLocale()); 297 } 298 299 300 307 public SecuredDBObject(String dbKey, int theUser) 308 throws DBException { 309 super(dbKey); 310 setRequestingUid(theUser); 311 } 312 313 319 public void add() 320 throws DBException { 321 isAllowed(ADD); 322 super.add(); 323 } 324 325 326 333 public boolean checkAllowed(String requestedFunction) 334 throws DBException { 335 try { 336 isAllowed(requestedFunction); 337 } catch (SecurityException de) { 338 log.debug(de); 339 340 return false; 341 } 342 343 return true; 344 } 345 346 347 352 public void delete() 353 throws DBException { 354 isAllowed(DELETE); 355 super.delete(); 356 } 357 358 359 366 public boolean find() 367 throws DBException { 368 isAllowed(SEARCH); 369 370 return super.find(); 371 } 372 373 374 382 protected synchronized void createSecurityCache() throws CacheException { 383 384 synchronized (SecuredDBObject.class) { 387 CacheSystem cs = CacheManager.getCacheSystem(getDataContext()); 388 if (cs == null) { 389 return; 391 } 392 393 if (!cs.existsCache(CACHE_NAME)) { 394 if (log.isDebugEnabled()) { 395 log.debug("Cache did not exist - creating"); 396 } 397 398 cs.createCache(CACHE_NAME, false, 1000); 399 cs.addListener(CACHE_NAME, GroupMembers.class.getName()); 400 cs.addListener(CACHE_NAME, DBObjSecurity.class.getName()); 401 cs.addListener(CACHE_NAME, DefaultUserInfo.class.getName()); 402 cs.addListener(CACHE_NAME, UserGroup.class.getName()); 403 } 404 } 405 } 406 407 419 public void isAllowed(String requestedFunction) 420 throws SecurityException , DBException { 421 if (log.isDebugEnabled()) { 422 log.debug("Checking permission for function '" + 423 requestedFunction + "' for user " + uid); 424 } 425 if (uid == 0) { 426 throw new DBException("User not specified. Must have a " + 427 "valid user id to access database object '" + 428 getMetaData().getDescription() + "'"); 429 } 430 431 if (uid == -1 || User.getAdminId(getDataContext()) == uid) { 432 if (log.isDebugEnabled()) { 433 log.debug("User was SYSTEM - permission granted"); 434 } 435 436 return; 437 } 438 try { 439 CacheSystem cs = CacheManager.getCacheSystem(getDataContext()); 440 if (cs != null) { 441 if (!cs.existsCache(CACHE_NAME)) { 442 createSecurityCache(); 443 } 444 } 445 446 ValidValue sec = null; 447 if (cs != null) { 448 sec = (ValidValue) cs.getItem(CACHE_NAME, 449 uid + "|" + 450 getClass().getName()); 451 } 452 453 if (sec == null) { 454 User u = new User(); 455 456 u.setDataContext(StringUtil.notNull(getDataContext())); 457 u.setUid(uid); 458 u.retrieve(); 459 460 Vector groups = u.getGroups(); 461 462 if (log.isDebugEnabled()) { 463 log.debug("User '" + u.getLoginName() + 464 "' in db/context '" + getDataContext() + 465 "' who requested function '" + 466 requestedFunction + "' on database object '" + 467 getClass().getName() + "' is in " + 468 groups.size() + " groups."); 469 } 470 471 DBObjSecurity dbSec = new DBObjSecurity(); 472 dbSec.setDataContext(StringUtil.notNull(getDataContext())); 473 474 if (log.isDebugEnabled()) { 475 log.debug("User '" + u.getLoginName() + 476 "' in db/context '" + this.getMappedDataContext() + 477 "' requested function '" + requestedFunction + 478 "' on database object '" + getClass().getName() + 479 "' which is in original db '" + 480 this.getDataContext() + "'"); 481 } 482 483 DBObjSecurity oneSec = null; 484 String oneGroupName = null; 485 486 FastStringBuffer currentSecurity = new FastStringBuffer(6); 487 for (Enumeration e = groups.elements(); e.hasMoreElements();) { 488 oneGroupName = (String ) e.nextElement(); 489 490 if (log.isDebugEnabled()) { 491 log.debug("User '" + u.getLoginName() + 492 "' in db/context '" + getDataContext() + 493 "' who requested function '" + 494 requestedFunction + 495 "' on database object '" + 496 getClass().getName() + "' is in group '" + 497 oneGroupName + "'"); 498 } 499 500 dbSec.clear(); 501 dbSec.setField("GroupName", oneGroupName); 502 dbSec.setField("DBObjectName", getClass().getName()); 503 504 String newSec = null; 505 506 for (Iterator esec = dbSec.searchAndRetrieveList().iterator(); 507 esec.hasNext();) { 508 oneSec = (DBObjSecurity) esec.next(); 509 newSec = oneSec.getField("MethodCode"); 510 511 512 if (currentSecurity.toString().indexOf(newSec) < 0) { 513 currentSecurity.append(newSec); 514 if ( currentSecurity.length() >= 4 ) { 515 break; 517 } 518 } 519 } 520 } 521 522 523 sec = new ValidValue(uid + "|" + getClass().getName(), 524 currentSecurity.toString()); 525 526 if (cs != null) { 527 cs.addItem(CACHE_NAME, sec, CACHE_TTY); 528 } 529 530 if (log.isDebugEnabled()) { 531 log.debug("User '" + u.getLoginName() + 532 "' in db/context '" + getDataContext() + 533 "' who requested function '" + 534 requestedFunction + "' on database object '" + 535 getClass().getName() + 536 "'. Security string created from database is '" + 537 sec.getDescription() + "'"); 538 } 539 } else { 540 if (log.isDebugEnabled()) { 541 log.debug("User '" + uid + "' in db/context '" + 542 getDataContext() + "' who requested function '" + 543 requestedFunction + "' on database object '" + 544 getClass().getName() + 545 "'. Security string from cache is '" + 546 sec.getDescription() + "'"); 547 } 548 } 549 550 if (sec.getDescription().indexOf(requestedFunction) != -1) { 551 return; 552 } 553 if (log.isDebugEnabled()) { 554 log.debug("User '" + uid + "' in db/context '" + getDataContext() + 555 "' is denied permission to perform function '" + 556 requestedFunction + "' on database object '" + 557 getClass().getName() + "'. Security string is '" + 558 sec.getDescription() + "', which did not contain '" + 559 requestedFunction + "'"); 560 } 561 562 String permString = null; 563 564 if (requestedFunction.equalsIgnoreCase(ADD)) { 565 permString = ("Add"); 566 } else if (requestedFunction.equalsIgnoreCase(SEARCH)) { 567 permString = ("Search"); 568 } else if (requestedFunction.equalsIgnoreCase(UPDATE)) { 569 permString = ("Update"); 570 } else if (requestedFunction.equalsIgnoreCase(DELETE)) { 571 permString = ("Delete"); 572 } else { 573 permString = ("perform operation '" + 574 requestedFunction + "'"); 575 } 576 577 String [] args = new String [4]; 578 args[0] = "'" + User.getLoginFromId(getRequestingUid(), getDataContext()) + " (" + getRequestingUid() + ")'"; 579 args[1] = "'" + permString + "'"; 580 args[2] = "'" + getMetaData().getDescription() + "'"; 581 args[3] = "'" + getDataContext() + "'"; 582 583 throw new SecurityException (Messages.getString("knownUserSecException", args)); 584 } catch (CacheException ce) { 585 throw new DBException(ce); 586 } 587 } 588 589 590 595 public int getSystemUid() { 596 return SecuredDBObject.SYSTEM_ACCOUNT; 597 } 598 599 606 public void retrieve() 607 throws DBException { 608 isAllowed(SEARCH); 609 super.retrieve(); 610 } 611 612 613 622 public synchronized void search() 623 throws DBException { 624 isAllowed(SEARCH); 625 super.search(); 626 } 627 628 629 639 public synchronized ArrayList searchAndRetrieveList() 640 throws DBException { 641 isAllowed(SEARCH); 642 return super.searchAndRetrieveList(); 643 } 644 645 646 659 public synchronized ArrayList searchAndRetrieveList(String sortKeys) 660 throws DBException { 661 isAllowed(SEARCH); 662 return super.searchAndRetrieveList(sortKeys); 663 } 664 665 670 public void update() 671 throws DBException { 672 isAllowed(UPDATE); 673 super.update(); 674 } 675 676 677 687 protected String getString(String stringCode, Object [] args) 688 throws DBException { 689 return Messages.getString(getJDBCMetaData().getSchema(), getLocale(), stringCode, args); 690 } 691 692 693 700 public static SecuredDBObject instantiate(String className) 701 throws DBException { 702 StringUtil.assertNotBlank(className, 703 "DBObject class name may not be blank or null here"); 704 705 try { 706 Class c = ClassLocator.loadClass(className); 707 708 return (SecuredDBObject) c.newInstance(); 709 } catch (ClassNotFoundException cn) { 710 throw new DBException("DBObject object '" + className + 711 "' not found", cn); 712 } catch (InstantiationException ie) { 713 throw new DBException("DBObject object '" + className + 714 "' cannot be instantiated", ie); 715 } catch (IllegalAccessException iae) { 716 throw new DBException("llegal access loading " + 717 "DBObject object '" + className + 718 "' doesn't have a public default constructor", 719 iae); 720 } 721 } 722 723 730 protected String getString(String stringCode) 731 throws DBException { 732 Object [] args = {}; 733 734 return getString(stringCode, args); 735 } 736 737 738 746 protected String getString(String stringCode, String arg1) 747 throws DBException { 748 Object [] args = {arg1}; 749 750 return getString(stringCode, args); 751 } 752 753 762 protected String getString(String stringCode, String arg1, String arg2) 763 throws DBException { 764 Object [] args = {arg1, arg2}; 765 766 return getString(stringCode, args); 767 } 768 769 779 protected String getString(String stringCode, String arg1, String arg2, 780 String arg3) 781 throws DBException { 782 Object [] args = {arg1, arg2, arg3}; 783 784 return getString(stringCode, args); 785 } 786 787 798 protected String getString(String stringCode, String arg1, String arg2, 799 String arg3, String arg4) 800 throws DBException { 801 Object [] args = {arg1, arg2, arg3, arg4}; 802 803 return getString(stringCode, args); 804 } 805 806 813 public void copyAttributes(DBObject returnObj) throws DBException { 814 super.copyAttributes(returnObj); 815 if (returnObj instanceof SecuredDBObject) { 816 ((SecuredDBObject) returnObj).setRequestingUid(getRequestingUid()); 817 } 818 } 819 820 828 public synchronized int count() throws com.jcorporate.expresso.core.db.DBException { 829 isAllowed(SEARCH); 830 return super.count(); 831 } 832 833 836 public synchronized void deleteAll() throws com.jcorporate.expresso.core.db.DBException { 837 isAllowed(DELETE); 838 super.deleteAll(); 839 } 840 841 848 public boolean canRequesterRead() throws DBException { 849 boolean result = false; 850 851 int userId = this.getRequestingUid(); 852 853 if (userId == SYSTEM_ACCOUNT) { 854 return true; 855 } 856 857 User user = new User(); 858 user.setUid(userId); 859 user.setDataContext(this.getDataContext()); 860 861 if (!user.find()) { 862 throw new DBException("cannot find requesting user with ID: " + getRequestingUid()); 863 } 864 865 if (user.isAdmin()) { 866 return true; 867 } 868 869 try { 870 this.isAllowed(SEARCH); 871 result = true; 872 } catch (Exception e) { 873 result = false; 874 } 875 876 return result; 877 } 878 879 886 public boolean canRequesterAdd() throws DBException { 887 boolean result = false; 888 889 int userId = this.getRequestingUid(); 890 891 if (userId == SYSTEM_ACCOUNT) { 892 return true; 893 } 894 895 User user = new User(); 896 user.setUid(userId); 897 user.setDataContext(this.getDataContext()); 898 899 if (!user.find()) { 900 throw new DBException("cannot find requesting user with ID: " + getRequestingUid()); 901 } 902 903 if (user.getLoginName().equals(User.ADMIN_USER)) { 904 return true; 905 } 906 907 try { 908 this.isAllowed(ADD); 909 result = true; 910 } catch (Exception e) { 911 result = false; 912 } 913 914 return result; 915 } 916 917 924 public boolean canRequesterDelete() throws DBException { 925 boolean result = false; 926 927 int userId = this.getRequestingUid(); 928 929 if (userId == SYSTEM_ACCOUNT) { 930 return true; 931 } 932 933 User user = new User(); 934 user.setUid(userId); 935 user.setDataContext(this.getDataContext()); 936 937 if (!user.find()) { 938 throw new DBException("cannot find requesting user with ID: " + getRequestingUid()); 939 } 940 941 if (user.getLoginName().equals(User.ADMIN_USER)) { 942 return true; 943 } 944 945 try { 946 this.isAllowed(DELETE); 947 result = true; 948 } catch (Exception e) { 949 result = false; 950 } 951 952 return result; 953 } 954 955 962 public boolean canRequesterUpdate() throws DBException { 963 boolean result = false; 964 965 int userId = this.getRequestingUid(); 966 967 if (userId == SYSTEM_ACCOUNT) { 968 return true; 969 } 970 971 User user = new User(); 972 user.setUid(userId); 973 user.setDataContext(this.getDataContext()); 974 975 if (!user.find()) { 976 throw new DBException("cannot find requesting user with ID: " + getRequestingUid()); 977 } 978 979 if (user.getLoginName().equals(User.ADMIN_USER)) { 980 return true; 981 } 982 983 try { 984 this.isAllowed(UPDATE); 985 result = true; 986 } catch (Exception e) { 987 result = false; 988 } 989 990 return result; 991 } 992 993 } 994 | Popular Tags |