| /* Copyright (c) 2001-2010, The HSQL Development Group |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are met: |
| * |
| * Redistributions of source code must retain the above copyright notice, this |
| * list of conditions and the following disclaimer. |
| * |
| * Redistributions in binary form must reproduce the above copyright notice, |
| * this list of conditions and the following disclaimer in the documentation |
| * and/or other materials provided with the distribution. |
| * |
| * Neither the name of the HSQL Development Group nor the names of its |
| * contributors may be used to endorse or promote products derived from this |
| * software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG, |
| * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| |
| package org.hsqldb.rights; |
| |
| import org.hsqldb.HsqlNameManager.HsqlName; |
| import org.hsqldb.NumberSequence; |
| import org.hsqldb.Routine; |
| import org.hsqldb.SchemaObject; |
| import org.hsqldb.Session; |
| import org.hsqldb.Table; |
| import org.hsqldb.Tokens; |
| import org.hsqldb.error.Error; |
| import org.hsqldb.error.ErrorCode; |
| import org.hsqldb.lib.HashMap; |
| import org.hsqldb.lib.HashSet; |
| import org.hsqldb.lib.HsqlArrayList; |
| import org.hsqldb.lib.Iterator; |
| import org.hsqldb.lib.MultiValueHashMap; |
| import org.hsqldb.lib.OrderedHashSet; |
| import org.hsqldb.lib.Set; |
| import org.hsqldb.lib.WrapperIterator; |
| import org.hsqldb.types.Type; |
| |
| /** |
| * A Grantee Object holds the name, access and administrative rights for a |
| * particular grantee.<p> |
| * It supplies the methods used to grant, revoke, test |
| * and check a grantee's access rights to other database objects. |
| * It also holds a reference to the common PUBLIC User Object, |
| * which represent the special user refered to in |
| * GRANT ... TO PUBLIC statements.<p> |
| * The check(), isAccessible() and getGrantedClassNames() methods check the |
| * rights granted to the PUBLIC User Object, in addition to individually |
| * granted rights, in order to decide which rights exist for the user. |
| * |
| * Method names ending in Direct indicate methods which do not recurse |
| * to look through Roles which "this" object is a member of. |
| * |
| * We use the word "Admin" (e.g., in private variable "admin" and method |
| * "isAdmin()) to mean this Grantee has admin priv by any means. |
| * We use the word "adminDirect" (e.g., in private variable "adminDirect" |
| * and method "isAdminDirect()) to mean this Grantee has admin priv |
| * directly. |
| * |
| * @author Campbell Boucher-Burnett (boucherb@users dot sourceforge.net) |
| * @author Fred Toussi (fredt@users dot sourceforge.net) |
| * @author Blaine Simpson (blaine dot simpson at admc dot com) |
| * |
| * @version 1.9.0 |
| * @since 1.8.0 |
| */ |
| public class Grantee implements SchemaObject { |
| |
| boolean isRole; |
| |
| /** |
| * true if this grantee has database administrator priv directly |
| * (ie., not by membership in any role) |
| */ |
| private boolean isAdminDirect = false; |
| |
| /** true if this grantee has database administrator priv by any means. */ |
| private boolean isAdmin = false; |
| |
| /** true if this user can create schemas with its own authorisation */ |
| boolean isSchemaCreator = false; |
| |
| /** true if this grantee is PUBLIC. */ |
| boolean isPublic = false; |
| |
| /** true if this grantee is _SYSTEM. */ |
| boolean isSystem = false; |
| |
| /** Grantee name. */ |
| protected HsqlName granteeName; |
| |
| /** map with database object identifier keys and access privileges values */ |
| private MultiValueHashMap directRightsMap; |
| |
| /** contains righs granted direct, or via roles, expept those of PUBLIC */ |
| private HashMap fullRightsMap; |
| |
| /** These are the DIRECT roles. Each of these may contain nested roles */ |
| OrderedHashSet roles; |
| |
| /** map with database object identifier keys and access privileges values */ |
| private MultiValueHashMap grantedRightsMap; |
| |
| /** Needed only to give access to the roles for this database */ |
| protected GranteeManager granteeManager; |
| |
| /** */ |
| protected Right ownerRights; |
| |
| /** |
| * Constructor. |
| */ |
| Grantee(HsqlName name, GranteeManager man) { |
| |
| fullRightsMap = new HashMap(); |
| directRightsMap = new MultiValueHashMap(); |
| grantedRightsMap = new MultiValueHashMap(); |
| granteeName = name; |
| granteeManager = man; |
| roles = new OrderedHashSet(); |
| ownerRights = new Right(); |
| ownerRights.isFull = true; |
| ownerRights.grantor = GranteeManager.systemAuthorisation; |
| ownerRights.grantee = this; |
| } |
| |
| public int getType() { |
| return SchemaObject.GRANTEE; |
| } |
| |
| public HsqlName getName() { |
| return granteeName; |
| } |
| |
| public HsqlName getSchemaName() { |
| return null; |
| } |
| |
| public HsqlName getCatalogName() { |
| return null; |
| } |
| |
| public Grantee getOwner() { |
| return null; |
| } |
| |
| public OrderedHashSet getReferences() { |
| return new OrderedHashSet(); |
| } |
| |
| public OrderedHashSet getComponents() { |
| return null; |
| } |
| |
| public void compile(Session session, SchemaObject parentObject) {} |
| |
| public String getSQL() { |
| |
| StringBuffer sb = new StringBuffer(); |
| |
| sb.append(Tokens.T_CREATE).append(' ').append(Tokens.T_ROLE); |
| sb.append(' ').append(granteeName.statementName); |
| |
| return sb.toString(); |
| } |
| |
| public long getChangeTimestamp() { |
| return 0; |
| } |
| |
| public String getNameString() { |
| return granteeName.name; |
| } |
| |
| public String getStatementName() { |
| return granteeName.statementName; |
| } |
| |
| public boolean isRole() { |
| return isRole; |
| } |
| |
| public boolean isSystem() { |
| return isSystem; |
| } |
| |
| /** |
| * Retrieves the map object that represents the rights that have been |
| * granted on database objects. <p> |
| * |
| * The map has keys and values with the following interpretation: <P> |
| * |
| * <UL> |
| * <LI> The keys are generally (but not limited to) objects having |
| * an attribute or value equal to the name of an actual database |
| * object. |
| * |
| * <LI> Specifically, the keys act as database object identifiers. |
| * |
| * <LI> The values are Right objects. |
| * </UL> |
| */ |
| public MultiValueHashMap getRights() { |
| |
| // necessary to create the script |
| return directRightsMap; |
| } |
| |
| /** |
| * Grant a role |
| */ |
| public void grant(Grantee role) { |
| roles.add(role); |
| } |
| |
| /** |
| * Revoke a direct role only |
| */ |
| public void revoke(Grantee role) { |
| |
| if (!hasRoleDirect(role)) { |
| throw Error.error(ErrorCode.X_0P503, role.getNameString()); |
| } |
| |
| roles.remove(role); |
| } |
| |
| /** |
| * Gets direct roles, not roles nested within them. |
| */ |
| public OrderedHashSet getDirectRoles() { |
| return roles; |
| } |
| |
| String getAllRolesAsString() { |
| return roleMapToString(getAllRoles()); |
| } |
| |
| public String getDirectRolesAsString() { |
| return roleMapToString(roles); |
| } |
| |
| public String roleMapToString(OrderedHashSet roles) { |
| |
| StringBuffer sb = new StringBuffer(); |
| |
| for (int i = 0; i < roles.size(); i++) { |
| if (sb.length() > 0) { |
| sb.append(','); |
| } |
| |
| Grantee role = (Grantee) roles.get(i); |
| |
| sb.append(role.getStatementName()); |
| } |
| |
| return sb.toString(); |
| } |
| |
| /** |
| * Gets direct and indirect roles. |
| */ |
| public OrderedHashSet getAllRoles() { |
| |
| OrderedHashSet set = getGranteeAndAllRoles(); |
| |
| // Since we added "Grantee" in addition to Roles, need to remove self. |
| set.remove(this); |
| |
| return set; |
| } |
| |
| public OrderedHashSet getGranteeAndAllRoles() { |
| |
| OrderedHashSet set = new OrderedHashSet(); |
| |
| addGranteeAndRoles(set); |
| |
| return set; |
| } |
| |
| public OrderedHashSet getGranteeAndAllRolesWithPublic() { |
| |
| OrderedHashSet set = new OrderedHashSet(); |
| |
| addGranteeAndRoles(set); |
| set.add(granteeManager.publicRole); |
| |
| return set; |
| } |
| |
| /** |
| * Adds to given Set this.sName plus all roles and nested roles. |
| * |
| * @return Given role with new elements added. |
| */ |
| private OrderedHashSet addGranteeAndRoles(OrderedHashSet set) { |
| |
| Grantee candidateRole; |
| |
| set.add(this); |
| |
| for (int i = 0; i < roles.size(); i++) { |
| candidateRole = (Grantee) roles.get(i); |
| |
| if (!set.contains(candidateRole)) { |
| candidateRole.addGranteeAndRoles(set); |
| } |
| } |
| |
| return set; |
| } |
| |
| /** |
| * returns a map with grantee name keys and sets of granted roles as value |
| */ |
| public void addAllRoles(HashMap map) { |
| |
| for (int i = 0; i < roles.size(); i++) { |
| Grantee role = (Grantee) roles.get(i); |
| |
| map.put(role.granteeName.name, role.roles); |
| } |
| } |
| |
| public boolean hasRoleDirect(Grantee role) { |
| return roles.contains(role); |
| } |
| |
| public boolean hasRole(Grantee role) { |
| return getAllRoles().contains(role); |
| } |
| |
| /** |
| * Grants the specified rights on the specified database object. <p> |
| * |
| * Keys stored in rightsMap for database tables are their HsqlName |
| * attribute. This allows rights to persist when a table is renamed. <p> |
| */ |
| void grant(HsqlName name, Right right, Grantee grantor, |
| boolean withGrant) { |
| |
| final Right grantableRights = grantor.getAllGrantableRights(name); |
| Right existingRight = null; |
| |
| if (right == Right.fullRights) { |
| if (grantableRights.isEmpty()) { |
| return; // has no rights |
| } |
| |
| right = grantableRights; |
| } else { |
| if (!grantableRights.contains(right)) { |
| throw Error.error(ErrorCode.X_0L000); |
| } |
| } |
| |
| Iterator it = directRightsMap.get(name); |
| |
| while (it.hasNext()) { |
| Right existing = (Right) it.next(); |
| |
| if (existing.grantor == grantor) { |
| existingRight = existing; |
| |
| existingRight.add(right); |
| |
| break; |
| } |
| } |
| |
| if (existingRight == null) { |
| existingRight = right.duplicate(); |
| existingRight.grantor = grantor; |
| existingRight.grantee = this; |
| |
| directRightsMap.put(name, existingRight); |
| } |
| |
| if (withGrant) { |
| if (existingRight.grantableRights == null) { |
| existingRight.grantableRights = right.duplicate(); |
| } else { |
| existingRight.grantableRights.add(right); |
| } |
| } |
| |
| if (!grantor.isSystem) { |
| |
| // based on assumption that there is no need to access |
| grantor.grantedRightsMap.put(name, existingRight); |
| } |
| |
| updateAllRights(); |
| } |
| |
| /** |
| * Revokes the specified rights on the specified database object. <p> |
| * |
| * If, after removing the specified rights, no rights remain on the |
| * database object, then the key/value pair for that object is removed |
| * from the rights map |
| */ |
| void revoke(SchemaObject object, Right right, Grantee grantor, |
| boolean grantOption) { |
| |
| HsqlName name = object.getName(); |
| |
| if (object instanceof Routine) { |
| name = ((Routine) object).getSpecificName(); |
| } |
| |
| Iterator it = directRightsMap.get(name); |
| Right existing = null; |
| |
| while (it.hasNext()) { |
| existing = (Right) it.next(); |
| |
| if (existing.grantor == grantor) { |
| break; |
| } |
| } |
| |
| if (existing == null) { |
| return; |
| } |
| |
| if (existing.grantableRights != null) { |
| existing.grantableRights.remove(object, right); |
| } |
| |
| if (grantOption) { |
| return; |
| } |
| |
| if (right.isFull) { |
| directRightsMap.remove(name, existing); |
| grantor.grantedRightsMap.remove(name, existing); |
| updateAllRights(); |
| |
| return; |
| } |
| |
| existing.remove(object, right); |
| |
| if (existing.isEmpty()) { |
| directRightsMap.remove(name, existing); |
| grantor.grantedRightsMap.remove(name, existing); |
| } |
| |
| updateAllRights(); |
| |
| return; |
| } |
| |
| /** |
| * Revokes all rights on the specified database object.<p> |
| * |
| * This method removes any existing mapping from the rights map |
| */ |
| void revokeDbObject(HsqlName name) { |
| |
| directRightsMap.remove(name); |
| grantedRightsMap.remove(name); |
| fullRightsMap.remove(name); |
| } |
| |
| /** |
| * Revokes all rights from this Grantee object. The map is cleared and |
| * the database administrator role attribute is set false. |
| */ |
| void clearPrivileges() { |
| |
| roles.clear(); |
| directRightsMap.clear(); |
| grantedRightsMap.clear(); |
| fullRightsMap.clear(); |
| |
| isAdmin = false; |
| } |
| |
| public OrderedHashSet getColumnsForAllPrivileges(Table table) { |
| |
| if (isFullyAccessibleByRole(table.getName())) { |
| return table.getColumnNameSet(); |
| } |
| |
| Right right = (Right) fullRightsMap.get(table.getName()); |
| |
| return right == null ? Right.emptySet |
| : right.getColumnsForAllRights(table); |
| } |
| |
| public OrderedHashSet getAllDirectPrivileges(SchemaObject object) { |
| |
| if (object.getOwner() == this) { |
| OrderedHashSet set = new OrderedHashSet(); |
| |
| set.add(ownerRights); |
| |
| return set; |
| } |
| |
| Iterator rights = directRightsMap.get(object.getName()); |
| |
| if (rights.hasNext()) { |
| OrderedHashSet set = new OrderedHashSet(); |
| |
| while (rights.hasNext()) { |
| set.add(rights.next()); |
| } |
| |
| return set; |
| } |
| |
| return Right.emptySet; |
| } |
| |
| public OrderedHashSet getAllGrantedPrivileges(SchemaObject object) { |
| |
| Iterator rights = grantedRightsMap.get(object.getName()); |
| |
| if (rights.hasNext()) { |
| OrderedHashSet set = new OrderedHashSet(); |
| |
| while (rights.hasNext()) { |
| set.add(rights.next()); |
| } |
| |
| return set; |
| } |
| |
| return Right.emptySet; |
| } |
| |
| /** |
| * Checks if a right represented by the methods |
| * have been granted on the specified database object. <p> |
| * |
| * This is done by checking that a mapping exists in the rights map |
| * from the dbobject argument. Otherwise, it throws. |
| */ |
| public void checkSelect(Table table, boolean[] checkList) { |
| |
| if (isFullyAccessibleByRole(table.getName())) { |
| return; |
| } |
| |
| Right right = (Right) fullRightsMap.get(table.getName()); |
| |
| if (right != null && right.canSelect(table, checkList)) { |
| return; |
| } |
| |
| throw Error.error(ErrorCode.X_42501, table.getName().name); |
| } |
| |
| public void checkInsert(Table table, boolean[] checkList) { |
| |
| if (isFullyAccessibleByRole(table.getName())) { |
| return; |
| } |
| |
| Right right = (Right) fullRightsMap.get(table.getName()); |
| |
| if (right != null && right.canInsert(table, checkList)) { |
| return; |
| } |
| |
| throw Error.error(ErrorCode.X_42501, table.getName().name); |
| } |
| |
| public void checkUpdate(Table table, boolean[] checkList) { |
| |
| if (isFullyAccessibleByRole(table.getName())) { |
| return; |
| } |
| |
| Right right = (Right) fullRightsMap.get(table.getName()); |
| |
| if (right != null && right.canUpdate(table, checkList)) { |
| return; |
| } |
| |
| throw Error.error(ErrorCode.X_42501, table.getName().name); |
| } |
| |
| public void checkReferences(Table table, boolean[] checkList) { |
| |
| if (isFullyAccessibleByRole(table.getName())) { |
| return; |
| } |
| |
| Right right = (Right) fullRightsMap.get(table.getName()); |
| |
| if (right != null && right.canReference(table, checkList)) { |
| return; |
| } |
| |
| throw Error.error(ErrorCode.X_42501, table.getName().name); |
| } |
| |
| public void checkTrigger(Table table, boolean[] checkList) { |
| |
| if (isFullyAccessibleByRole(table.getName())) { |
| return; |
| } |
| |
| Right right = (Right) fullRightsMap.get(table.getName()); |
| |
| if (right != null && right.canReference(table, checkList)) { |
| return; |
| } |
| |
| throw Error.error(ErrorCode.X_42501, table.getName().name); |
| } |
| |
| public void checkDelete(Table table) { |
| |
| if (isFullyAccessibleByRole(table.getName())) { |
| return; |
| } |
| |
| Right right = (Right) fullRightsMap.get(table.getName()); |
| |
| if (right != null && right.canDelete()) { |
| return; |
| } |
| |
| throw Error.error(ErrorCode.X_42501, table.getName().name); |
| } |
| |
| public void checkAccess(SchemaObject object) { |
| |
| if (isFullyAccessibleByRole(object.getName())) { |
| return; |
| } |
| |
| HsqlName name = object.getName(); |
| |
| if (object instanceof Routine) { |
| name = ((Routine) object).getSpecificName(); |
| } |
| |
| Right right = (Right) fullRightsMap.get(name); |
| |
| if (right != null && !right.isEmpty()) { |
| return; |
| } |
| |
| throw Error.error(ErrorCode.X_42501, object.getName().name); |
| } |
| |
| /** |
| * Checks if this object can modify schema objects or grant access rights |
| * to them. |
| */ |
| public void checkSchemaUpdateOrGrantRights(String schemaName) { |
| |
| if (!hasSchemaUpdateOrGrantRights(schemaName)) { |
| throw Error.error(ErrorCode.X_42501, schemaName); |
| } |
| } |
| |
| /** |
| * Checks if this object can modify schema objects or grant access rights |
| * to them. |
| */ |
| public boolean hasSchemaUpdateOrGrantRights(String schemaName) { |
| |
| // If a DBA |
| if (isAdmin()) { |
| return true; |
| } |
| |
| Grantee schemaOwner = |
| granteeManager.database.schemaManager.toSchemaOwner(schemaName); |
| |
| // If owner of Schema |
| if (schemaOwner == this) { |
| return true; |
| } |
| |
| // If a member of Schema authorization role |
| if (hasRole(schemaOwner)) { |
| return true; |
| } |
| |
| return false; |
| } |
| |
| public boolean isGrantable(SchemaObject object, Right right) { |
| |
| if (isFullyAccessibleByRole(object.getName())) { |
| return true; |
| } |
| |
| Right grantableRights = getAllGrantableRights(object.getName()); |
| |
| return grantableRights.contains(right); |
| } |
| |
| public boolean isGrantable(Grantee role) { |
| return isAdmin; |
| } |
| |
| public boolean isFullyAccessibleByRole(HsqlName name) { |
| |
| if (isAdmin) { |
| return true; |
| } |
| |
| if (name.schema == null) { |
| return false; |
| } |
| |
| Grantee owner = name.schema.owner; |
| |
| if (owner == this) { |
| return true; |
| } |
| |
| if (hasRole(owner)) { |
| return true; |
| } |
| |
| return false; |
| } |
| |
| /** |
| * Checks whether this Grantee has administrative privs either directly |
| * or indirectly. Otherwise it throws. |
| */ |
| public void checkAdmin() { |
| |
| if (!isAdmin()) { |
| throw Error.error(ErrorCode.X_42507); |
| } |
| } |
| |
| /** |
| * Returns true if this Grantee has administrative privs either directly |
| * or indirectly. |
| */ |
| public boolean isAdmin() { |
| return isAdmin; |
| } |
| |
| /** |
| * Returns true if this Grantee can create schemas with own authorization. |
| */ |
| public boolean isSchemaCreator() { |
| return isAdmin || hasRole(granteeManager.schemaRole); |
| } |
| |
| /** |
| * Returns true if this Grantee can change to a different user. |
| */ |
| public boolean canChangeAuthorisation() { |
| return isAdmin || hasRole(granteeManager.changeAuthRole); |
| } |
| |
| /** |
| * Returns true if this grantee object is for the PUBLIC role. |
| */ |
| public boolean isPublic() { |
| return isPublic; |
| } |
| |
| /** |
| * Violates naming convention (for backward compatibility). |
| * Should be "setAdminDirect(boolean"). |
| */ |
| void setAdminDirect() { |
| isAdmin = isAdminDirect = true; |
| } |
| |
| /** |
| * Recursive method used with ROLE Grantee objects to set the fullRightsMap |
| * and admin flag for all the roles. |
| * |
| * If a new ROLE is granted to a ROLE Grantee object, the ROLE should first |
| * be added to the Set of ROLE Grantee objects (roles) for the grantee. |
| * The grantee will be the parameter. |
| * |
| * If the direct permissions granted to an existing ROLE Grentee is |
| * modified no extra initial action is necessary. |
| * The existing Grantee will be the parameter. |
| * |
| * If an existing ROLE is REVOKEed from a ROLE, it should first be removed |
| * from the set of ROLE Grantee objects in the containing ROLE. |
| * The containing ROLE will be the parameter. |
| * |
| * If an existing ROLE is DROPped, all its privileges should be cleared |
| * first. The ROLE will be the parameter. After calling this method on |
| * all other roles, the DROPped role should be removed from all grantees. |
| * |
| * After the initial modification, this method should be called iteratively |
| * on all the ROLE Grantee objects contained in RoleManager. |
| * |
| * The updateAllRights() method is then called iteratively on all the |
| * USER Grantee objects contained in UserManager. |
| * @param role a modified, revoked or dropped role. |
| * @return true if this Grantee has possibly changed as a result |
| */ |
| boolean updateNestedRoles(Grantee role) { |
| |
| boolean hasNested = false; |
| |
| if (role != this) { |
| for (int i = 0; i < roles.size(); i++) { |
| Grantee currentRole = (Grantee) roles.get(i); |
| |
| hasNested |= currentRole.updateNestedRoles(role); |
| } |
| } |
| |
| if (hasNested) { |
| updateAllRights(); |
| } |
| |
| return hasNested || role == this; |
| } |
| |
| /** |
| * Method used with all Grantee objects to set the full set of rights |
| * according to those inherited form ROLE Grantee objects and those |
| * granted to the object itself. |
| */ |
| |
| /** |
| * @todo -- see if this is correct and the currentRole.fullRightsMap |
| * is always updated prior to being added to this.fullRightsMap |
| */ |
| void updateAllRights() { |
| |
| fullRightsMap.clear(); |
| |
| isAdmin = isAdminDirect; |
| |
| for (int i = 0; i < roles.size(); i++) { |
| Grantee currentRole = (Grantee) roles.get(i); |
| |
| addToFullRights(currentRole.fullRightsMap); |
| |
| isAdmin |= currentRole.isAdmin(); |
| } |
| |
| addToFullRights(directRightsMap); |
| |
| if (!isRole && !isPublic && !isSystem) { |
| addToFullRights(granteeManager.publicRole.fullRightsMap); |
| } |
| } |
| |
| /** |
| * Full or partial rights are added to existing |
| */ |
| void addToFullRights(HashMap map) { |
| |
| Iterator it = map.keySet().iterator(); |
| |
| while (it.hasNext()) { |
| Object key = it.next(); |
| Right add = (Right) map.get(key); |
| Right existing = (Right) fullRightsMap.get(key); |
| |
| if (existing == null) { |
| existing = add.duplicate(); |
| |
| fullRightsMap.put(key, existing); |
| } else { |
| existing.add(add); |
| } |
| |
| if (add.grantableRights == null) { |
| continue; |
| } |
| |
| if (existing.grantableRights == null) { |
| existing.grantableRights = add.grantableRights.duplicate(); |
| } else { |
| existing.grantableRights.add(add.grantableRights); |
| } |
| } |
| } |
| |
| /** |
| * Full or partial rights are added to existing |
| */ |
| void addToFullRights(MultiValueHashMap map) { |
| |
| Iterator it = map.keySet().iterator(); |
| |
| while (it.hasNext()) { |
| Object key = it.next(); |
| Iterator values = map.get(key); |
| Right existing = (Right) fullRightsMap.get(key); |
| |
| while (values.hasNext()) { |
| Right add = (Right) values.next(); |
| |
| if (existing == null) { |
| existing = add.duplicate(); |
| |
| fullRightsMap.put(key, existing); |
| } else { |
| existing.add(add); |
| } |
| |
| if (add.grantableRights == null) { |
| continue; |
| } |
| |
| if (existing.grantableRights == null) { |
| existing.grantableRights = add.grantableRights.duplicate(); |
| } else { |
| existing.grantableRights.add(add.grantableRights); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Iteration of all visible grantees, including self. <p> |
| * |
| * For grantees with admin, this is all grantees. |
| * For regular grantees, this is self plus all roles granted directly |
| * or indirectly |
| */ |
| public Set visibleGrantees() { |
| |
| HashSet grantees = new HashSet(); |
| GranteeManager gm = granteeManager; |
| |
| if (isAdmin()) { |
| grantees.addAll(gm.getGrantees()); |
| } else { |
| grantees.add(this); |
| |
| Iterator it = getAllRoles().iterator(); |
| |
| while (it.hasNext()) { |
| grantees.add(it.next()); |
| } |
| } |
| |
| return grantees; |
| } |
| |
| /** |
| * Set of all non-reserved visible grantees, including self. <p> |
| * |
| * For grantees with admin, this is all grantees. |
| * For regular grantees, this is self plus all roles granted directly |
| * or indirectly. <P> |
| * |
| * @param andPublic when <tt>true</tt> retains the reserved PUBLIC grantee |
| */ |
| public Set nonReservedVisibleGrantees(boolean andPublic) { |
| |
| Set grantees = visibleGrantees(); |
| GranteeManager gm = granteeManager; |
| |
| grantees.remove(gm.dbaRole); |
| grantees.remove(GranteeManager.systemAuthorisation); |
| |
| if (!andPublic) { |
| grantees.remove(gm.publicRole); |
| } |
| |
| return grantees; |
| } |
| |
| public boolean hasNonSelectTableRight(Table table) { |
| |
| if (isFullyAccessibleByRole(table.getName())) { |
| return true; |
| } |
| |
| Right right = (Right) fullRightsMap.get(table.getName()); |
| |
| if (right == null) { |
| return false; |
| } |
| |
| return right.isFull || right.isFullDelete || right.isFullInsert |
| || right.isFullUpdate || right.isFullReferences |
| || right.isFullTrigger; |
| } |
| |
| public boolean hasTableRight(Table table) { |
| |
| if (isFullyAccessibleByRole(table.getName())) { |
| return true; |
| } |
| |
| Right right = (Right) fullRightsMap.get(table.getName()); |
| |
| if (right == null) { |
| return false; |
| } |
| |
| return right.isFull || right.isFullDelete || right.isFullInsert |
| || right.isFullUpdate || right.isFullReferences |
| || right.isFullTrigger || right.isFullSelect; |
| } |
| |
| public Iterator getAllDirectFullRights(SchemaObject object) { |
| |
| Grantee owner = object.getOwner(); |
| |
| if (owner == this) { |
| return new WrapperIterator(ownerRights); |
| } |
| |
| return directRightsMap.get(object.getName()); |
| } |
| |
| public Right getAllGrantableRights(HsqlName name) { |
| |
| if (isAdmin) { |
| return name.schema.owner.ownerRights; |
| } |
| |
| if (name.schema.owner == this) { |
| return ownerRights; |
| } |
| |
| if (roles.contains(name.schema.owner)) { |
| return name.schema.owner.ownerRights; |
| } |
| |
| OrderedHashSet set = getAllRoles(); |
| |
| for (int i = 0; i < set.size(); i++) { |
| Grantee role = (Grantee) set.get(i); |
| |
| if (name.schema.owner == role) { |
| return role.ownerRights; |
| } |
| } |
| |
| Right right = (Right) fullRightsMap.get(name); |
| |
| return right == null || right.grantableRights == null ? Right.noRights |
| : right |
| .grantableRights; |
| } |
| |
| public boolean isAccessible(HsqlName name, int privilegeType) { |
| |
| if (isFullyAccessibleByRole(name)) { |
| return true; |
| } |
| |
| Right right = (Right) fullRightsMap.get(name); |
| |
| if (right == null) { |
| return false; |
| } |
| |
| return right.canAccess(privilegeType); |
| } |
| |
| /** |
| * returns true if grantee has any privilege (to any column) of the object |
| */ |
| public boolean isAccessible(SchemaObject object) { |
| return isAccessible(object.getName()); |
| } |
| |
| public boolean isAccessible(HsqlName name) { |
| |
| if (isFullyAccessibleByRole(name)) { |
| return true; |
| } |
| |
| Right right = (Right) fullRightsMap.get(name); |
| |
| if (right != null && !right.isEmpty()) { |
| return true; |
| } |
| |
| if (!isPublic) { |
| return granteeManager.publicRole.isAccessible(name); |
| } |
| |
| return false; |
| } |
| |
| public HsqlArrayList getRightsSQL() { |
| |
| HsqlArrayList list = new HsqlArrayList(); |
| String roleString = getDirectRolesAsString(); |
| |
| if (roleString.length() != 0) { |
| StringBuffer sb = new StringBuffer(128); |
| |
| sb.append(Tokens.T_GRANT).append(' ').append(roleString); |
| sb.append(' ').append(Tokens.T_TO).append(' '); |
| sb.append(getStatementName()); |
| list.add(sb.toString()); |
| } |
| |
| MultiValueHashMap rightsMap = getRights(); |
| Iterator dbObjects = rightsMap.keySet().iterator(); |
| |
| while (dbObjects.hasNext()) { |
| Object nameObject = dbObjects.next(); |
| Iterator rights = rightsMap.get(nameObject); |
| |
| while (rights.hasNext()) { |
| Right right = (Right) rights.next(); |
| StringBuffer sb = new StringBuffer(128); |
| HsqlName hsqlname = (HsqlName) nameObject; |
| |
| switch (hsqlname.type) { |
| |
| case SchemaObject.TABLE : |
| case SchemaObject.VIEW : |
| Table table = |
| granteeManager.database.schemaManager |
| .findUserTable(null, hsqlname.name, |
| hsqlname.schema.name); |
| |
| if (table != null) { |
| sb.append(Tokens.T_GRANT).append(' '); |
| sb.append(right.getTableRightsSQL(table)); |
| sb.append(' ').append(Tokens.T_ON).append(' '); |
| sb.append(Tokens.T_TABLE).append(' '); |
| sb.append( |
| hsqlname.getSchemaQualifiedStatementName()); |
| } |
| break; |
| |
| case SchemaObject.SEQUENCE : |
| NumberSequence sequence = |
| (NumberSequence) granteeManager.database |
| .schemaManager |
| .findSchemaObject(hsqlname.name, |
| hsqlname.schema.name, |
| SchemaObject.SEQUENCE); |
| |
| if (sequence != null) { |
| sb.append(Tokens.T_GRANT).append(' '); |
| sb.append(Tokens.T_USAGE); |
| sb.append(' ').append(Tokens.T_ON).append(' '); |
| sb.append(Tokens.T_SEQUENCE).append(' '); |
| sb.append( |
| hsqlname.getSchemaQualifiedStatementName()); |
| } |
| break; |
| |
| case SchemaObject.DOMAIN : |
| Type domain = |
| (Type) granteeManager.database.schemaManager |
| .findSchemaObject(hsqlname.name, |
| hsqlname.schema.name, |
| SchemaObject.DOMAIN); |
| |
| if (domain != null) { |
| sb.append(Tokens.T_GRANT).append(' '); |
| sb.append(Tokens.T_USAGE); |
| sb.append(' ').append(Tokens.T_ON).append(' '); |
| sb.append(Tokens.T_DOMAIN).append(' '); |
| sb.append( |
| hsqlname.getSchemaQualifiedStatementName()); |
| } |
| break; |
| |
| case SchemaObject.TYPE : |
| Type type = |
| (Type) granteeManager.database.schemaManager |
| .findSchemaObject(hsqlname.name, |
| hsqlname.schema.name, |
| SchemaObject.DOMAIN); |
| |
| if (type != null) { |
| sb.append(Tokens.T_GRANT).append(' '); |
| sb.append(Tokens.T_USAGE); |
| sb.append(' ').append(Tokens.T_ON).append(' '); |
| sb.append(Tokens.T_TYPE).append(' '); |
| sb.append( |
| hsqlname.getSchemaQualifiedStatementName()); |
| } |
| break; |
| |
| case SchemaObject.PROCEDURE : |
| case SchemaObject.FUNCTION : |
| case SchemaObject.SPECIFIC_ROUTINE : |
| SchemaObject routine = |
| (SchemaObject) granteeManager.database |
| .schemaManager |
| .findSchemaObject(hsqlname.name, |
| hsqlname.schema.name, |
| hsqlname.type); |
| |
| if (routine != null) { |
| sb.append(Tokens.T_GRANT).append(' '); |
| sb.append(Tokens.T_EXECUTE).append(' '); |
| sb.append(Tokens.T_ON).append(' '); |
| sb.append(Tokens.T_SPECIFIC).append(' '); |
| |
| if (routine.getType() == SchemaObject.PROCEDURE) { |
| sb.append(Tokens.T_PROCEDURE); |
| } else { |
| sb.append(Tokens.T_FUNCTION); |
| } |
| |
| sb.append(' '); |
| sb.append( |
| hsqlname.getSchemaQualifiedStatementName()); |
| } |
| break; |
| } |
| |
| if (sb.length() == 0) { |
| continue; |
| } |
| |
| sb.append(' ').append(Tokens.T_TO).append(' '); |
| sb.append(getStatementName()); |
| list.add(sb.toString()); |
| } |
| } |
| |
| return list; |
| } |
| } |