package eu.doppel_helix.netbeans.mantisintegration.repository; import biz.futureware.mantisconnect.AccountData; import biz.futureware.mantisconnect.MantisConnectPortType; import eu.doppel_helix.netbeans.mantisintegration.data.Permission; import eu.doppel_helix.netbeans.mantisintegration.data.Version; import eu.doppel_helix.netbeans.mantisintegration.issue.MantisIssue; import java.math.BigInteger; import java.rmi.RemoteException; import java.text.MessageFormat; import java.util.HashMap; import java.util.logging.Level; import java.util.logging.Logger; import javax.xml.rpc.ServiceException; import org.apache.axis.AxisFault; public class Capabilities { private static final Version tagVersion = new Version("1.2.9"); private static final Logger logger = Logger.getLogger(Capabilities.class.getName()); private final MantisRepository mr; private final HashMap<BigInteger,Boolean> projectUpdater = new HashMap<>(); private boolean userIsUpdaterChecked = false; private Boolean userIsUpdater = false; private final HashMap<BigInteger,Permission> projectTimetracker = new HashMap<>(); private boolean trackTimeChecked = false; private boolean trackTime = false; private Permission trackTimeGlobal = null; private boolean trackTimeGlobalChecked = false; public Capabilities(MantisRepository mr) { this.mr = mr; } public boolean canUpdate(MantisIssue mi) { // While updating MantisIssue could be not update and project not yet assigned if(mi == null || mi.getProject() == null) { return false; } BigInteger projectId = mi.getProject().getId(); // Try project specific variant first (will fail on large resultsets) // Check cached value -- BEWARE! NULL _is_ a valid user => unknown if(projectUpdater.containsKey(projectId) && projectUpdater.get(projectId) != null) { return projectUpdater.get(projectId); } // 40 is the access level for "updater" final BigInteger requiredAccesslevel = BigInteger.valueOf(40); // Only try this once => takes potentially extremely long if (! projectUpdater.containsKey(projectId)) { try { AccountData[] validUsers = mr.getClient().mc_project_get_users( mr.getInfo().getUsername(), new String(mr.getInfo().getPassword()), projectId, requiredAccesslevel); for (AccountData ac : validUsers) { if (mr.getInfo().getUsername().equalsIgnoreCase(ac.getName())) { projectUpdater.put(projectId, true); return true; } } projectUpdater.put(projectId, false); } catch (Exception ex) { logger.log(Level.INFO, MessageFormat.format( "Failed to retrieve updaters for project {0}", projectId), ex); // Prevent multiple tries to retrieve users projectUpdater.put(projectId, null); } } // Fallback to user role if(userIsUpdaterChecked && userIsUpdater != null) { return userIsUpdater; } // Try this only once ... if(! userIsUpdaterChecked) { userIsUpdaterChecked = true; BigInteger userAccessLevel; try { userAccessLevel = mr.getAccount().getAccess_level(); if (userAccessLevel.compareTo(requiredAccesslevel) >= 0) { userIsUpdater = true; } else { userIsUpdater = false; } return userIsUpdater; } catch (Exception ex) { logger.log(Level.INFO, "Failed to retrieve accesslevel for user", ex); userIsUpdater = null; } } // *arg* -> we can't know so asume the developer (our targetgroup) // knows what he is doing and allowed return true; } public boolean isTagSupport() throws ServiceException, RemoteException { return mr.getVersion().compareTo(tagVersion) >= 0; } public Permission getTrackTime(MantisIssue mi) throws RemoteException { // While updating MantisIssue could be not update and project not yet assigned // Fallback to WRITE permission if(mi == null || mi.getProject() == null) { return Permission.WRITE; } BigInteger projectId = mi.getProject().getId(); // Try project specific variant first (will fail on large resultsets) // Check cached value -- BEWARE! NULL _is_ a valid user => unknown if (projectTimetracker.containsKey(projectId) && projectTimetracker.get(projectId) != null) { return projectTimetracker.get(projectId); } if (this.trackTimeChecked && (!trackTime)) { return Permission.NONE; } trackTime = false; MantisConnectPortType mcpt; try { mcpt = mr.getClient(); } catch (ServiceException ex) { logger.log(Level.WARNING, "Failed to access bugtracker to retrieve timetracking info"); return Permission.NONE; } // The following assumes, that a failure means the backing system // does not support time tracking -- the AxisFault indicates // a problem on the logical layer, not somewhere beneath try { String enabled = mcpt.mc_config_get_string( mr.getInfo().getUsername(), new String(mr.getInfo().getPassword()), "time_tracking_enabled"); if("1".equals(enabled)) { trackTime = true; } else { trackTime = false; } trackTimeChecked = true; } catch (AxisFault af) { trackTimeChecked = true; return Permission.NONE; } if (! trackTime) { return Permission.NONE; } BigInteger viewThreshold = BigInteger.valueOf(55); // Default: Developer BigInteger editThreshold = BigInteger.valueOf(55); // Default: Developer try { String viewThresholdString = mcpt.mc_config_get_string( mr.getInfo().getUsername(), new String(mr.getInfo().getPassword()), "time_tracking_view_threshold"); String editThresholdString = mcpt.mc_config_get_string( mr.getInfo().getUsername(), new String(mr.getInfo().getPassword()), "time_tracking_edit_threshold"); viewThreshold = new BigInteger(viewThresholdString); editThreshold = new BigInteger(editThresholdString); } catch (Exception ex) { } // Only try this once => takes potentially extremely long if (! projectTimetracker.containsKey(projectId)) { try { // Check for EDIT access AccountData[] validUsers = mr.getClient().mc_project_get_users( mr.getInfo().getUsername(), new String(mr.getInfo().getPassword()), projectId, editThreshold); for (AccountData ac : validUsers) { if (mr.getInfo().getUsername().equalsIgnoreCase(ac.getName())) { projectTimetracker.put(projectId, Permission.WRITE); return Permission.WRITE; } } // Check for READ access validUsers = mr.getClient().mc_project_get_users( mr.getInfo().getUsername(), new String(mr.getInfo().getPassword()), projectId, viewThreshold); for (AccountData ac : validUsers) { if (mr.getInfo().getUsername().equalsIgnoreCase(ac.getName())) { projectTimetracker.put(projectId, Permission.READ); return Permission.READ; } } projectTimetracker.put(projectId, Permission.NONE); return Permission.NONE; } catch (Exception ex) { logger.log(Level.INFO, MessageFormat.format( "Failed to retrieve updaters for project {0}", projectId), ex); // Prevent multiple tries to retrieve users projectUpdater.put(projectId, null); } } // Try this only once ... if (! trackTimeGlobalChecked) { trackTimeGlobalChecked = true; try { BigInteger userAccessLevel = mr.getAccount().getAccess_level(); if (userAccessLevel.compareTo(editThreshold) >= 0) { trackTimeGlobal = Permission.WRITE; } else if (userAccessLevel.compareTo(viewThreshold) >= 0) { trackTimeGlobal = Permission.READ; } else { trackTimeGlobal = Permission.NONE; } return trackTimeGlobal; } catch (ServiceException | RemoteException ex) { logger.log(Level.INFO, "Failed to retrieve accesslevel for user", ex); userIsUpdater = null; } } else if (trackTimeGlobal != null) { return trackTimeGlobal; } // If time tracking is enabled and we can't fetch project specific // settings, we fall back to write access... return Permission.WRITE; } }