/**
  * Retrieve list of iBIOMES users.
  *
  * @param usertype User type (admins, users, or groups)
  * @return User list
  * @throws JargonException
  * @throws IOException
  * @throws Exception
  */
 @RequestMapping(value = "/services/users", method = RequestMethod.GET)
 @ResponseBody
 public UserListMetadata getUsers() throws JargonException, IOException {
   IRODSAccount irodsAccount =
       (IRODSAccount) request.getSession().getAttribute("SPRING_SECURITY_CONTEXT");
   UserAO userAO = irodsAccessObjectFactory.getUserAO(irodsAccount);
   UserListMetadata users = new UserListMetadata(userAO.findAll());
   return users;
 }
 /**
  * Retrieve info for particular iBIOMES user.
  *
  * @param headers
  * @param username
  * @return
  * @throws IOException
  * @throws JargonException
  */
 @RequestMapping(value = "/services/users/{username}", method = RequestMethod.GET)
 @ResponseBody
 public UserMetadata getUser(@PathVariable("username") String username)
     throws JargonException, IOException {
   IRODSAccount irodsAccount =
       (IRODSAccount) request.getSession().getAttribute("SPRING_SECURITY_CONTEXT");
   UserAO userAO = irodsAccessObjectFactory.getUserAO(irodsAccount);
   UserMetadata user = new UserMetadata(userAO.findByName(username));
   return user;
 }
  /**
   * Update user password.
   *
   * @param headers
   * @param username
   * @return
   * @throws IOException
   * @throws JargonException
   */
  @RequestMapping(value = "/services/users/{username}/updatepwd", method = RequestMethod.GET)
  @ResponseBody
  public IBIOMESResponse updateUserPassword(
      @PathVariable("username") String username,
      @RequestParam("oldPwd") String oldPwd,
      @RequestParam("newPwd") String newPwd)
      throws JargonException, IOException {
    IRODSAccount irodsAccount =
        (IRODSAccount) request.getSession().getAttribute("SPRING_SECURITY_CONTEXT");
    UserAO userAO = irodsAccessObjectFactory.getUserAO(irodsAccount);
    try {
      userAO.changeAUserPasswordByThatUser(username, oldPwd, newPwd);

      // create new iRODS account object to reflect changes
      IRODSAccount newAccount =
          IRODSAccount.instance(
              irodsAccount.getHost(),
              irodsAccount.getPort(),
              irodsAccount.getUserName(),
              newPwd,
              irodsAccount.getHomeDirectory(),
              irodsAccount.getZone(),
              irodsAccount.getDefaultStorageResource());

      IRODSSession session = irodsAccessObjectFactory.getIrodsSession();

      // TODO UPDATE SESSION INFO!!! OR SOEMTHING WRONG HERE...

      AuthResponse authResponse = null;
      IRODSAccessObjectFactory accessAO = IRODSAccessObjectFactoryImpl.instance(session);
      try {
        request.getSession().removeAttribute("SPRING_SECURITY_CONTEXT");
        authResponse = accessAO.authenticateIRODSAccount(newAccount);
        session.currentConnection(authResponse.getAuthenticatedIRODSAccount());
        request
            .getSession()
            .setAttribute("SPRING_SECURITY_CONTEXT", authResponse.getAuthenticatedIRODSAccount());
      } catch (JargonException e) {
        e.printStackTrace();
        return new IBIOMESResponse(
            false,
            "Cannot update session information. Exception: " + e.getLocalizedMessage(),
            null);
      }

    } catch (AuthenticationException exc) {
      return new IBIOMESResponse(false, "Current password is not correct", null);
    }

    return new IBIOMESResponse(true, "Password successfully updated", null);
  }
 /**
  * Create temporary user password.
  *
  * @return
  * @throws JargonException
  */
 @RequestMapping(value = "/services/user/getTmpPassword", method = RequestMethod.GET)
 @ResponseBody
 public IBIOMESResponse getTemporaryPassword() throws JargonException {
   IRODSAccount irodsAccount =
       (IRODSAccount) request.getSession().getAttribute("SPRING_SECURITY_CONTEXT");
   if (irodsAccount.isAnonymousAccount()) {
     return new IBIOMESResponse(true, "", "");
   } else {
     UserAO userAO = irodsAccessObjectFactory.getUserAO(irodsAccount);
     try {
       String password = userAO.getTemporaryPasswordForConnectedUser();
       return new IBIOMESResponse(true, "", password);
     } catch (AuthenticationException exc) {
       return new IBIOMESResponse(
           false,
           "Could not generate temporary password for user '" + irodsAccount.getUserName() + "'",
           null);
     }
   }
 }
  @Test
  public void testAddUserDuplicateByAdmin() throws Exception {

    String testUser = "******";
    String testPassword = "******";
    IRODSAccount irodsAccount =
        testingPropertiesHelper.buildIRODSAccountFromTestProperties(testingProperties);

    IRODSAccessObjectFactory accessObjectFactory = irodsFileSystem.getIRODSAccessObjectFactory();

    UserAO userAO = accessObjectFactory.getUserAO(irodsAccount);
    userAO.deleteUser(testUser);
    User user = new User();
    user.setName(testUser);
    user.setUserType(UserTypeEnum.RODS_USER);
    userAO.addUser(user);

    StringBuilder sb = new StringBuilder();
    sb.append("http://localhost:");
    sb.append(
        testingPropertiesHelper.getPropertyValueAsInt(
            testingProperties, RestTestingProperties.REST_PORT_PROPERTY));
    sb.append("/user/");

    DefaultHttpClientAndContext clientAndContext =
        RestAuthUtils.httpClientSetup(irodsAccount, testingProperties);
    try {

      HttpPut httpPut = new HttpPut(sb.toString());
      httpPut.addHeader("accept", "application/json");
      httpPut.addHeader("Content-Type", "application/json");

      ObjectMapper mapper = new ObjectMapper();
      UserAddByAdminRequest addRequest = new UserAddByAdminRequest();
      addRequest.setDistinguishedName("dn here");
      addRequest.setTempPassword(testPassword);
      addRequest.setUserName(testUser);
      String body = mapper.writeValueAsString(addRequest);

      System.out.println(body);

      httpPut.setEntity(new StringEntity(body));

      HttpResponse response =
          clientAndContext.getHttpClient().execute(httpPut, clientAndContext.getHttpContext());
      HttpEntity entity = response.getEntity();
      Assert.assertEquals(200, response.getStatusLine().getStatusCode());
      String entityData = EntityUtils.toString(entity);

      System.out.println(entityData);

      UserAddActionResponse actual = mapper.readValue(entityData, UserAddActionResponse.class);
      Assert.assertEquals(testUser, actual.getUserName());
      Assert.assertEquals(
          UserAddActionResponse.UserAddActionResponseCode.USER_NAME_IS_TAKEN,
          actual.getUserAddActionResponse());
      Assert.assertEquals(
          UserAddActionResponse.UserAddActionResponseCode.USER_NAME_IS_TAKEN.ordinal(),
          actual.getUserAddActionResponseNumericCode());

    } finally {
      // When HttpClient instance is no longer needed,
      // shut down the connection manager to ensure
      // immediate deallocation of all system resources
      clientAndContext.getHttpClient().getConnectionManager().shutdown();
    }
  }
  @Test
  public void testAddUserByAdminLongDn() throws Exception {

    String testUser = "******";
    String testPassword = "******";
    String testDN =
        "/CN=xxxxxyyxx-64f0-4d49-a0a9-508a8a5328cd/emailAddress=xxxxxxxxxxthismaynotshowup";
    IRODSAccount irodsAccount =
        testingPropertiesHelper.buildIRODSAccountFromTestProperties(testingProperties);

    IRODSAccount userAccount =
        testingPropertiesHelper.buildIRODSAccountForIRODSUserFromTestPropertiesForGivenUser(
            testingProperties, testUser, testPassword);

    IRODSAccessObjectFactory accessObjectFactory = irodsFileSystem.getIRODSAccessObjectFactory();

    UserAO userAO = accessObjectFactory.getUserAO(irodsAccount);

    try {
      userAO.findByName(testUser);
      String homeDir = MiscIRODSUtils.computeHomeDirectoryForIRODSAccount(userAccount);
      IRODSFile userHomeDir =
          irodsFileSystem.getIRODSFileFactory(userAccount).instanceIRODSFile(homeDir);

      for (File homeDirFile : userHomeDir.listFiles()) {
        homeDirFile.delete();
      }
      userAO.deleteUser(testUser);

    } catch (DataNotFoundException dnf) {
      // OK
    }

    StringBuilder sb = new StringBuilder();
    sb.append("http://localhost:");
    sb.append(
        testingPropertiesHelper.getPropertyValueAsInt(
            testingProperties, RestTestingProperties.REST_PORT_PROPERTY));
    sb.append("/user/");

    DefaultHttpClientAndContext clientAndContext =
        RestAuthUtils.httpClientSetup(irodsAccount, testingProperties);
    try {

      HttpPut httpPut = new HttpPut(sb.toString());
      httpPut.addHeader("accept", "application/json");
      httpPut.addHeader("Content-Type", "application/json");

      ObjectMapper mapper = new ObjectMapper();
      UserAddByAdminRequest addRequest = new UserAddByAdminRequest();
      addRequest.setDistinguishedName(testDN);
      addRequest.setTempPassword(testPassword);
      addRequest.setUserName(testUser);
      String body = mapper.writeValueAsString(addRequest);

      System.out.println(body);

      httpPut.setEntity(new StringEntity(body));

      HttpResponse response =
          clientAndContext.getHttpClient().execute(httpPut, clientAndContext.getHttpContext());
      HttpEntity entity = response.getEntity();
      Assert.assertEquals(200, response.getStatusLine().getStatusCode());
      String entityData = EntityUtils.toString(entity);

      System.out.println(entityData);

      UserAddActionResponse actual = mapper.readValue(entityData, UserAddActionResponse.class);
      Assert.assertEquals(testUser, actual.getUserName());
      Assert.assertEquals(
          UserAddActionResponse.UserAddActionResponseCode.SUCCESS,
          actual.getUserAddActionResponse());
      Assert.assertEquals(
          UserAddActionResponse.UserAddActionResponseCode.SUCCESS.ordinal(),
          actual.getUserAddActionResponseNumericCode());

    } finally {
      // When HttpClient instance is no longer needed,
      // shut down the connection manager to ensure
      // immediate deallocation of all system resources
      clientAndContext.getHttpClient().getConnectionManager().shutdown();
    }

    User user = userAO.findByName(testUser);
    Assert.assertNotNull("user not added", user);
    Assert.assertEquals("dn not set", testDN, user.getUserDN());
  }