@Test
 public void testGetStoryTasksWithEffortLeft_notInTimeframe() {
   executeClassSql();
   DateTime start = new DateTime(2008, 6, 10, 1, 0, 0, 0);
   User user = new User();
   user.setId(1);
   Interval interval = new Interval(start, start.plusDays(5));
   List<Task> actual = this.taskDAO.getStoryTasksWithEffortLeft(user, interval);
   assertEquals(0, actual.size());
 }
  @Test
  public void testGetAllIterationAndStoryTasks_user_hasNoAssigned() {
    executeClassSql();
    DateTime start = new DateTime(2009, 6, 10, 1, 0, 0, 0);
    Interval interval = new Interval(start, start.plusDays(5));
    User user = new User();
    user.setId(4);

    List<Task> actual = this.taskDAO.getAllIterationAndStoryTasks(user, interval);
    assertEquals(0, actual.size());
  }
Beispiel #3
0
 @Test
 public void testListUsersByEnabledStatus_disabled() {
   executeClassSql();
   List<User> users = userDAO.listUsersByEnabledStatus(false);
   assertEquals(1, users.size());
   List<Integer> foundIds = new ArrayList<Integer>();
   for (User user : users) {
     foundIds.add(user.getId());
   }
   assertTrue(foundIds.contains(3));
 }
 @Test
 public void testGetUnassignedStoryTasksWithEffortLeftWithNullEffortSpent() {
   executeClassSql();
   DateTime start = new DateTime(2009, 6, 10, 1, 0, 0, 0);
   User user = new User();
   user.setId(3);
   Interval interval = new Interval(start, start.plusDays(5));
   List<UnassignedLoadTO> actual =
       this.taskDAO.getUnassignedStoryTasksWithEffortLeft(user, interval);
   assertTrue(actual.isEmpty());
 }
 // check from the backlogId if the associated product is accessible for the current user
 private boolean checkAccess(int backlogId) {
   Product product = (backlogBusiness.getParentProduct(backlogBusiness.retrieve(backlogId)));
   User user = SecurityUtil.getLoggedUser();
   Collection<Team> teams = user.getTeams();
   for (Iterator<Team> iter = teams.iterator(); iter.hasNext(); ) {
     Team team = (Team) iter.next();
     if (team.getProducts().contains(product)) {
       return false;
     }
   }
   return true;
 }
 @Test
 public void testGetUnassignedIterationTasksWithEffortLeft() {
   executeClassSql();
   DateTime start = new DateTime(2009, 6, 10, 1, 0, 0, 0);
   User user = new User();
   user.setId(1);
   Interval interval = new Interval(start, start.plusDays(5));
   List<UnassignedLoadTO> actual =
       this.taskDAO.getUnassignedIterationTasksWithEffortLeft(user, interval);
   assertEquals(2, actual.size());
   assertEquals(970, actual.get(0).effortLeft.intValue());
   assertEquals(100, actual.get(0).availability);
   assertEquals(1, actual.get(0).iterationId);
 }
  @Test
  public void testGetAllIterationAndStoryTasks() {
    executeClassSql();
    DateTime start = new DateTime(2009, 6, 10, 1, 0, 0, 0);
    Interval interval = new Interval(start, start.plusDays(5));
    User user = new User();
    user.setId(1);
    List<Task> actual = this.taskDAO.getAllIterationAndStoryTasks(user, interval);

    HashSet<Integer> actualIds = new HashSet<Integer>();
    for (Task t : actual) {
      actualIds.add(t.getId());
    }

    HashSet<Integer> expectedIds = new HashSet<Integer>(Arrays.asList(2, 3, 4));
    assertEquals(expectedIds, actualIds);
  }
  /**
   * Calculates overheads for user from given backlogs( projects)
   *
   * @param from
   * @param weeksAhead
   * @param items
   * @return
   */
  public HashMap<Integer, String> calculateOverheads(
      Date from, int weeksAhead, List<Backlog> items, User user) {
    GregorianCalendar cal = new GregorianCalendar();
    CalendarUtils cUtils = new CalendarUtils();
    HashMap<Integer, String> overheads = new HashMap<Integer, String>();

    Date start = from;
    Date end = cUtils.nextMonday(start);
    cal.setTime(start);
    Integer week = cal.get(GregorianCalendar.WEEK_OF_YEAR);
    List<Assignment> assignments = new ArrayList<Assignment>(user.getAssignments());

    for (int i = 1; i <= weeksAhead; i++) {
      // 1. Get Backlogs that hit for the week
      log.debug("Projects searched from :" + start);
      log.debug("Projects searched ending :" + end);
      cal.setTime(start);
      week = cal.get(GregorianCalendar.WEEK_OF_YEAR);
      log.debug("Calculating overhead for week" + week);

      // 2. Get projects that hit current week
      List<Backlog> list = this.getProjectsAndIterationsInTimeFrame(items, start, end);
      log.debug(list.size() + " projects found for given time frame");

      // 3. Calculate overhead sum from items in those projects
      AFTime overhead = new AFTime(0);
      for (Backlog blog : list) {
        // Only check assignments for Projects (overhead
        // only set for projects not iterations)
        if (blog.getClass().equals(Project.class)) {
          Project pro = (Project) blog;
          for (Assignment ass : assignments) {
            if (ass.getBacklog().equals((Backlog) pro)) {
              if (pro.getDefaultOverhead() != null) {
                overhead.add(pro.getDefaultOverhead());
                log.debug("Added overhead from project: " + pro.getDefaultOverhead());
              }
              if (ass.getDeltaOverhead() != null) {
                overhead.add(ass.getDeltaOverhead());
                log.debug("Added overhead from user: "******"Class was iteration class, overhead :" + blog.getClass());
        }
      }
      overheads.put(week, overhead.toString());
      start = cUtils.nextMonday(start);
      end = cUtils.nextMonday(start);
      cal.setTime(start);
      week = cal.get(GregorianCalendar.WEEK_OF_YEAR);
    }

    return overheads;
  }
  @Before
  public void setUpStorysProjectResponsiblesData() {
    Iteration iter = new Iteration();
    Project proj = new Project();
    Product prod = new Product();
    iter.setParent(proj);
    proj.setParent(prod);

    assignedUser = new User();
    assignedUser.setId(2233);

    storyInIteration = new Story();
    storyInProject = new Story();
    storyInProduct = new Story();

    storyInIteration.setId(868);
    storyInProduct.setId(951);
    storyInProject.setId(3);

    storyInIteration.setIteration(iter);
    storyInIteration.setBacklog(proj);
    storyInProject.setBacklog(proj);
    storyInProduct.setBacklog(prod);
  }
 /**
  * Calculate whether given hours can be fitted to the given week. Each day is assumed 8 hours
  * long.
  *
  * @param currentWeek
  * @param targetWeek
  * @param totalWorkload
  * @return
  */
 private boolean isAccommodableWorkload(
     int currentWeek, int targetWeek, AFTime totalWorkload, User user) {
   if (user == null) {
     return false;
   }
   long totalInWeek = 5;
   int daysLeft = 5;
   if (currentWeek == targetWeek) {
     Calendar cal = GregorianCalendar.getInstance();
     daysLeft = 1;
     while (cal.get(Calendar.DAY_OF_WEEK) != Calendar.FRIDAY && daysLeft < 6) {
       cal.add(Calendar.DAY_OF_YEAR, 1);
       daysLeft++;
     }
   }
   totalInWeek =
       (long)
           (user.getWeekHours().getTime()
               * (1.0 * daysLeft * settingBusiness.getCriticalLow() / (5 * 100)));
   if (totalInWeek < totalWorkload.getTime()) {
     return false;
   }
   return true;
 }
  @Override
  public String intercept(ActionInvocation invocation) throws Exception {
    Object action = invocation.getAction();
    boolean accessDenied = false;

    // check read only user permissions
    User currentUser = SecurityUtil.getLoggedUser();
    if (!(action instanceof ROIterationAction
            || action instanceof ChartAction
            || action instanceof IterationAction
            || action instanceof IterationHistoryAction
            || action instanceof StoryAction)
        && currentUser.getLoginName().equals("readonly")) {

      return "login";
    } else if ((action instanceof ROIterationAction
            || action instanceof ChartAction
            || action instanceof IterationAction
            || action instanceof IterationHistoryAction
            || action instanceof StoryAction)
        && currentUser.getLoginName().equals("readonly")) {

      // TODO FINNUCKS: this causes an exception
      /*int id = -99;
      if(action instanceof ROIterationAction){
          readOnlyId = ((ROIterationAction)action).getIteration().getId();
          return invocation.invoke();
      } else if(action instanceof IterationAction){
          id = ((IterationAction) action).getIterationId();
      } else if(action instanceof IterationHistoryAction){
          id = ((IterationHistoryAction) action).getIterationId();
      } else if(action instanceof StoryAction){
          id = ((StoryAction) action).getIterationId();
      } else if(action instanceof ChartAction){
          id = ((ChartAction) action).getBacklogId();
      }

      if(id != readOnlyId){
          return "noauth";
      } else {*/
      return invocation.invoke();
      // }
    }

    // matrix authorizations
    if (action instanceof BacklogAction) {
      accessDenied = checkAccess(((BacklogAction) action).getBacklogId());
    } else if (action instanceof ProductAction) {
      accessDenied = checkAccess(((ProductAction) action).getProductId());
    } else if (action instanceof ProjectAction) {
      accessDenied = checkAccess(((ProjectAction) action).getProjectId());
    } else if (action instanceof IterationAction) {
      accessDenied = checkAccess(((IterationAction) action).getIterationId());
    } else {
      // admin authorizations
      currentUser = SecurityUtil.getLoggedUser();
      boolean isAdmin = currentUser.isAdmin();

      if (isAdmin) {
        // admin has access to any actions
        return invocation.invoke();
      } else {
        if (action instanceof AccessAction
            || action instanceof DatabaseExportAction
            || action instanceof SettingAction) {
          return "notadmin";
        } else {
          return invocation.invoke();
        }
      }
    }

    if (accessDenied) return "noauth";
    return invocation.invoke();
  }
  private void fillProjectPortfolioData(ProjectPortfolioData data) {
    HashMap<Project, String> userDataMap = new HashMap<Project, String>();
    HashMap<Project, Integer> unassignedUserDataMap = new HashMap<Project, Integer>();
    HashMap<Project, String> summaryLoadLeftMap = new HashMap<Project, String>();
    HashMap<String, String> loadLeftData = new HashMap<String, String>();
    HashMap<String, String> userOverheads = new HashMap<String, String>();
    HashMap<String, String> totalUserOverheads = new HashMap<String, String>();
    HashMap<String, Integer> unassignedUsersMap = new HashMap<String, Integer>();
    Map<Project, List<User>> assignmentMap = new HashMap<Project, List<User>>(0);
    Map<Project, List<User>> nonAssignmentMap = new HashMap<Project, List<User>>(0);
    Set<String> keySet = new HashSet<String>();

    Map<String, Integer> unassignedBlisMap = new HashMap<String, Integer>();

    Collection<Project> projects = projectDAO.getOngoingProjects();

    // Go trough all projects and bli:s
    for (Project pro : projects) {
      int assignedUsers = backlogBusiness.getNumberOfAssignedUsers(pro);
      int unestimatedBlis = 0;
      AFTime ongoingBliLoadLeft = new AFTime(0);
      Set<User> allUsers = new HashSet<User>(this.backlogBusiness.getUsers(pro, true));
      HashSet<User> projectAssignments =
          new HashSet<User>(this.backlogBusiness.getUsers(pro, true));
      List<User> nonAssignedUsers = new ArrayList<User>();
      /*
       * ArrayList<User> assignments = new ArrayList<User>(
       * this.backlogBusiness.getUsers(pro, true));
       */
      Collection<BacklogItem> blis = getBlisInProjectAndItsIterations(pro);

      // Get overheads for users in this project
      for (Assignment ass : pro.getAssignments()) {
        if (ass.getDeltaOverhead() != null) {
          userOverheads.put(
              pro.getId() + "-" + ass.getUser().getId(), ass.getDeltaOverhead().toString());
          AFTime total = new AFTime(0);
          if (pro.getDefaultOverhead() != null) {
            total.add(pro.getDefaultOverhead());
          }
          total.add(ass.getDeltaOverhead());
          totalUserOverheads.put(pro.getId() + "-" + ass.getUser().getId(), total.toString());
        } else {
          if (pro.getDefaultOverhead() != null) {
            totalUserOverheads.put(
                pro.getId() + "-" + ass.getUser().getId(), pro.getDefaultOverhead().toString());
          } else {
            totalUserOverheads.put(pro.getId() + "-" + ass.getUser().getId(), "");
          }
        }
      }

      for (BacklogItem bli : blis) {
        if (bli.getResponsibles() != null) {
          ArrayList<User> responsibles = new ArrayList<User>(bli.getResponsibles());

          if (bli.getEffortLeft() == null) {
            unestimatedBlis++;
            allUsers.addAll(bli.getResponsibles());
          } else if (bli.getEffortLeft().getTime() != 0) {
            ongoingBliLoadLeft.add(bli.getEffortLeft());
            allUsers.addAll(bli.getResponsibles());
          }

          for (User resp : responsibles) {

            keySet.add(pro.getId() + "-" + resp.getId());

            // Calculate and add effort from bli to user(s) assigned
            // Uses projectID-UserId as map key
            String effortForUsr = loadLeftData.get(pro.getId() + "-" + resp.getId());
            if (effortForUsr != null) {
              AFTime usrLoadLeft = new AFTime(effortForUsr);
              if (bli.getEffortLeft() != null) {
                // Add effort to this user: (bli effort / number
                // of people assigned)
                AFTime newEffort = new AFTime(bli.getEffortLeft().getTime() / responsibles.size());
                usrLoadLeft.add(newEffort);
                loadLeftData.put(pro.getId() + "-" + resp.getId(), usrLoadLeft.toString());
              }
            } else { // no effort for user, create one
              if (bli.getEffortLeft() != null) {
                AFTime t = new AFTime(bli.getEffortLeft().getTime() / responsibles.size());
                loadLeftData.put(pro.getId() + "-" + resp.getId(), t.toString());
              }
            }

            // Check whether user is responsible for a bli in the
            // project but is currently not assigned to it

            if (!projectAssignments.contains(resp) && bli.getEffortLeft() == null) {
              unassignedUsersMap.put(pro.getId() + "-" + resp.getId(), 1);
              if (!nonAssignedUsers.contains(resp)) {
                nonAssignedUsers.add(resp);
              }
            } else if (!projectAssignments.contains(resp) && bli.getEffortLeft().getTime() != 0) {
              unassignedUsersMap.put(pro.getId() + "-" + resp.getId(), 1);
              if (!nonAssignedUsers.contains(resp)) {
                nonAssignedUsers.add(resp);
              }
            }
            if (bli.getEffortLeft() == null) {
              int numberOfUnestimatedBlis = 1;
              if (unassignedBlisMap.get(pro.getId() + "-" + resp.getId()) != null) {
                numberOfUnestimatedBlis =
                    unassignedBlisMap.get(pro.getId() + "-" + resp.getId()) + 1;
              }
              unassignedBlisMap.put(pro.getId() + "-" + resp.getId(), numberOfUnestimatedBlis);
            }
          }
        }
      }
      int unassignedUsers = allUsers.size() - assignedUsers;

      String userDataString = "" + assignedUsers;
      EffortSumData loadData = new EffortSumData();
      loadData.setEffortHours(ongoingBliLoadLeft);
      loadData.setNonEstimatedItems(unestimatedBlis);
      String loadLeftString = loadData.toString();

      summaryLoadLeftMap.put(pro, loadLeftString);
      userDataMap.put(pro, userDataString);
      unassignedUserDataMap.put(pro, unassignedUsers);
      assignmentMap.put(pro, new ArrayList<User>(this.backlogBusiness.getUsers(pro, true)));
      nonAssignmentMap.put(pro, nonAssignedUsers);
    }

    for (String key : keySet) {
      String value = loadLeftData.get(key);
      // Fetch aftime-value and non-estimated items to a
      // EffortSumData-object to get correct output string.
      AFTime aftimeValue = new AFTime(0);
      if (value != null) aftimeValue = new AFTime(value);

      int userUnestimatedBlis = 0;
      if (unassignedBlisMap.get(key) != null) userUnestimatedBlis += unassignedBlisMap.get(key);

      EffortSumData sumData = new EffortSumData();
      sumData.setEffortHours(aftimeValue);
      sumData.setNonEstimatedItems(userUnestimatedBlis);

      value = sumData.toString();

      loadLeftData.put(key, value);
    }

    data.setUnassignedUsers(unassignedUsersMap);
    data.setAssignedUsers(assignmentMap);
    data.setSummaryUserData(userDataMap);
    data.setSummaryUnassignedUserData(unassignedUserDataMap);
    data.setSummaryLoadLeftData(summaryLoadLeftMap);
    data.setLoadLefts(loadLeftData);
    data.setUserOverheads(userOverheads);
    data.setTotalUserOverheads(totalUserOverheads);
    data.setNonAssignedUsers(nonAssignmentMap);
  }
  public String intercept(ActionInvocation invocation) throws Exception {

    int userId;
    Object action = invocation.getAction();

    if (action instanceof ExceptionHandler) {
      // actually print the message for debugging purposes
      String trace = getStackTrace(((ExceptionHandler) action).getException());
      return "";
    }

    // TODO FINNUCKS: this logs out a current user on one of
    // these actions and sets it to the read only user.
    // Need to check ID and ... ?
    if (action instanceof ROIterationAction
        || (isUnderReadOnlyAction
            && (action instanceof ChartAction
                || action instanceof IterationAction
                || action instanceof IterationHistoryAction
                || action instanceof StoryAction))) {

      isUnderReadOnlyAction = true;

      // log in read only user if we got to here
      UserDAOHibernate userDao = new UserDAOHibernate();

      SessionFactory sessionFactory = null;
      try {
        sessionFactory = (SessionFactory) new InitialContext().lookup("hibernateSessionFactory");
        userDao.setSessionFactory(sessionFactory);
      } catch (NamingException e) {
        e.printStackTrace();
      }
      Session session = sessionFactory.openSession();

      User user = userDao.getByLoginName("readonly");

      SecurityUtil.setLoggedUser(user);

      // push current user to the value stack
      invocation.getStack().set("currentUser", user);
      invocation.getStack().set("currentUserJson", new JSONSerializer().serialize(user));

      session.disconnect();
      session.close();

      // perform request
      String result = invocation.invoke();

      // after the request:
      // reset the logged user
      SecurityUtil.setLoggedUser(null);

      return result;
    }

    try {
      // get the current user id
      userId = SecurityUtil.getLoggedUserId();
    } catch (IllegalStateException e) {
      // no logged user

      log.warn("no user found to be assigned");

      SecurityUtil.setLoggedUser(null);

      return invocation.invoke();
    }

    // get the user object corresponding to the id
    User user = userBusiness.retrieve(userId);

    // check that user hasn't been removed during the session
    if (user == null) {
      SecurityUtil.logoutCurrentUser();
    }
    // check that user hasn't been disabled during the session
    if (!user.isEnabled()) {
      SecurityUtil.logoutCurrentUser();
    }

    // before the request:
    // set this user as the logged user
    SecurityUtil.setLoggedUser(user);

    // push current user to the value stack
    invocation.getStack().set("currentUser", user);
    invocation.getStack().set("currentUserJson", new JSONSerializer().serialize(user));

    // perform request
    String result = invocation.invoke();

    // after the request:
    // reset the logged user
    SecurityUtil.setLoggedUser(null);

    return result;
  }
  @Override
  public String intercept(ActionInvocation invocation) throws Exception {
    // System.out.println("URL: " + ServletActionContext.getRequest().getRequestURL().toString());
    HttpServletRequest req = ServletActionContext.getRequest();
    String actionName = ServletActionContext.getActionMapping().getName();

    User loggedUser =
        SecurityUtil
            .getLoggedUser(); // SecurityUtil.getLoggedUser() can't get all needed information of
                              // user -> should retrieve by making new user.
    User user = userBusiness.retrieve(loggedUser.getId());

    boolean admin = user.isAdmin();
    boolean readOnly = user.getName().equals("readonly");
    boolean access = false;

    if (admin) {
      // if admin, everything is fine
      access = true;
    } else if (readOnly) {
      // check read only operations
      if (actionName.equals("ROIterationHistoryByToken")
          || actionName.equals("ROIterationMetricsByToken")
          || actionName.equals(("ROIterationData"))) {
        access = true;
      }
    } else {
      if (actionName.equals("createTeam")
          || actionName.equals("deleteTeam")
          || actionName.equals("deleteTeamForm")
          || actionName.equals("storeTeam")
          || actionName.equals("storeNewTeam")) {

        // these are admin-only operations
        access = false;

      } else if (actionName.equals("storeUserAndRedirect")) {
        Map params = req.getParameterMap();
        boolean attemptAdmin = params.containsKey("user.admin");
        int id = Integer.parseInt(((String[]) params.get("userId"))[0]);
        if (id == user.getId() && !attemptAdmin) {
          access = true;
        }
      } else if (actionName.equals("storeUser")) {

        // check if ID is of current user, and what is being stored
        // can't set user.admin or team
        Map params = req.getParameterMap();
        boolean attemptAdmin = params.containsKey("user.admin");
        boolean attemptTeam = params.containsKey("teamsChanged") || params.containsKey("teamIds");
        int id = Integer.parseInt(((String[]) params.get("userId"))[0]);

        if (id == user.getId() && !attemptAdmin && !attemptTeam) {
          // check not setting user.admin
          access = true;
        }
      } else if (actionName.equals("storeNewUser")) {
        Map params = req.getParameterMap();
        boolean attemptToCreateNonAdmin =
            params.containsKey("user.admin")
                && ((String[]) params.get("user.admin"))[0].equals("false");
        // Non admins can create only other non admin users
        if (attemptToCreateNonAdmin) {
          // Non admins can only add new users to their teams
          if (params.containsKey("teamIds")) {
            Set<String> myTeamIds = new HashSet<String>();
            for (Team team : user.getTeams()) {
              myTeamIds.add("" + team.getId());
            }
            String[] teamIds = (String[]) params.get("teamIds");
            Set<String> newUserTeamIds = new HashSet<String>();
            for (String teamId : teamIds) {
              newUserTeamIds.add(teamId);
            }
            if (myTeamIds.containsAll(newUserTeamIds)) {
              access = true;
            }
          } else {
            access = true;
          }
        }
      } else if (actionName.equals("retrieveAllProducts")
          || actionName.equals("retrieveAllSAIterations")) {
        // access matrix operations
        access = false;
      } else if (actionName.equals("storeNewIteration") || actionName.equals("storeNewProduct")) {
        // these are operations available to everyone
        access = true;
      } else if ((actionName.equals("retrieveBranchMetrics")
              || actionName.equals("getStoryHierarchy"))
          && req.getParameterMap().containsKey("storyId")) {
        Map params = req.getParameterMap();
        int storyId = Integer.parseInt(((String[]) params.get("storyId"))[0]);
        Story story = storyBusiness.retrieve(storyId);
        if (story.getIteration() != null) {
          access =
              this.authorizationBusiness.isBacklogAccessible(story.getIteration().getId(), user);
        }
        if (!access && story.getBacklog() != null) {
          access = this.authorizationBusiness.isBacklogAccessible(story.getBacklog().getId(), user);
        }
      } else {
        // Default case: Try to find a backlog id of some kind to check.

        Map params = req.getParameterMap();
        int id = -1;
        if (params.containsKey("iterationId"))
          id = Integer.parseInt(((String[]) params.get("iterationId"))[0]);
        else if (params.containsKey("backlogId"))
          id = Integer.parseInt(((String[]) params.get("backlogId"))[0]);
        else if (params.containsKey("productId"))
          id = Integer.parseInt(((String[]) params.get("productId"))[0]);
        else if (params.containsKey("projectId"))
          id = Integer.parseInt(((String[]) params.get("projectId"))[0]);
        else if (params.containsKey("taskId")) {
          int taskId = Integer.parseInt(((String[]) params.get("taskId"))[0]);
          Task task = taskBusiness.retrieve(taskId);
          if (task.getIteration() != null) id = task.getIteration().getId();
          else if (task.getStory().getIteration() != null)
            id = task.getStory().getIteration().getId();
          else id = task.getStory().getBacklog().getId(); // story in project/product w/a iteration
        } else if (params.containsKey("storyId")) {
          int storyId = Integer.parseInt(((String[]) params.get("storyId"))[0]);
          Story story = storyBusiness.retrieve(storyId);
          if (story.getIteration() != null) {
            id = story.getIteration().getId();
          } else {
            id = story.getBacklog().getId();
          }
        }

        boolean attemptTeam = params.containsKey("teamsChanged");
        if (!attemptTeam) {
          if (id != -1
              && !(id == 0 && actionName.equals("retrieveSubBacklogs") && params.size() == 1))
            access = this.authorizationBusiness.isBacklogAccessible(id, user);
          else
            // Operations without ids must be allowed
            access = true;
        }
      }
    }

    if (access) return invocation.invoke();
    else return "noauth";
  }