// Copyright 2004-2014 Jim Voris // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // package com.qumasoft.server; import com.qumasoft.qvcslib.QVCSConstants; import com.qumasoft.qvcslib.RoleType; import com.qumasoft.qvcslib.Utility; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.util.logging.Level; import java.util.logging.Logger; /** * Role privileges manager. This is a singleton. * @author Jim Voris */ public final class RolePrivilegesManager { // Create our logger object private static final Logger LOGGER = Logger.getLogger("com.qumasoft.server"); // This is a singleton. private static final RolePrivilegesManager ROLE_PRIVILEGES_MANAGER = new RolePrivilegesManager(); // These are the actions that we know about. The privilege to perform these actions can be enabled/disabled per separately defined role. /** Get a file action. */ public static final ServerAction GET = new ServerAction("Get file", false); /** Get a directory action. */ public static final ServerAction GET_DIRECTORY = new ServerAction("Get directory", false); /** Show the cemetery directory action. */ public static final ServerAction SHOW_CEMETERY = new ServerAction("Show cemetery", false); /** Show branch archives directory action. */ public static final ServerAction SHOW_BRANCH_ARCHIVES_DIRECTORY = new ServerAction("Show branch archives directory", false); /** Check out a file revision action. */ public static final ServerAction CHECK_OUT = new ServerAction("Check out", true); /** Check in a file revision action. */ public static final ServerAction CHECK_IN = new ServerAction("Check in", true); /** Lock a file revision action. */ public static final ServerAction LOCK = new ServerAction("Lock", true); /** Unlock a file revision action. */ public static final ServerAction UNLOCK = new ServerAction("Unlock", true); /** Break a revision lock action. */ public static final ServerAction BREAK_LOCK = new ServerAction("Break lock", true); /** Label a file action. */ public static final ServerAction LABEL = new ServerAction("Label", true); /** Label the files in a directory action. */ public static final ServerAction LABEL_DIRECTORY = new ServerAction("Label directory", true); /** Apply a label at checkin time action. */ public static final ServerAction LABEL_AT_CHECKIN = new ServerAction("Label at checkin", true); /** Remove a label action. */ public static final ServerAction REMOVE_LABEL = new ServerAction("Remove label", true); /** Remove a label from the files in a directory action. */ public static final ServerAction REMOVE_LABEL_DIRECTORY = new ServerAction("Remove label from directory", true); /** Rename a file action. */ public static final ServerAction RENAME_FILE = new ServerAction("Rename file", true); /** Move a file action. */ public static final ServerAction MOVE_FILE = new ServerAction("Move file", true); /** Delete a file action. */ public static final ServerAction SET_OBSOLETE = new ServerAction("Delete file", true); /** Set QVCS archive attributes action. */ public static final ServerAction SET_ATTRIBUTES = new ServerAction("Set file attributes", true); /** Set the comment prefix for an archive file action. */ public static final ServerAction SET_COMMENT_PREFIX = new ServerAction("Set comment prefix", true); /** Set the module description action. */ public static final ServerAction SET_MODULE_DESCRIPTION = new ServerAction("Set file description", true); /** Set a revision description action. */ public static final ServerAction SET_REVISION_DESCRIPTION = new ServerAction("Set revision description", true); /** Create a new QVCS archive action (put a file under source control). */ public static final ServerAction CREATE_ARCHIVE = new ServerAction("Create archive", true); /** Add a directory action. */ public static final ServerAction ADD_DIRECTORY = new ServerAction("Add directory", true); /** Merge changes from parent to branch action. */ public static final ServerAction MERGE_FROM_PARENT = new ServerAction("Merge from parent", true); /** Promote to parent action. */ public static final ServerAction PROMOTE_TO_PARENT = new ServerAction("Promote to parent", true); /** Delete a directory action. */ public static final ServerAction DELETE_DIRECTORY = new ServerAction("Delete directory", true); /** Maintain a view's properties action. */ public static final ServerAction SERVER_MAINTAIN_VIEW = new ServerAction("Maintain view", true); /** Add a user role action. */ public static final ServerAction ADD_USER_ROLE = new ServerAction("(Admin tool): Add user role", true); /** Remove a user role action. */ public static final ServerAction REMOVE_USER_ROLE = new ServerAction("(Admin tool): Remove user role", true); /** Assign user roles action. */ public static final ServerAction ASSIGN_USER_ROLES = new ServerAction("(Admin tool): Assign user roles", true); /** List the users of a project action. */ public static final ServerAction LIST_PROJECT_USERS = new ServerAction("(Admin tool): List project users", false); /** List user roles action. */ public static final ServerAction LIST_USER_ROLES = new ServerAction("(Admin tool): List user roles", false); /** Maintain a project's properties action. */ public static final ServerAction SERVER_MAINTAIN_PROJECT = new ServerAction("(Admin tool): Maintain project", true); private boolean isInitializedFlag = false; private String storeName = null; private String storeNameOld = null; private RolePrivilegesStore rolePrivilegesStore = null; /** * Creates a new instance of RolePrivilegesManager. */ private RolePrivilegesManager() { } /** * Initialize the role privileges manager. * @return true if initialization was successful; false otherwise. */ public synchronized boolean initialize() { if (!isInitializedFlag) { storeName = System.getProperty("user.dir") + File.separator + QVCSConstants.QVCS_ADMIN_DATA_DIRECTORY + File.separator + QVCSConstants.QVCS_ROLE_PRIVILEGES_STORE_NAME + "dat"; storeNameOld = storeName + ".old"; loadRoleStore(); isInitializedFlag = true; } return isInitializedFlag; } /** * Get the singleton instance of the role privileges manager. * @return the singleton instance of the role privileges manager. */ public static RolePrivilegesManager getInstance() { return ROLE_PRIVILEGES_MANAGER; } private synchronized void loadRoleStore() { FileInputStream fileStream = null; try { File storeFile = new File(storeName); fileStream = new FileInputStream(storeFile); ObjectInputStream inStream = new ObjectInputStream(fileStream); rolePrivilegesStore = (RolePrivilegesStore) inStream.readObject(); rolePrivilegesStore.createAdminPrivileges(); } catch (FileNotFoundException e) { // The file doesn't exist yet. Create a default store. rolePrivilegesStore = new RolePrivilegesStore(); rolePrivilegesStore.createDefaultPrivileges(); writeStore(); } catch (IOException | ClassNotFoundException e) { LOGGER.log(Level.WARNING, "Failed to read role privileges store: " + e.getLocalizedMessage()); if (fileStream != null) { try { fileStream.close(); fileStream = null; } catch (IOException ex) { LOGGER.log(Level.WARNING, Utility.expandStackTraceToString(ex)); } } // Serialization failed. Create a default store. rolePrivilegesStore = new RolePrivilegesStore(); rolePrivilegesStore.createDefaultPrivileges(); LOGGER.log(Level.INFO, "Creating default role privileges store."); writeStore(); } finally { if (fileStream != null) { try { fileStream.close(); } catch (IOException e) { LOGGER.log(Level.WARNING, Utility.expandStackTraceToString(e)); } } } } /** * Write the role privileges store to disk. */ public synchronized void writeStore() { FileOutputStream fileStream = null; try { File storeFile = new File(storeName); File oldStoreFile = new File(storeNameOld); if (oldStoreFile.exists()) { oldStoreFile.delete(); } if (storeFile.exists()) { storeFile.renameTo(oldStoreFile); } File newStoreFile = new File(storeName); // Make sure the needed directories exists if (!newStoreFile.getParentFile().exists()) { newStoreFile.getParentFile().mkdirs(); } fileStream = new FileOutputStream(newStoreFile); ObjectOutputStream outStream = new ObjectOutputStream(fileStream); outStream.writeObject(rolePrivilegesStore); } catch (IOException e) { LOGGER.log(Level.WARNING, Utility.expandStackTraceToString(e)); } finally { if (fileStream != null) { try { fileStream.close(); } catch (IOException e) { LOGGER.log(Level.WARNING, Utility.expandStackTraceToString(e)); } } } } /** * Does the user have the privileges needed to perform the requested action. * @param projectName the project name. * @param userName the QVCS user name. * @param action the action they wish to perform. * @return true if the user is allowed to perform the requested operation; false if not allowed. */ public synchronized boolean isUserPrivileged(String projectName, String userName, ServerAction action) { String[] userRoles = RoleManager.getRoleManager().listUserRoles(projectName, userName); boolean returnValue = false; for (String userRole : userRoles) { returnValue = rolePrivilegesStore.isRolePrivileged(userRole, action.getAction()); if (returnValue) { break; } } return returnValue; } /** * Get the list of available roles. * @return the list of available roles. */ public synchronized String[] getAvailableRoles() { return rolePrivilegesStore.getAvailableRoles(); } /** * For a given String, return the associated RoleType instance. * @param roleType role type as a String. * @return the associated RoleType instance. */ public synchronized RoleType getRoleType(String roleType) { return rolePrivilegesStore.getRoleType(roleType); } /** * Get the list of role privileges. * @return the list of role privileges. */ public synchronized String[] getRolePrivilegesList() { return rolePrivilegesStore.getRolePrivilegesList(); } /** * Get the role privileges flags for a given role. * @param role the role. * @return the role privileges flags for a given role. */ public synchronized Boolean[] getRolePrivilegesFlags(String role) { return rolePrivilegesStore.getRolePrivilegesFlags(role); } /** * Update the privileges flags for a given role. * @param role the role. * @param privileges the role privileges. * @param privilegesFlags the role privileges flags. */ public synchronized void updatePrivileges(final String role, final String[] privileges, final Boolean[] privilegesFlags) { rolePrivilegesStore.updatePrivileges(role, privileges, privilegesFlags); writeStore(); } /** * Delete a role. * @param role the role to delete. */ public synchronized void deleteRole(final String role) { rolePrivilegesStore.deleteRole(role); writeStore(); } }