123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276 |
- /*
- * EliasDB
- *
- * Copyright 2016 Matthias Ladkau. All rights reserved.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- */
- package ac
- import (
- "bytes"
- "encoding/json"
- "flag"
- "fmt"
- "io/ioutil"
- "net/http"
- "os"
- "strings"
- "sync"
- "testing"
- "devt.de/krotik/common/datautil"
- "devt.de/krotik/common/errorutil"
- "devt.de/krotik/common/httputil"
- "devt.de/krotik/common/httputil/access"
- "devt.de/krotik/common/httputil/auth"
- "devt.de/krotik/common/stringutil"
- "devt.de/krotik/eliasdb/api"
- )
- const TESTPORT = ":9090"
- // Main function for all tests in this package
- func TestMain(m *testing.M) {
- var err error
- flag.Parse()
- hs, wg := startServer()
- if hs == nil {
- return
- }
- // Disable access logging
- LogAccess = func(v ...interface{}) {}
- // Register public endpoints
- api.RegisterRestEndpoints(PublicAccessControlEndpointMap)
- // Initialise auth handler
- AuthHandler = auth.NewCookieAuthHandleFuncWrapper(http.HandleFunc)
- // Important statement! - all registered endpoints afterwards
- // are subject to access control
- api.HandleFunc = AuthHandler.HandleFunc
- // Register management endpoints
- api.RegisterRestEndpoints(AccessManagementEndpointMap)
- // Register dummy page
- api.HandleFunc("/foo", func(w http.ResponseWriter, r *http.Request) {
- w.Write([]byte("foobar!"))
- })
- // Initialise user DB
- UserDB, err = datautil.NewEnforcedUserDB("test_user.db", "")
- errorutil.AssertOk(err)
- // Put the UserDB in charge of verifying passwords
- AuthHandler.SetAuthFunc(UserDB.CheckUserPassword)
- // Initialise ACL's
- var conf map[string]interface{}
- errorutil.AssertOk(json.Unmarshal(stringutil.StripCStyleComments(DefaultAccessDB), &conf))
- at, err := access.NewMemoryACLTableFromConfig(conf)
- errorutil.AssertOk(err)
- InitACLs(at)
- // Connect the ACL object to the AuthHandler - this provides authorization for users
- AuthHandler.SetAccessFunc(ACL.CheckHTTPRequest)
- // Adding special handlers which redirect to the login page
- AuthHandler.CallbackSessionExpired = CallbackSessionExpired
- AuthHandler.CallbackUnauthorized = CallbackUnauthorized
- // Add users
- UserDB.UserDB.AddUserEntry("elias", "elias", nil)
- UserDB.UserDB.AddUserEntry("johndoe", "doe", nil)
- UserDB.UserDB.AddUserEntry("guest", "g", nil)
- // Disable debounce time for unit tests
- DebounceTime = 0
- // Run the tests
- res := m.Run()
- // Teardown
- stopServer(hs, wg)
- // Stop ACL monitoring
- ACL.Close()
- // Remove files
- os.Remove("test_user.db")
- os.Exit(res)
- }
- func TestSwaggerDefs(t *testing.T) {
- // Test we can build swagger defs from the endpoint
- data := map[string]interface{}{
- "paths": map[string]interface{}{},
- "definitions": map[string]interface{}{},
- }
- for _, inst := range PublicAccessControlEndpointMap {
- inst().SwaggerDefs(data)
- }
- for _, inst := range AccessManagementEndpointMap {
- inst().SwaggerDefs(data)
- }
- }
- /*
- Start a HTTP test server.
- */
- func startServer() (*httputil.HTTPServer, *sync.WaitGroup) {
- hs := &httputil.HTTPServer{}
- var wg sync.WaitGroup
- wg.Add(1)
- go hs.RunHTTPServer(TESTPORT, &wg)
- wg.Wait()
- // Server is started
- if hs.LastError != nil {
- panic(hs.LastError)
- }
- return hs, &wg
- }
- /*
- Stop a started HTTP test server.
- */
- func stopServer(hs *httputil.HTTPServer, wg *sync.WaitGroup) {
- if hs.Running == true {
- wg.Add(1)
- // Server is shut down
- hs.Shutdown()
- wg.Wait()
- } else {
- panic("Server was not running as expected")
- }
- }
- /*
- Send a request to a HTTP test server
- */
- func sendTestRequest(contentType string, url string, method string, content []byte,
- reqMod func(*http.Request)) string {
- body, _ := sendTestRequestResponse(contentType, url, method, content, reqMod)
- return body
- }
- /*
- Send a request to a HTTP test server
- */
- func sendTestRequestResponse(contentType string, url string, method string,
- content []byte, reqMod func(*http.Request)) (string, *http.Response) {
- var req *http.Request
- var err error
- if content != nil {
- req, err = http.NewRequest(method, url, bytes.NewBuffer(content))
- } else {
- req, err = http.NewRequest(method, url, nil)
- }
- if err != nil {
- panic(err)
- }
- req.Header.Set("Content-Type", contentType)
- if reqMod != nil {
- reqMod(req)
- }
- client := &http.Client{}
- resp, err := client.Do(req)
- if err != nil {
- panic(err)
- }
- defer resp.Body.Close()
- body, _ := ioutil.ReadAll(resp.Body)
- bodyStr := strings.Trim(string(body), " \n")
- // Try json decoding first
- out := bytes.Buffer{}
- err = json.Indent(&out, []byte(bodyStr), "", " ")
- if err == nil {
- return out.String(), resp
- }
- // Just return the body
- return bodyStr, resp
- }
- /*
- Perform authentication and retrieve an auth cookie
- */
- func doAuth(user, pass string) *http.Cookie {
- queryURL := "http://localhost" + TESTPORT
- // Send authentication request with correct credentials
- res, resp := sendTestRequestResponse("application/json", queryURL+EndpointLogin, "POST", []byte(`
- {
- "user" : "`+user+`",
- "pass" : "`+pass+`"
- }
- `), nil)
- errorutil.AssertTrue(len(resp.Cookies()) > 0, res)
- // Right after authentication we only have the authentication cookie - after
- // the first visit to a non-public page we will also have a session cookie
- authCookie := resp.Cookies()[0]
- errorutil.AssertTrue(authCookie.Name == "~aid",
- fmt.Sprint("Unexpected name for cookie:", authCookie))
- return authCookie
- }
|