By default, the EDAB database provides persistent storage for users, groups, and their relationships. However, many users already have a set of users and groups, as well as persistent storage mechanism in place. In these cases, duplicating users and groups in the new reporting environment is inefficient, time-consuming, and requires extra administration overhead.
To prevent these issues, EDAB provides three different ways on how users can integrate their existing user/group framework into the reporting system. The first option is to retrieve users and groups from an LDAP server. This connection and setup is detailed in Section 1.4.1.4 - LDAP Settings. The second option is to retrieve users and groups from an existing database and the third option is to use the UserSecurityProvider interface which provides an open API allowing users to retrieve/implement users and groups from any source.
If your existing users are in a database, EDAB provides a simple implementation of the UserSecurityProvider that can be configured using a properties file. This implementation allows you to supply the connection information for the database as well as SQL statements for all the user/group related actions. Note that this implementation will not work in all circumstances. If your schema cannot retrieve/set the proper information with a single SQL statement, you may need to provide your own implementation of UserSecurityProvider.
The properties file is named user-database.properties
, and should be placed in the <EDABInstallDir>/WEB-INF/orguserdb
directory. A sample properties file is shown below:
############################################################# #Whether to use custom database for user/group custom.user.database=true ############################################################# ############################################################# #If custom.user.database=true, then use these information to #connect to the database. custom.user.database.url=jdbc:hsqldb:C:/EDAB/data/quadbasedb custom.user.database.jdbcDriver=org.hsqldb.jdbcDriver custom.user.database.login=sa custom.user.database.password= ############################################################# ############################################################# #Whether each of the methods in UserSecurityProvider #is enabled. #----------------------------------------------------------- getUsers.enable=true getUsers.sql=Select username, fullname, email, password, user_role, id, securitylevel From users Order By username #----------------------------------------------------------- getGroups.enable=true getGroups.sql=Select name, description, id, securitylevel From groups Order By name #----------------------------------------------------------- getGroupRelations.enable=true getGroupRelations.sql=SELECT parent_g.name, child_g.name FROM group_relations r, groups parent_g, groups child_g WHERE r.parent_id = parent_g.id AND r.child_id = child_g.id #----------------------------------------------------------- getGroupUserRelations.enable=true getGroupUserRelations.sql=Select g.name, u.username From group_user_relations gr, groups g, users u Where gr.group_id=g.id And gr.user_id=u.id Order By g.name #----------------------------------------------------------- getUserParents.enable=true getUserParents.sql=SELECT r.group_id, g.name FROM group_user_relations r, groups g WHERE r.group_id = g.id AND r.user_id=? #----------------------------------------------------------- getGroupParents.enable=true getGroupParents.sql=Select parent_id From group_relations Where child_id=? #----------------------------------------------------------- deleteUser.enable=true deleteUser.sql=Delete From users Where username=? #----------------------------------------------------------- deleteGroup.enable=true deleteGroup.sql=Delete From groups Where name=? #----------------------------------------------------------- createUser.enable=true createUser.sql=Insert Into users (id, username, fullname, email, password, user_role, securitylevel) Values (?, ?, ?, ?, ?, ?, ?) #----------------------------------------------------------- createGroup.enable=true createGroup.sql1=Insert Into groups (id, name, description, securitylevel) Values (?, ?, ?, ?) createGroup.sql2=Delete From group_relations Where parent_id=? createGroup.sql3=Delete From group_user_relations Where group_id=? createGroup.sql4=Insert Into group_relations (parent_id, child_id) Values (?, ?) #----------------------------------------------------------- updateUser.enable=true updateUser.sql=Update users Set username=?, fullname=?, email=?, password=?, user_role=?, securitylevel=? Where username=? #----------------------------------------------------------- updateGroup.enable=true updateGroup.sql1=Update groups Set name=?, description=?, securitylevel=? Where name=? updateGroup.sql2=Delete From group_relations Where parent_id=? updateGroup.sql3=Delete From group_user_relations Where group_id=? updateGroup.sql4=Insert Into group_relations (parent_id, child_id) Values (?, ?) #----------------------------------------------------------- addGroupUserRelation.enable=true addGroupUserRelation.sql=Insert Into group_user_relations (group_id, user_id) Values (?, ?) #----------------------------------------------------------- setSecurityLevels.enable=true setSecurityLevels.sql1=Update users Set securitylevel=? Where username=? setSecurityLevels.sql2=Update groups Set securitylevel=? Where name=? #----------------------------------------------------------- resetSecurityLevel.enable=true #----------------------------------------------------------- getGroupsBySecurityLevel.enable=true getGroupsBySecurityLevel.sql=Select name From Groups Where securitylevel=? #----------------------------------------------------------- getUsersBySecurityLevel.enable=true getUsersBySecurityLevel.sql=Select username From users Where securitylevel=? #----------------------------------------------------------- #############################################################
The question marks in the SQL statements will be supplied by the EDAB engine when it runs queries. For any method that isn't enabled, EDAB will save that information in the EDAB database. Depending on your configuration, saving some information in the EDAB database and some in your own may not be able to work correctly.
For maximum flexibility, EDAB allows users to provide their own implementation of users and groups. The UserSecurityProvider interface provides open APIs into all the methods that set/retrieve user and group information. Implementing UserSecurityProvider allows you to retrieve user/group information from any source, and allows you to integrate your user database if the schema prevents you from retrieving the correct information with a single query. Below is a sample UserSecurityProvider implementation:
import java.util.*; import quadbase.reportorganizer.data.*; import quadbase.reportorganizer.ext.*; /** * A sample implementation of UserSecurityProvider that provides hard-coded * initialized users/groups/security that does not have any data persistent * mechanism. */ public class MyUserSecurityProvider implements UserSecurityProvider { User[] users; Group[] groups; GroupRelation[] gr; GroupUserRelation[] gur; /** * Initializes the provider with dummy users/groups/security */ public MyUserSecurityProvider() { users = new User[6]; users[0] = createUser("admin"); users[1] = createUser("jason"); users[2] = createUser("ricky"); users[3] = createUser("jordan"); users[4] = createUser("oneal"); users[5] = createUser("jerry"); groups = new Group[6]; groups[0] = createGroup("nba"); groups[1] = createGroup("sports"); groups[2] = createGroup("testers"); groups[3] = createGroup("managers"); groups[4] = createGroup("marketing"); groups[5] = createGroup("engineers"); gr = new GroupRelation[3]; gr[0] = new GroupRelation("sports","nba"); gr[1] = new GroupRelation("managers","marketing"); gr[2] = new GroupRelation("engineers","testers"); gur = new GroupUserRelation[6]; gur[0] = new GroupUserRelation("managers", "jason"); gur[1] = new GroupUserRelation("nba", "jordan"); gur[2] = new GroupUserRelation("marketing", "ricky"); gur[3] = new GroupUserRelation("nba", "oneal"); gur[4] = new GroupUserRelation("testers", "jerry"); gur[5] = new GroupUserRelation("testers", "jason"); } public User[] getUsers() throws Exception { return users; } public Group[] getGroups() throws Exception { return groups; } public GroupRelation[] getGroupRelations() throws Exception { return gr; } public GroupUserRelation[] getGroupUserRelations() throws Exception { return gur; } public String[] getUserParents(String username) throws Exception { Vector v = new Vector(); for (int i = 0; i < gur.length; i++) if (gur[i].getUserName().equals(username)) v.add(gur[i].getGroupName()); return toStringArr(v); } public String[] getGroupParents(String groupname) throws Exception { Vector v = new Vector(); for (int i = 0; i < gr.length; i++) if (gr[i].getChildName().equals(groupname)) v.add(gr[i].getParentName()); return toStringArr(v); } public void deleteUser(String username) throws Exception { if (users.length == 0) return; User[] users2 = new User[users.length-1]; int j = 0; for (int i = 0; i < users.length; i++) { if (j == users.length-1 && !users[i].getName().equals(username)) return; if (!users[i].getName().equals(username)) { users2[j] = users[i]; j += 1; } } users = users2; } /** * Delete a Group. Also deletes the group relationships and * group-user relationships * that references this GROUPNAME. * @param groupname the group name */ public void deleteGroup(String groupname) throws Exception { if (groups.length == 0) return; Group[] groups2 = new Group[groups.length-1]; int j = 0; for (int i = 0; i < groups.length; i++) { if (j == groups.length-1 && !groups[i].getName().equals(groupname)) return; if (!groups[i].getName().equals(groupname)) { groups2[j] = groups[i]; j += 1; } } groups = groups2; Vector v = new Vector(); for (int i = 0; i < gr.length; i++) { if (gr[i].getParentName().equals(groupname) || gr[i].getChildName().equals(groupname)) continue; v.add(gr[i]); } GroupRelation[] gr2 = new GroupRelation[v.size()]; for (int i = 0; i < gr2.length; i++) gr2[i] = (GroupRelation) v.get(i); gr = gr2; v = new Vector(); for (int i = 0; i < gur.length; i++) { if (gur[i].getGroupName().equals(groupname)) continue; v.add(gur[i]); } GroupUserRelation[] gur2 = new GroupUserRelation[v.size()]; for (int i = 0; i < gur2.length; i++) gur2[i] = (GroupUserRelation) v.get(i); gur = gur2; } public void createUser(User user) throws Exception { User[] users2 = new User[users.length+1]; System.arraycopy(users, 0, users2, 0, users.length); users2[users2.length-1] = user; users = users2; } public void updateUser(User user) throws Exception { for (int i = 0; i < users.length; i++) { if (users[i].getName().equals(user.getName())) { users[i] = user; return; } } } /** * Create a new Group. * @param parentGroup create this group * @param childUsers set the group to have these child users * @param childGroups set the group to have these child groups */ public void createGroup(Group parentGroup, User[] childUsers, Group[] childGroups) throws Exception { addGroup(parentGroup); if (childUsers != null && childUsers.length > 0) { for (int i = 0; i < childUsers.length; i++) { addGroupUserRelation (parentGroup.getName(), childUsers[i].getName()); } } if (childGroups != null && childGroups.length > 0) { GroupRelation[] gr2 = new GroupRelation[gr.length+childGroups.length]; System.arraycopy(gr, 0, gr2, 0, gr.length); int j = 0; for (int i = gr.length; i < gr2.length; i++) { gr2[i] = new GroupRelation(parentGroup.getName(), childGroups[j].getName()); j++; } gr = gr2; } } /** * Update a Group. This simple implementation simply calls * deleteGroup(parentGroup.getName()) and calls * createGroup(parentGroup, childUsers, childGroups); * * @param parentGroup update this group * @param childUsers set the group to have these child users * @param childGroups set the group to have these child groups */ public void updateGroup(Group parentGroup, User[] childUsers, Group[] childGroups) throws Exception { deleteGroup(parentGroup.getName()); createGroup(parentGroup, childUsers, childGroups); } public void addGroupUserRelation(String groupname, String username) throws Exception { GroupUserRelation[] gur2 = new GroupUserRelation[gur.length+1]; System.arraycopy(gur, 0, gur2, 0, gur.length); gur2[gur2.length-1] = new GroupUserRelation(groupname, username); gur = gur2; } // SECURITY LEVEL /////////////////////////////////////////////////////// /** * Sets the security level(s) for a group or user of the specified name(s) * Also sets the security level(s) for group or user that is not in NAME * but with the same SECLEVEL to -1 (Can simply call * resetSecurityLevel(secLevel) in the first line of this method * to achieve this). * @param secLevel the result security level number * @param name an array of name(s) to change * @param isGroup whether the name[i] is a group (isGroup[i]==true) * or a user (isGroup[i]==false). */ public void setSecurityLevels(int secLevel, String[] name, boolean[] isGroup) throws Exception { resetSecurityLevel(secLevel); for (int i = 0; i < name.length; i++) { if (isGroup[i]) { for (int j = 0; j < groups.length; j++) if (groups[j].getName().equals(name[i])) { groups[j].setSecurityLevel(secLevel); break; } } else { for (int j = 0; j < users.length; j++) if (users[j].getName().equals(name[i])) { users[j].setSecurityLevel(secLevel); break; } } } } /** * Resets (set to -1) the security level number of all groups * and users whose security level number is SECLEVEL. * @param secLevel the security level number of the group/user */ public void resetSecurityLevel(int secLevel) throws Exception { for (int i = 0; i < users.length; i++) if (users[i].getSecurityLevel() == secLevel) users[i].setSecurityLevel(-1); for (int i = 0; i < groups.length; i++) if (groups[i].getSecurityLevel() == secLevel) groups[i].setSecurityLevel(-1); } /** * @param secLevel the security level number of the group * @return the Group names of all groups with SECLEVEL */ public String[] getGroupsBySecurityLevel(int secLevel) throws Exception { Vector v = new Vector(); for (int i = 0; i < groups.length; i++) if (secLevel == groups[i].getSecurityLevel()) v.add(groups[i].getName()); String[] result = new String[v.size()]; for (int i = 0; i < result.length; i++) result[i] = (String) v.get(i); return result; } /** * @param secLevel the security level number of the user * @return the User names of all users with SECLEVEL */ public String[] getUsersBySecurityLevel(int secLevel) throws Exception { Vector v = new Vector(); for (int i = 0; i < users.length; i++) if (secLevel == users[i].getSecurityLevel()) v.add(users[i].getName()); String[] result = new String[v.size()]; for (int i = 0; i < result.length; i++) result[i] = (String) v.get(i); return result; } User createUser(String name) { if(name.equalsIgnoreCase("admin")){ return new User(name, //name name + " full name", //full name name, //password name + "@example.com", //email User.ADMIN, //role -1); //security level }else{ return new User(name, //name name + " full name", //full name name, //password name + "@example.com", //email User.DESIGNER, //role -1); //security level } } Group createGroup(String name) { return new Group(name, //name name + " desc", //description -1); //security level } void addGroup(Group g) { Group[] g2 = new Group[groups.length+1]; System.arraycopy(groups, 0, g2, 0, groups.length); g2[g2.length-1] = g; groups = g2; } static String[] toStringArr(Vector v) { String[] p = new String[v.size()]; for (int i = 0; i < p.length; i++) p[i] = (String) v.get(i); return p; } }
In the previous sample, the users and groups are defined as simple arrays in the code. As with the database properties file, any method that you do not implement in the UserSecurityProvider interface will use the default EDAB database as the storage mechanism.
The UserSecurityProvider
class can be set as a server option in EDAB. You can set this in one of two places. The first option is the Admin Console. You can specify the class in the Server Options tab. For more information about server configuration options, see Section 1.4.1.3 - Server Options. You can also specify the class by modifying the QB.properties
under <EDABInstallDir>/WEB-INF/classes
. However, editing configuration files directly is not recommended and should be done only in case when the EDAB server cannot be started because incorrect values have been provided through the Admin Console. If you still want to edit the files manually: edit user-database.properties
to use the "users/groups" other than ERES database, QB.properties
to set ERES database not only "users/groups", but also ERES setting, report/chart/etc/file paths, schedules, email settings, extension classes. It has higher priority than the database defined by user-database.properties
. Compiled, MyUserSecurityProvider.class
, if used, should be located in <EDABInstallDir>/WEB-INF/classes
directory.