// Copyright 2011 Google Inc. All Rights Reserved.
//
// 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.google.enterprise.adaptor;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;

import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;

import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;

/**
 * Tests for {@link AdministratorSecurityHandler}.
 */
public class AdministratorSecurityHandlerTest {
  private SessionManager<HttpExchange> sessionManager
      = new SessionManager<HttpExchange>(new MockTimeProvider(),
          new SessionManager.HttpExchangeClientStore(), 10000, 1000);
  private CountingHttpHandler mockHandler = new CountingHttpHandler();
  private AdministratorSecurityHandler handler
      = new AdministratorSecurityHandler(mockHandler, sessionManager,
          new MockAuthnClient());
  private MockHttpExchange ex = new MockHttpExchange("POST", "/",
      new MockHttpContext(handler, "/"));

  @Test
  public void testGet() throws Exception {
    ex = new MockHttpExchange("GET", "/", new MockHttpContext(handler, "/"));
    handler.handle(ex);
    assertEquals(403, ex.getResponseCode());
    assertEquals(0, mockHandler.getTimesExecuted());
  }

  @Test
  public void testInvalidRequest() throws Exception {
    ex.setRequestBody("not=expected&really-unexpected".getBytes("UTF-8"));
    handler.handle(ex);
    assertEquals(403, ex.getResponseCode());
    assertEquals(0, mockHandler.getTimesExecuted());
  }

  @Test
  public void testIOException() throws Exception {
    ex.setRequestBody(new InputStream() {
      @Override
      public int read() throws IOException {
        throw new IOException();
      }
    });
    handler.handle(ex);
    assertEquals(403, ex.getResponseCode());
    assertEquals(0, mockHandler.getTimesExecuted());
  }

  @Test
  public void testPasswordOnly() throws Exception {
    ex.setRequestBody("password=pass".getBytes("UTF-8"));
    handler.handle(ex);
    assertEquals(403, ex.getResponseCode());
    assertEquals(0, mockHandler.getTimesExecuted());
  }

  @Test
  public void testUsernameOnly() throws Exception {
    ex.setRequestBody("username=user".getBytes("UTF-8"));
    handler.handle(ex);
    assertEquals(403, ex.getResponseCode());
    assertEquals(0, mockHandler.getTimesExecuted());
  }

  @Test
  public void testInvalidCredentials() throws Exception {
    ex.setRequestBody("username=wrong&password=wrong".getBytes("UTF-8"));
    handler.handle(ex);
    assertEquals(403, ex.getResponseCode());
    assertEquals(0, mockHandler.getTimesExecuted());
  }

  @Test
  public void testInvalidTestErrorCredentials() throws Exception {
    ex.setRequestBody("username=cause&password=error".getBytes("UTF-8"));
    handler.handle(ex);
    assertEquals(403, ex.getResponseCode());
    assertEquals(0, mockHandler.getTimesExecuted());
  }

  @Test
  public void testValidCredentials() throws Exception {
    ex.setRequestBody("username=user&password=pass".getBytes("UTF-8"));
    handler.handle(ex);
    assertEquals(303, ex.getResponseCode());
    assertEquals(0, mockHandler.getTimesExecuted());
    String cookie = ex.getResponseHeaders().getFirst("Set-Cookie")
        .split(";")[0];

    ex = new MockHttpExchange("GET", "/", new MockHttpContext(handler, "/"));
    ex.getRequestHeaders().set("Cookie", cookie);
    handler.handle(ex);
    assertEquals(200, ex.getResponseCode());
    assertEquals(1, mockHandler.getTimesExecuted());
  }

  @Test
  public void testPreexistingSession() throws Exception {
    HttpExchange tmpEx = new MockHttpExchange("GET", "/",
      new MockHttpContext(handler, "/"));
    // Create session
    sessionManager.getSession(tmpEx, true);
    String cookie = tmpEx.getResponseHeaders().getFirst("Set-Cookie")
        .split(";")[0];

    ex.getRequestHeaders().set("Cookie", cookie);
    assertNotNull(sessionManager.getSession(ex, false));
    handler.handle(ex);
    assertEquals(403, ex.getResponseCode());
    assertEquals(0, mockHandler.getTimesExecuted());
  }

  private class MockAuthnClient implements
      AdministratorSecurityHandler.AuthnClient {
    @Override
    public AuthzStatus authn(String username, String password) {
      if ("user".equals(username) && "pass".equals(password)) {
        return AuthzStatus.PERMIT;
      } else if ("cause".equals(username) && "error".equals(password)) {
        return AuthzStatus.INDETERMINATE;
      } else {
        return AuthzStatus.DENY;
      }
    }
  }

  private static class CountingHttpHandler implements HttpHandler {
    private int executed;

    @Override
    public void handle(HttpExchange ex) throws IOException {
      executed++;
      ex.sendResponseHeaders(200, -1);
    }

    public int getTimesExecuted() {
      return executed;
    }
  }
}
