Newer
Older
package rootmux
import (
"encoding/json"
"io/ioutil"
"net/http"
"net/http/cookiejar"
"net/http/httptest"
"net/url"
"os"
"regexp"
"testing"
"forge.grandlyon.com/apoyen/elections/internal/auth"
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
"forge.grandlyon.com/apoyen/sdk-go/pkg/tester"
"forge.grandlyon.com/apoyen/sdk-go/pkg/tokens"
"forge.grandlyon.com/apoyen/elections/internal/mocks"
)
var (
reg, _ = regexp.Compile("[\n \t]+")
initialUsersBuff, _ = ioutil.ReadFile("../../configs/users.json")
initialUsers = reg.ReplaceAllString(string(initialUsersBuff), "")
newUser = `{"id":"3","login":"new_user","memberOf":["USERS"],"password":"test"}`
noH = tester.Header{Key: "", Value: ""}
)
func init() {
tokens.Init("../../configs/tokenskey.json", true)
}
func TestAll(t *testing.T) {
os.Mkdir("data", os.ModePerm)
os.Create("./data/test.db")
os.Link("../../data/users.db", "./data/users.db")
// Create the mock OAuth2 server
oAuth2Server := httptest.NewServer(mocks.CreateMockOAuth2())
defer oAuth2Server.Close()
// Create the mock API server
go http.ListenAndServe(":8091", mocks.CreateMockAPI())
// Set the constants with environment variables
os.Setenv("HOSTNAME", "sdk-go.io")
os.Setenv("ADMIN_GROUP", "ADMINS")
os.Setenv("CLIENT_ID", "clientid")
os.Setenv("CLIENT_SECRET", "clientsecret")
os.Setenv("TOKEN_URL", oAuth2Server.URL+"/token")
os.Setenv("USERINFO_URL", oAuth2Server.URL+"/userinfo")
os.Setenv("LOGOUT_URL", oAuth2Server.URL+"/logout")
// Set up testers
os.Setenv("AUTH_URL", oAuth2Server.URL+"/auth-wrong-state") // Set the server to access failing OAuth2 endpoints
Oauth2Tests(t)
os.Setenv("AUTH_URL", oAuth2Server.URL+"/auth") // Set the server to access the correct OAuth2Endpoint
os.Setenv("USERINFO_URL", oAuth2Server.URL+"/admininfo")
resetData(t)
appTests(t)
os.RemoveAll("./data")
}
/**
SECURITY TESTS (this tests are to check that the security protections works)
**/
func Oauth2Tests(t *testing.T) {
// Create the tester
ts, do, _ := createTester(t)
defer ts.Close() // Close the tester
// Try to login (must fail)
do("GET", "/OAuth2Login", noH, "", 500, "invalid oauth state")
}
func appTests(t *testing.T) {
ts, do, _ := createTester(t)
defer ts.Close() // Close the tester
tests := func() {
// Get the XSRF Token
response := do("GET", "/api/common/WhoAmI", noH, "", 200, "")
token := auth.TokenData{}
json.Unmarshal([]byte(response), &token)
xsrfHeader := tester.Header{Key: "XSRF-TOKEN", Value: token.XSRFToken}
do("POST", "/api/Capturer", xsrfHeader, `{"UserID":2,"Name":"Capturer"}`, 500, `UserID is already bind to a Capturer`)
}
// Do an OAuth2 login with an known admin
do("GET", "/OAuth2Login", noH, "", 200, "<!DOCTYPE html>")
tests()
// Try to logout (must pass)
do("GET", "/Logout", noH, "", 200, "Logout OK")
}
func resetData(t *testing.T) {
os.RemoveAll("./data")
os.Mkdir("data", os.ModePerm)
os.Create("./data/test.db")
os.Link("../../data/users.db", "./data/users.db")
ts, do, _ := createTester(t)
defer ts.Close() // Close the tester
// Init Data in DB tests
init := func() {
response := do("GET", "/api/common/WhoAmI", noH, "", 200, "")
token := auth.TokenData{}
json.Unmarshal([]byte(response), &token)
xsrfHeader := tester.Header{Key: "XSRF-TOKEN", Value: token.XSRFToken}
// Create a capturer
do("POST", "/api/Capturer", xsrfHeader, `{"UserID":2,"Name":"Capturer"}`, 200, `{"ID":1,"UserID":2,"Name":"Capturer","DeskRounds":null}`)
do("POST", "/api/Capturer", xsrfHeader, `{"UserID":3,"Name":"Capturer"}`, 200, `{"ID":2,"UserID":3,"Name":"Capturer","DeskRounds":null}`)
}
do("POST", "/Login", noH, `{"login": "admin","password": "password"}`, 200, "")
init()
do("GET", "/Logout", noH, "", 200, "Logout OK")
}
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
func resetDataWithData(t *testing.T) {
os.RemoveAll("./data")
os.Mkdir("data", os.ModePerm)
os.Create("./data/test.db")
os.Link("../../data/users.db", "./data/users.db")
ts, do, _ := createTester(t)
defer ts.Close() // Close the tester
// Init Data in DB tests
init := func() {
response := do("GET", "/api/common/WhoAmI", noH, "", 200, "")
token := auth.TokenData{}
json.Unmarshal([]byte(response), &token)
xsrfHeader := tester.Header{Key: "XSRF-TOKEN", Value: token.XSRFToken}
// Create a capturer
do("POST", "/api/Capturer", xsrfHeader, `{"UserID":2,"Name":"Capturer"}`, 200, `{"ID":1,"UserID":2,"Name":"Capturer","DeskRounds":null}`)
do("POST", "/api/Capturer", xsrfHeader, `{"UserID":3,"Name":"Capturer"}`, 200, `{"ID":2,"UserID":3,"Name":"Capturer","DeskRounds":null}`)
do("POST", "/api/Election", xsrfHeader, `{"Name":"Grand Lyon 2020","BallotType":"metropolitan-direct"}`, 200, `{"ID":1,"Name":"Grand Lyon 2020","BallotType":"metropolitan-direct","Areas":null,"Rounds":null}`)
do("POST", "/api/Area", xsrfHeader, `{"ElectionID":1,"Name":"Area 1","SeatNumber":9,"MapID":"1"}`, 200, `{"ID":1,"ElectionID":1,"Name":"Area 1","SeatNumber":9,"MapID":"1","Sections":null}`)
do("POST", "/api/Section", xsrfHeader, `{"AreaID":1,"Name":"Section 1","MapID":"1"}`, 200, `{"ID":1,"AreaID":1,"Name":"Section 1","MapID":"1","Desks":null}`)
}
do("POST", "/Login", noH, `{"login": "admin","password": "password"}`, 200, "")
init()
do("GET", "/Logout", noH, "", 200, "Logout OK")
}
func createTester(t *testing.T) (*httptest.Server, func(method string, url string, header tester.Header, payload string, expectedStatus int, expectedBody string) string, func(method string, url string, header tester.Header, payload string, expectedStatus int, expectedBody string) string) {
// Create the server
mux := CreateRootMux(1443, "../../web")
ts := httptest.NewServer(mux.Mux)
url, _ := url.Parse(ts.URL)
port := url.Port()
mux.Manager.Config.RedirectURL = "http://" + os.Getenv("HOSTNAME") + ":" + port + "/OAuth2Callback"
mux.Manager.Hostname = "http://" + os.Getenv("HOSTNAME") + ":" + port
// Create the cookie jar
jar, _ := cookiejar.New(nil)
// wrap the testing function
return ts, tester.CreateServerTester(t, port, os.Getenv("HOSTNAME"), jar), tester.CreateServerTester(t, port, os.Getenv("HOSTNAME"), nil)
}