package basic

import (
	"encoding/base64"
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/docker/distribution/registry/auth"
	"golang.org/x/net/context"
)

func TestBasicAccessController(t *testing.T) {

	testRealm := "The-Shire"
<<<<<<< HEAD
	testUsers := []string{"bilbo", "frodo", "MiShil", "DeokMan"}
	testPasswords := []string{"baggins", "baggins", "새주", "공주님"}
	testHtpasswdContent := `bilbo:{SHA}5siv5c0SHx681xU6GiSx9ZQryqs=
							frodo:$2y$05$926C3y10Quzn/LnqQH86VOEVh/18T6RnLaS.khre96jLNL/7e.K5W
							MiShil:$2y$05$0oHgwMehvoe8iAWS8I.7l.KoECXrwVaC16RPfaSCU5eVTFrATuMI2
							DeokMan:공주님`
=======
	testUser := "bilbo"
	testHtpasswdContent := "bilbo:{SHA}5siv5c0SHx681xU6GiSx9ZQryqs="
>>>>>>> Implementation of a basic authentication scheme using standard .htpasswd files

	tempFile, err := ioutil.TempFile("", "htpasswd-test")
	if err != nil {
		t.Fatal("could not create temporary htpasswd file")
	}
	if _, err = tempFile.WriteString(testHtpasswdContent); err != nil {
		t.Fatal("could not write temporary htpasswd file")
	}

	options := map[string]interface{}{
		"realm": testRealm,
		"path":  tempFile.Name(),
	}

	accessController, err := newAccessController(options)
	if err != nil {
		t.Fatal("error creating access controller")
	}

	tempFile.Close()

<<<<<<< HEAD
	var userNumber = 0

=======
>>>>>>> Implementation of a basic authentication scheme using standard .htpasswd files
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		ctx := context.WithValue(nil, "http.request", r)
		authCtx, err := accessController.Authorized(ctx)
		if err != nil {
			switch err := err.(type) {
			case auth.Challenge:
				err.ServeHTTP(w, r)
				return
			default:
				t.Fatalf("unexpected error authorizing request: %v", err)
			}
		}

		userInfo, ok := authCtx.Value("auth.user").(auth.UserInfo)
		if !ok {
			t.Fatal("basic accessController did not set auth.user context")
		}

<<<<<<< HEAD
		if userInfo.Name != testUsers[userNumber] {
			t.Fatalf("expected user name %q, got %q", testUsers[userNumber], userInfo.Name)
=======
		if userInfo.Name != testUser {
			t.Fatalf("expected user name %q, got %q", testUser, userInfo.Name)
>>>>>>> Implementation of a basic authentication scheme using standard .htpasswd files
		}

		w.WriteHeader(http.StatusNoContent)
	}))

	client := &http.Client{
		CheckRedirect: nil,
	}

	req, _ := http.NewRequest("GET", server.URL, nil)
	resp, err := client.Do(req)

	if err != nil {
		t.Fatalf("unexpected error during GET: %v", err)
	}
	defer resp.Body.Close()

	// Request should not be authorized
	if resp.StatusCode != http.StatusUnauthorized {
		t.Fatalf("unexpected non-fail response status: %v != %v", resp.StatusCode, http.StatusUnauthorized)
	}

<<<<<<< HEAD
	for i := 0; i < len(testUsers); i++ {
		userNumber = i
		req, _ = http.NewRequest("GET", server.URL, nil)
		sekrit := testUsers[i] + ":" + testPasswords[i]
		credential := "Basic " + base64.StdEncoding.EncodeToString([]byte(sekrit))

		req.Header.Set("Authorization", credential)
		resp, err = client.Do(req)

		if err != nil {
			t.Fatalf("unexpected error during GET: %v", err)
		}
		defer resp.Body.Close()

		// Request should be authorized
		if resp.StatusCode != http.StatusNoContent {
			t.Fatalf("unexpected non-success response status: %v != %v for %s %s %s", resp.StatusCode, http.StatusNoContent, testUsers[i], testPasswords[i], credential)
		}
=======
	req, _ = http.NewRequest("GET", server.URL, nil)

	sekrit := "bilbo:baggins"
	credential := "Basic " + base64.StdEncoding.EncodeToString([]byte(sekrit))

	req.Header.Set("Authorization", credential)
	resp, err = client.Do(req)

	if err != nil {
		t.Fatalf("unexpected error during GET: %v", err)
	}
	defer resp.Body.Close()

	// Request should be authorized
	if resp.StatusCode != http.StatusNoContent {
		t.Fatalf("unexpected non-success response status: %v != %v", resp.StatusCode, http.StatusNoContent)
>>>>>>> Implementation of a basic authentication scheme using standard .htpasswd files
	}

}
