@Test
  @LocalData
  public void testLoadOnStart() throws Exception {
    // verify that SpecificUserAuthorizationStrategy is loaded correctly from the disk on startup.
    {
      FreeStyleProject p = j.jenkins.getItemByFullName("test", FreeStyleProject.class);
      assertNotNull(p);
      AuthorizeProjectProperty prop = p.getProperty(AuthorizeProjectProperty.class);
      assertNotNull(prop);
      assertEquals(SpecificUsersAuthorizationStrategy.class, prop.getStrategy().getClass());
      SpecificUsersAuthorizationStrategy strategy =
          (SpecificUsersAuthorizationStrategy) prop.getStrategy();
      assertEquals("test1", strategy.getUserid());
    }

    j.jenkins.reload();

    // verify that SpecificUserAuthorizationStrategy is reloaded correctly from the disk.
    {
      FreeStyleProject p = j.jenkins.getItemByFullName("test", FreeStyleProject.class);
      assertNotNull(p);
      AuthorizeProjectProperty prop = p.getProperty(AuthorizeProjectProperty.class);
      assertNotNull(prop);
      assertEquals(SpecificUsersAuthorizationStrategy.class, prop.getStrategy().getClass());
      SpecificUsersAuthorizationStrategy strategy =
          (SpecificUsersAuthorizationStrategy) prop.getStrategy();
      assertEquals("test1", strategy.getUserid());
    }
  }
  @Test
  public void testRestInterfaceSuccess() throws Exception {
    prepareSecurity();

    FreeStyleProject srcProject = j.createFreeStyleProject();
    srcProject.addProperty(
        new AuthorizeProjectProperty(new SpecificUsersAuthorizationStrategy("test1", false)));
    srcProject.save();

    WebClient wc = j.createWebClient();
    wc.login("test1", "test1");

    // GET config.xml of srcProject (userid is set to test1)
    String configXml =
        getConfigXml(wc.goToXml(String.format("%s/config.xml", srcProject.getUrl())));

    // POST config.xml of srcProject (userid is set to test1) to a new project.
    // This should success.
    FreeStyleProject destProject = j.createFreeStyleProject();
    destProject.save();
    String projectName = destProject.getFullName();

    WebRequestSettings req =
        new WebRequestSettings(
            wc.createCrumbedUrl(String.format("%s/config.xml", destProject.getUrl())),
            HttpMethod.POST);
    req.setRequestBody(configXml);
    wc.getPage(req);

    {
      FreeStyleProject p = j.jenkins.getItemByFullName(projectName, FreeStyleProject.class);
      assertNotNull(p);
      AuthorizeProjectProperty prop = p.getProperty(AuthorizeProjectProperty.class);
      assertNotNull(prop);
      assertEquals(SpecificUsersAuthorizationStrategy.class, prop.getStrategy().getClass());
      SpecificUsersAuthorizationStrategy strategy =
          (SpecificUsersAuthorizationStrategy) prop.getStrategy();
      assertEquals("test1", strategy.getUserid());
    }

    j.jenkins.reload();

    {
      FreeStyleProject p = j.jenkins.getItemByFullName(projectName, FreeStyleProject.class);
      assertNotNull(p);
      AuthorizeProjectProperty prop = p.getProperty(AuthorizeProjectProperty.class);
      assertNotNull(prop);
      assertEquals(SpecificUsersAuthorizationStrategy.class, prop.getStrategy().getClass());
      SpecificUsersAuthorizationStrategy strategy =
          (SpecificUsersAuthorizationStrategy) prop.getStrategy();
      assertEquals("test1", strategy.getUserid());
    }
  }
  @Test
  public void testRestInterfaceFailure() throws Exception {
    prepareSecurity();

    FreeStyleProject srcProject = j.createFreeStyleProject();
    srcProject.addProperty(
        new AuthorizeProjectProperty(new SpecificUsersAuthorizationStrategy("admin", false)));
    srcProject.save();

    WebClient wc = j.createWebClient();
    wc.login("test1", "test1");

    // GET config.xml of srcProject (userid is set to admin)
    String configXml =
        getConfigXml(wc.goToXml(String.format("%s/config.xml", srcProject.getUrl())));

    // POST config.xml of srcProject (userid is set to admin) to a new project.
    // This should fail.
    FreeStyleProject destProject = j.createFreeStyleProject();
    destProject.save();
    String projectName = destProject.getFullName();

    WebRequestSettings req =
        new WebRequestSettings(
            wc.createCrumbedUrl(String.format("%s/config.xml", destProject.getUrl())),
            HttpMethod.POST);
    req.setRequestBody(configXml);

    try {
      wc.getPage(req);
      fail();
    } catch (FailingHttpStatusCodeException e) {
    }

    {
      FreeStyleProject p = j.jenkins.getItemByFullName(projectName, FreeStyleProject.class);
      assertNotNull(p);
      AuthorizeProjectProperty prop = p.getProperty(AuthorizeProjectProperty.class);
      assertTrue(prop == null || prop.getStrategy() == null);
    }

    j.jenkins.reload();

    {
      FreeStyleProject p = j.jenkins.getItemByFullName(projectName, FreeStyleProject.class);
      assertNotNull(p);
      AuthorizeProjectProperty prop = p.getProperty(AuthorizeProjectProperty.class);
      assertTrue(prop == null || prop.getStrategy() == null);
    }
  }
  @Test
  public void testConfigurationAuthentication() throws Exception {
    prepareSecurity();

    FreeStyleProject p = j.createFreeStyleProject();

    WebClient wc = j.createWebClient();
    wc.login("test1");

    // Reauthentication is not required if No need for re-authentication is checked
    p.addProperty(
        new AuthorizeProjectProperty(new SpecificUsersAuthorizationStrategy("admin", true)));
    j.submit(wc.getPage(p, "configure").getFormByName("config"));

    // Reauthentication is required if No need for re-authentication is checked
    p.removeProperty(AuthorizeProjectProperty.class);
    p.addProperty(
        new AuthorizeProjectProperty(new SpecificUsersAuthorizationStrategy("admin", false)));
    try {
      j.submit(wc.getPage(p, "configure").getFormByName("config"));
      fail();
    } catch (FailingHttpStatusCodeException e) {
      assertEquals(400, e.getStatusCode());
    }

    // No authentication is required if oneself.
    {
      HtmlPage page = wc.getPage(p, "configure");
      HtmlTextInput userid =
          page.<HtmlTextInput>getFirstByXPath(
              "//*[contains(@class, 'specific-user-authorization')]//input[contains(@name, 'userid') and @type='text']");
      userid.setValueAttribute("test1");
      j.submit(page.getFormByName("config"));

      assertEquals(
          "test1",
          ((SpecificUsersAuthorizationStrategy)
                  p.getProperty(AuthorizeProjectProperty.class).getStrategy())
              .getUserid());
    }

    // Reauthentication is required to change userid even if No need for re-authentication is
    // checked
    p.addProperty(
        new AuthorizeProjectProperty(new SpecificUsersAuthorizationStrategy("admin", true)));
    {
      HtmlPage page = wc.getPage(p, "configure");
      HtmlTextInput userid =
          page.<HtmlTextInput>getFirstByXPath(
              "//*[contains(@class, 'specific-user-authorization')]//input[contains(@name, 'userid') and @type='text']");
      userid.setValueAttribute("test2");
      try {
        j.submit(page.getFormByName("config"));
        fail();
      } catch (FailingHttpStatusCodeException e) {
        assertEquals(400, e.getStatusCode());
      }
    }
  }
  @Test
  public void testConfigureApitoken() throws Exception {
    prepareSecurity();

    FreeStyleProject p = j.createFreeStyleProject();
    p.addProperty(
        new AuthorizeProjectProperty(new SpecificUsersAuthorizationStrategy("test2", false)));

    WebClient wc = j.createWebClient();
    wc.login("test1");

    String apitokenForTest2 = User.get("test2").getProperty(ApiTokenProperty.class).getApiToken();
    assertNotNull(apitokenForTest2);
    assertNotEquals("", apitokenForTest2);

    // authentication fails without apitoken
    {
      HtmlPage page = wc.getPage(p, "configure");
      HtmlCheckBoxInput useApitoken =
          page.<HtmlCheckBoxInput>getFirstByXPath(
              "//*[contains(@class, 'specific-user-authorization')]//input[contains(@name, 'useApitoken') and @type='checkbox']");
      useApitoken.setChecked(true);
      try {
        j.submit(page.getFormByName("config"));
        fail();
      } catch (FailingHttpStatusCodeException e) {
        assertEquals(400, e.getStatusCode());
      }
    }

    // authentication succeeds with the good apitoken
    {
      HtmlPage page = wc.getPage(p, "configure");
      HtmlCheckBoxInput useApitoken =
          page.<HtmlCheckBoxInput>getFirstByXPath(
              "//*[contains(@class, 'specific-user-authorization')]//input[contains(@name, 'useApitoken') and @type='checkbox']");
      useApitoken.setChecked(true);
      HtmlTextInput apitoken =
          page.<HtmlTextInput>getFirstByXPath(
              "//*[contains(@class, 'specific-user-authorization')]//input[contains(@name, 'apitoken') and @type='text']");
      apitoken.setValueAttribute(apitokenForTest2);
      j.submit(page.getFormByName("config"));

      assertEquals(
          "test2",
          ((SpecificUsersAuthorizationStrategy)
                  p.getProperty(AuthorizeProjectProperty.class).getStrategy())
              .getUserid());
    }

    // authentication fails with a bad apitoken
    {
      HtmlPage page = wc.getPage(p, "configure");
      HtmlCheckBoxInput useApitoken =
          page.<HtmlCheckBoxInput>getFirstByXPath(
              "//*[contains(@class, 'specific-user-authorization')]//input[contains(@name, 'useApitoken') and @type='checkbox']");
      useApitoken.setChecked(true);
      HtmlTextInput apitoken =
          page.<HtmlTextInput>getFirstByXPath(
              "//*[contains(@class, 'specific-user-authorization')]//input[contains(@name, 'apitoken') and @type='text']");
      apitoken.setValueAttribute(apitokenForTest2 + "xxx");
      try {
        j.submit(page.getFormByName("config"));
        fail();
      } catch (FailingHttpStatusCodeException e) {
        assertEquals(400, e.getStatusCode());
      }
    }

    // authentication fails if the apitoken is used for password
    {
      HtmlPage page = wc.getPage(p, "configure");
      HtmlCheckBoxInput useApitoken =
          page.<HtmlCheckBoxInput>getFirstByXPath(
              "//*[contains(@class, 'specific-user-authorization')]//input[contains(@name, 'useApitoken') and @type='checkbox']");
      useApitoken.setChecked(false);
      HtmlPasswordInput password =
          page.<HtmlPasswordInput>getFirstByXPath(
              "//*[contains(@class, 'specific-user-authorization')]//input[contains(@name, 'password') and @type='password']");
      password.setValueAttribute(apitokenForTest2);
      HtmlTextInput apitoken =
          page.<HtmlTextInput>getFirstByXPath(
              "//*[contains(@class, 'specific-user-authorization')]//input[contains(@name, 'apitoken') and @type='text']");
      apitoken.setValueAttribute(apitokenForTest2);
      try {
        j.submit(page.getFormByName("config"));
        fail();
      } catch (FailingHttpStatusCodeException e) {
        assertEquals(400, e.getStatusCode());
      }
    }
  }
  @Test
  public void testCliFailure() throws Exception {
    prepareSecurity();

    FreeStyleProject srcProject = j.createFreeStyleProject();
    srcProject.addProperty(
        new AuthorizeProjectProperty(new SpecificUsersAuthorizationStrategy("admin", false)));
    srcProject.save();

    WebClient wc = j.createWebClient();
    wc.login("test1", "test1");

    // GET config.xml of srcProject (userid is set to admin)
    String configXml = null;
    {
      CLI cli = new CLI(j.getURL());
      ByteArrayOutputStream stdout = new ByteArrayOutputStream();
      ByteArrayOutputStream stderr = new ByteArrayOutputStream();
      int ret =
          cli.execute(
              Arrays.asList(
                  "get-job",
                  srcProject.getFullName(),
                  "--username",
                  "test1",
                  "--password",
                  "test1"),
              new NullInputStream(0),
              stdout,
              stderr);
      assertEquals(stderr.toString(), 0, ret);
      configXml = stdout.toString();
    }

    // POST config.xml of srcProject (userid is set to admin) to a new project.
    // This should fail.
    FreeStyleProject destProject = j.createFreeStyleProject();
    destProject.save();
    String projectName = destProject.getFullName();

    {
      CLI cli = new CLI(j.getURL());
      ByteArrayOutputStream stdout = new ByteArrayOutputStream();
      ByteArrayOutputStream stderr = new ByteArrayOutputStream();
      int ret =
          cli.execute(
              Arrays.asList(
                  "update-job",
                  destProject.getFullName(),
                  "--username",
                  "test1",
                  "--password",
                  "test1"),
              new ByteArrayInputStream(configXml.getBytes()),
              stdout,
              stderr);
      assertNotEquals(0, ret);
    }

    {
      FreeStyleProject p = j.jenkins.getItemByFullName(projectName, FreeStyleProject.class);
      assertNotNull(p);
      AuthorizeProjectProperty prop = p.getProperty(AuthorizeProjectProperty.class);
      assertTrue(prop == null || prop.getStrategy() == null);
    }

    j.jenkins.reload();

    {
      FreeStyleProject p = j.jenkins.getItemByFullName(projectName, FreeStyleProject.class);
      assertNotNull(p);
      AuthorizeProjectProperty prop = p.getProperty(AuthorizeProjectProperty.class);
      assertTrue(prop == null || prop.getStrategy() == null);
    }
  }