// 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.*;

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

import org.junit.Test;

import java.io.*;

/**
 * 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;
    }
  }
}
