Skip to content
Snippets Groups Projects
Commit fa1544c3 authored by Alexis Poyen's avatar Alexis Poyen
Browse files

Feat : Prevent not authenticated users to access API, allow clients to access...

Feat : Prevent not authenticated users to access API, allow clients to access only some API and Admin to acess all API
parent dfcc30b4
No related branches found
No related tags found
No related merge requests found
Pipeline #4601 failed
...@@ -21,13 +21,11 @@ type authzFunc func(http.Handler, []string, bool) http.Handler ...@@ -21,13 +21,11 @@ type authzFunc func(http.Handler, []string, bool) http.Handler
// DataHandler init a gorm DB an presents API handlers // DataHandler init a gorm DB an presents API handlers
type DataHandler struct { type DataHandler struct {
db *gorm.DB db *gorm.DB
authz authzFunc
} }
// NewDataHandler init a DataHandler and returns a pointer to it // NewDataHandler init a DataHandler and returns a pointer to it
func NewDataHandler(authzFromMain authzFunc) *DataHandler { func NewDataHandler(authzFromMain authzFunc) *DataHandler {
// authz := authzFromMain
db, err := gorm.Open("sqlite3", "./data/test.db") db, err := gorm.Open("sqlite3", "./data/test.db")
if err != nil { if err != nil {
panic("failed to connect database") panic("failed to connect database")
......
package models
import (
"net/http"
"net/http/httptest"
"net/url"
"os"
"testing"
"github.com/nicolaspernoud/vestibule/pkg/auth"
"github.com/nicolaspernoud/vestibule/pkg/tester"
)
func TestBankAPI(t *testing.T) {
// Remove the test db to start clean
os.Remove("./data/test.db")
os.Mkdir("data", os.ModePerm)
os.Create("./data/test.db")
// Create the handler
dh := NewDataHandler(auth.ValidateAuthMiddleware)
ts := httptest.NewServer(http.HandlerFunc(dh.ProcessAPI))
defer ts.Close()
url, _ := url.Parse(ts.URL)
port := url.Port()
// Wrap the testing function
do := tester.CreateServerTester(t, port, "sdk-go.io", nil)
noH := tester.Header{Key: "", Value: ""}
// Without authent API calls must fails with 403 user could not be got from context
// Try to get the first client
do("GET", "/api/UserClients/1", noH, "", 401, `error extracting token`)
// // Add bank account to client
// do("POST", "/api/BankAccounts", noH, `{"Number":"01-01","UserClientID":1,"Type":"checking-account","Amount":458,"BankOverdraft":-100}`, 200, "")
// // Add an other bank account to client
// do("POST", "/api/BankAccounts", noH, `{"Number":"01-02","UserClientID":1,"Type":"saving-account","Amount":1287,"BankOverdraft":0}`, 200, "")
// // Get account where id=1
// do("GET", "/api/BankAccounts/1", noH, "", 200, `{"ID":1,"Number":"01-01","UserClientID":1,"Type":"checking-account","Amount":458,"BankOverdraft":-100,"Operations":[]}`)
// // Get all Bank account
// do("GET", "/api/BankAccounts/", noH, "", 200, `[{"ID":1,"Number":"01-01","UserClientID":1,"Type":"checking-account","Amount":458,"BankOverdraft":-100,"Operations":[]},{"ID":2,"Number":"01-02","UserClientID":1,"Type":"saving-account","Amount":1287,"BankOverdraft":0,"Operations":[]}]`)
// // Add a bank account to Bakery
// do("POST", "/api/BankAccounts", noH, `{"Number":"02-01","UserClientID":2,"Type":"checking-account","Amount":4745,"BankOverdraft":-500}`, 200, "")
// // Add operation between client and Bakery
// do("POST", "/api/Operations", noH, `{"Debtor":1,"Amount":-100,"Creditor":3}`, 200, "")
// // Get operation where id=1
// do("GET", "/api/Operations/1", noH, "", 200, `{"ID":1,"Debtor":1,"Amount":-100`)
// // Get Operations for creditor (opposite operation should have been registered)
// do("GET", "/api/Operations/2", noH, "", 200, `{"ID":2,"Debtor":3,"Amount":100`)
// // Add invalid operation between client and Bakery must be refused with 417 (Expectation failed)
// do("POST", "/api/Operations", noH, `{"Debtor":1,"Amount":-1789,"Creditor":3}`, 417, "Not enough money")
// // Get client Dupond with his banks accounts and operations up to date (-100€ on checking-account)
// do("GET", "/api/UserClients/1", noH, "", 200, `{"ID":1,"Name":"Dupond","BankAccounts":[{"ID":1,"Number":"01-01","UserClientID":1,"Type":"checking-account","Amount":358,"BankOverdraft":-100,"Operations":null},{"ID":2,"Number":"01-02","UserClientID":1,"Type":"saving-account","Amount":1287,"BankOverdraft":0,"Operations":null}]}`)
// // Get client Bakery with his banks accounts and operations up to date (+100€ on checking-account)
// do("GET", "/api/UserClients/2", noH, "", 200, `{"ID":2,"Name":"Boulangerie","BankAccounts":[{"ID":3,"Number":"02-01","UserClientID":2,"Type":"checking-account","Amount":4845,"BankOverdraft":-500,"Operations":null}]}`)
// // Verify operation on client Dupond checking-account
// do("GET", "/api/BankAccounts/1", noH, "", 200, `{"ID":1,"Number":"01-01","UserClientID":1,"Type":"checking-account","Amount":358,"BankOverdraft":-100,"Operations":[{"ID":1,"Debtor":1,"Amount":-100`)
// // Verify operation on client Bakery checking-account
// do("GET", "/api/BankAccounts/3", noH, "", 200, `{"ID":3,"Number":"02-01","UserClientID":2,"Type":"checking-account","Amount":4845,"BankOverdraft":-500,"Operations":[{"ID":2,"Debtor":3,"Amount":100`)
// // Try to delete the first operation
// do("DELETE", "/api/Operations/1", noH, ``, 200, "")
// // Try to get the first user again
// do("GET", "/api/Operations/1", noH, "", 404, `id does not exist`)
// // The operation id=2 (opposite operation) should also have been deleted
// do("GET", "/api/Operations/2", noH, "", 404, `id does not exist`)
// // Test that bank account have been updated after operations deletion
// do("GET", "/api/BankAccounts/1", noH, "", 200, `{"ID":1,"Number":"01-01","UserClientID":1,"Type":"checking-account","Amount":458,"BankOverdraft":-100,"Operations":[]}`)
// do("GET", "/api/BankAccounts/3", noH, "", 200, `{"ID":3,"Number":"02-01","UserClientID":2,"Type":"checking-account","Amount":4745,"BankOverdraft":-500,"Operations":[]}`)
// // Try to delete the saving account of Dupond
// do("DELETE", "/api/BankAccounts/2", noH, ``, 200, "")
// // Try to get the first user again
// do("GET", "/api/BankAccounts/2", noH, "", 404, `id does not exist`)
// // Test that client have been updated after operations deletion and bank account deletion
// // Get client Dupond with his banks accounts and operations up to date (-100€ on checking-account)
// do("GET", "/api/UserClients/1", noH, "", 200, `{"ID":1,"Name":"Dupond","BankAccounts":[{"ID":1,"Number":"01-01","UserClientID":1,"Type":"checking-account","Amount":458,"BankOverdraft":-100,"Operations":null}]}`)
// // Try to delete the saving account of Dupond
// do("DELETE", "/api/UserClients/2", noH, ``, 200, "")
// // Try to get the first user again
// do("GET", "/api/UserClients/2", noH, "", 404, `id does not exist`)
// // Test that bank account have been deleted after client deletion
// do("GET", "/api/BankAccounts/3", noH, "", 404, `id does not exist`)
// remove db test
os.RemoveAll("./data")
}
...@@ -9,7 +9,6 @@ import ( ...@@ -9,7 +9,6 @@ import (
"net/url" "net/url"
"os" "os"
"regexp" "regexp"
"sync"
"testing" "testing"
"github.com/nicolaspernoud/vestibule/pkg/auth" "github.com/nicolaspernoud/vestibule/pkg/auth"
...@@ -34,6 +33,7 @@ func init() { ...@@ -34,6 +33,7 @@ func init() {
func TestAll(t *testing.T) { func TestAll(t *testing.T) {
// Set the users file // Set the users file
auth.UsersFile = "../../configs/users.json" auth.UsersFile = "../../configs/users.json"
resetData()
// Create the mock OAuth2 server // Create the mock OAuth2 server
oAuth2Server := httptest.NewServer(mocks.CreateMockOAuth2()) oAuth2Server := httptest.NewServer(mocks.CreateMockOAuth2())
defer oAuth2Server.Close() defer oAuth2Server.Close()
...@@ -49,147 +49,246 @@ func TestAll(t *testing.T) { ...@@ -49,147 +49,246 @@ func TestAll(t *testing.T) {
os.Setenv("LOGOUT_URL", oAuth2Server.URL+"/logout") os.Setenv("LOGOUT_URL", oAuth2Server.URL+"/logout")
// Set up testers // Set up testers
os.Setenv("AUTH_URL", oAuth2Server.URL+"/auth-wrong-state") // Set the server to access failing OAuth2 endpoints os.Setenv("AUTH_URL", oAuth2Server.URL+"/auth-wrong-state") // Set the server to access failing OAuth2 endpoints
oauth2Tests := createOauth2Tests(t) Oauth2Tests(t)
os.Setenv("AUTH_URL", oAuth2Server.URL+"/auth") // Set the server to access the correct OAuth2Endpoint os.Setenv("AUTH_URL", oAuth2Server.URL+"/auth") // Set the server to access the correct OAuth2Endpoint
unloggedTests := createUnLoggedTests(t)
userTests := createUserTests(t)
os.Setenv("USERINFO_URL", oAuth2Server.URL+"/admininfo") os.Setenv("USERINFO_URL", oAuth2Server.URL+"/admininfo")
adminTests := createAdminTests(t)
// RUN THE TESTS CONCURRENTLY
var wg sync.WaitGroup
functions := []func(wg *sync.WaitGroup){oauth2Tests, unloggedTests, userTests, adminTests}
for _, f := range functions {
wg.Add(1)
go f(&wg)
}
wg.Wait()
UnLoggedTests(t)
UserTests(t)
AdminTests(t)
os.RemoveAll("./data")
} }
/** /**
SECURITY TESTS (this tests are to check that the security protections works) SECURITY TESTS (this tests are to check that the security protections works)
**/ **/
func createOauth2Tests(t *testing.T) func(wg *sync.WaitGroup) { func Oauth2Tests(t *testing.T) {
// Create the tester // Create the tester
ts, do, _ := createTester(t) ts, do, _ := createTester(t)
return func(wg *sync.WaitGroup) { defer ts.Close() // Close the tester
defer ts.Close() // Close the tester // Try to login (must fail)
defer wg.Done() do("GET", "/OAuth2Login", noH, "", 500, "invalid oauth state")
// Try to login (must fail)
do("GET", "/OAuth2Login", noH, "", 500, "invalid oauth state")
}
} }
/** /**
UNLOGGED USER TESTS (this tests are to check that the security protections works) UNLOGGED USER TESTS (this tests are to check that the security protections works)
**/ **/
func createUnLoggedTests(t *testing.T) func(wg *sync.WaitGroup) { func UnLoggedTests(t *testing.T) {
// Create the tester // Create the tester
ts, do, _ := createTester(t) ts, do, _ := createTester(t)
return func(wg *sync.WaitGroup) {
defer ts.Close() // Close the tester defer ts.Close() // Close the tester
defer wg.Done() // Without authent API calls must fails with 403 user could not be got from context
// Without authent API calls must fails with 403 user could not be got from context // Try to get the first client should fail
// Try to get the first client do("GET", "/api/UserClients/1", noH, "", 401, `error extracting token`)
do("GET", "/api/UserClients/1", noH, "", 401, `error extracting token`) // Try to get all clients should fail
do("GET", "/api/UserClients", noH, "", 401, `error extracting token`)
// // Try to create an user (must fail) // Try to get the first operation should fail
// do("POST", "/api/admin/users/", noH, newUser, 401, "error extracting token") do("GET", "/api/Operations/1", noH, "", 401, `error extracting token`)
// // Try to delete an user (must fail) // Try to get all operations should fail
// do("DELETE", "/api/admin/users/0", noH, "", 401, "error extracting token") do("GET", "/api/Operations", noH, "", 401, `error extracting token`)
// // Try to access the main page (must pass) // Try to get the first BankAccount should fail
// do("GET", "/", noH, "", 200, "<!DOCTYPE html>") do("GET", "/api/BankAccounts/1", noH, "", 401, `error extracting token`)
// // Try to get the user informations (must fail) // Try to get all BankAccounts should fail
// do("GET", "/api/common/WhoAmI", noH, "", 401, "error extracting token") do("GET", "/api/BankAccounts", noH, "", 401, `error extracting token`)
// // Do a in memory login with an unknown user
// do("POST", "/Login", noH, `{"login": "unknownuser","password": "password"}`, http.StatusForbidden, `user not found`) // Unlogged user should not be able to create a Client
// // Do a in memory login with a known user but bad password do("POST", "/api/UserClients", noH, `{"Name":"Dupond"}`, 401, `error extracting token`)
// do("POST", "/Login", noH, `{"login": "admin","password": "badpassword"}`, http.StatusForbidden, `user not found`) // Unlogged user should not be able to create a Bank Account
// // Try to get a share token (must fail) do("POST", "/api/BankAccounts", noH, `{"Number":"01-01","UserClientID":1,"Type":"checking-account","Amount":458,"BankOverdraft":-100}`, 401, `error extracting token`)
// do("POST", "/api/common/Share", noH, `{"sharedfor":"guest","url":"userdav.vestibule.io/mydata/test.txt","lifespan":1,"readonly":true}`, 401, "error extracting token") // Unlogged user should not be able to create an Operation
} do("POST", "/api/Operations", noH, `{"Debtor":1,"Amount":-100,"Creditor":3}`, 401, `error extracting token`)
// Unlogged user should not be able to delete an Operation
do("DELETE", "/api/Operations/1", noH, ``, 401, "error extracting token")
// Unlogged user should not be able to delete a BankAccount
do("DELETE", "/api/BankAccounts/2", noH, ``, 401, "error extracting token")
// Unlogged user should not be able to delete a Client
do("DELETE", "/api/UserClients/2", noH, ``, 401, "error extracting token")
// Try to access the main page (must pass)
do("GET", "/", noH, "", 200, "<!DOCTYPE html>")
// Try to get the user informations (must fail)
do("GET", "/api/common/WhoAmI", noH, "", 401, "error extracting token")
// Do a in memory login with an unknown user
do("POST", "/Login", noH, `{"login": "unknownuser","password": "password"}`, http.StatusForbidden, `user not found`)
// Do a in memory login with a known user but bad password
do("POST", "/Login", noH, `{"login": "admin","password": "badpassword"}`, http.StatusForbidden, `user not found`)
// Try to get a share token (must fail)
do("POST", "/api/common/Share", noH, `{"sharedfor":"guest","url":"userdav.vestibule.io/mydata/test.txt","lifespan":1,"readonly":true}`, 401, "error extracting token")
} }
/** /**
USER TESTS (this tests are to check that a normally logged user can access the apps that is allowed to and only that) USER TESTS (this tests are to check that a normally logged user can access the apps that is allowed to and only that)
**/ **/
func createUserTests(t *testing.T) func(wg *sync.WaitGroup) { func UserTests(t *testing.T) {
// Create the tester // Create the tester
ts, do, _ := createTester(t) ts, do, _ := createTester(t)
return func(wg *sync.WaitGroup) { defer ts.Close() // Close the tester
defer ts.Close() // Close the tester dataInit := func() {
defer wg.Done() // Do a in memory login with an known admin
tests := func() { do("POST", "/Login", noH, `{"login": "admin","password": "password"}`, 200, "")
// Get the XSRF Token // Get the XSRF Token
response := do("GET", "/api/common/WhoAmI", noH, "", 200, "") response := do("GET", "/api/common/WhoAmI", noH, "", 200, "")
token := auth.TokenData{} token := auth.TokenData{}
json.Unmarshal([]byte(response), &token) json.Unmarshal([]byte(response), &token)
// xsrfHeader := tester.Header{Key: "XSRF-TOKEN", Value: token.XSRFToken} xsrfHeader := tester.Header{Key: "XSRF-TOKEN", Value: token.XSRFToken}
} do("POST", "/api/UserClients", xsrfHeader, `{"Name":"Dupond"}`, 200, "")
// Try to login with OAuth2 (must pass) do("POST", "/api/UserClients", xsrfHeader, `{"Name":"Boulangerie"}`, 200, "")
do("GET", "/OAuth2Login", noH, "", 200, "<!DOCTYPE html>")
// Run the tests do("POST", "/api/BankAccounts", xsrfHeader, `{"Number":"01-01","UserClientID":1,"Type":"checking-account","Amount":458,"BankOverdraft":-100}`, 200, "")
tests() do("POST", "/api/BankAccounts", xsrfHeader, `{"Number":"01-02","UserClientID":1,"Type":"saving-account","Amount":1287,"BankOverdraft":0}`, 200, "")
// Try to logout (must pass) do("POST", "/api/BankAccounts", xsrfHeader, `{"Number":"02-01","UserClientID":2,"Type":"checking-account","Amount":4745,"BankOverdraft":-500}`, 200, "")
do("GET", "/Logout", noH, "", 200, "Logout OK")
// Do a in memory login with an known user
do("POST", "/Login", noH, `{"login": "user","password": "password"}`, 200, "")
// Run the tests
tests()
// Try to logout (must pass)
do("GET", "/Logout", noH, "", 200, "Logout OK") do("GET", "/Logout", noH, "", 200, "Logout OK")
} }
dataInit()
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}
// Try to create a client should fail with 405
do("POST", "/api/UserClients", xsrfHeader, `{"Name":"Dupond"}`, 405, "You're not authorize to execute this method on this ressource.")
// Try to create a BankAccount should fail with 405
do("POST", "/api/BankAccounts", xsrfHeader, `{"Number":"01-01","UserClientID":1,"Type":"checking-account","Amount":458,"BankOverdraft":-100}`, 405, "You're not authorize to execute this method on this ressource.")
// Client should be able to create an operation
do("POST", "/api/Operations", xsrfHeader, `{"Debtor":1,"Amount":-100,"Creditor":3}`, 200, "")
// Get operation between client and Bakery
do("GET", "/api/Operations/1", xsrfHeader, "", 200, `{"ID":1,"Debtor":1,"Amount":-100`)
// Get Operations for creditor (opposite operation should have been registered)
do("GET", "/api/Operations/2", xsrfHeader, "", 200, `{"ID":2,"Debtor":3,"Amount":100`)
// Verify operation on client Dupond checking-account
do("GET", "/api/BankAccounts/1", xsrfHeader, "", 200, `{"ID":1,"Number":"01-01","UserClientID":1,"Type":"checking-account","Amount":358,"BankOverdraft":-100,"Operations":[{"ID":1,"Debtor":1,"Amount":-100`)
// Verify operation on client Bakery checking-account
do("GET", "/api/BankAccounts/3", xsrfHeader, "", 200, `{"ID":3,"Number":"02-01","UserClientID":2,"Type":"checking-account","Amount":4845,"BankOverdraft":-500,"Operations":[{"ID":2,"Debtor":3,"Amount":100`)
// Get client Dupond with his banks accounts and operations up to date (-100€ on checking-account)
do("GET", "/api/UserClients/1", xsrfHeader, "", 200, `{"ID":1,"Name":"Dupond","BankAccounts":[{"ID":1,"Number":"01-01","UserClientID":1,"Type":"checking-account","Amount":358,"BankOverdraft":-100,"Operations":null},{"ID":2,"Number":"01-02","UserClientID":1,"Type":"saving-account","Amount":1287,"BankOverdraft":0,"Operations":null}]}`)
// Get client Bakery with his banks accounts and operations up to date (+100€ on checking-account)
do("GET", "/api/UserClients/2", xsrfHeader, "", 200, `{"ID":2,"Name":"Boulangerie","BankAccounts":[{"ID":3,"Number":"02-01","UserClientID":2,"Type":"checking-account","Amount":4845,"BankOverdraft":-500,"Operations":null}]}`)
// Try to get all the clients
do("GET", "/api/UserClients", xsrfHeader, "", 200, `[{"ID":1,"Name":"Dupond","BankAccounts":[{"ID":1,"Number":"01-01","UserClientID":1,"Type":"checking-account","Amount":358,"BankOverdraft":-100,"Operations":null},{"ID":2,"Number":"01-02","UserClientID":1,"Type":"saving-account","Amount":1287,"BankOverdraft":0,"Operations":null}]},{"ID":2,"Name":"Boulangerie","BankAccounts":[{"ID":3,"Number":"02-01","UserClientID":2,"Type":"checking-account","Amount":4845,"BankOverdraft":-500,"Operations":null}]}]`)
// Try to delete the first operation should fail
do("DELETE", "/api/Operations/1", xsrfHeader, ``, 405, "You're not authorize to execute this method on this ressource.")
// Try to delete the saving account of Dupond should fail
do("DELETE", "/api/BankAccounts/2", xsrfHeader, ``, 405, "You're not authorize to execute this method on this ressource.")
// Try to delete the client Dupond should fail
do("DELETE", "/api/UserClients/2", xsrfHeader, ``, 405, "You're not authorize to execute this method on this ressource.")
}
// Do a in memory login with an known user
do("POST", "/Login", noH, `{"login": "user","password": "password"}`, 200, "")
// Run the tests
tests()
// Try to logout (must pass)
do("GET", "/Logout", noH, "", 200, "Logout OK")
} }
/** /**
ADMIN TESTS (this tests are to check that an administrator can alter the apps) ADMIN TESTS (this tests are to check that an administrator can alter the apps)
**/ **/
func createAdminTests(t *testing.T) func(wg *sync.WaitGroup) { func AdminTests(t *testing.T) {
// Create the tester // Create the tester
ts, do, _ := createTester(t) ts, do, _ := createTester(t)
return func(wg *sync.WaitGroup) { defer ts.Close() // Close the tester
defer ts.Close() // Close the tester tests := func() {
defer wg.Done() // Get the XSRF Token
tests := func() { response := do("GET", "/api/common/WhoAmI", noH, "", 200, "")
// Get the XSRF Token token := auth.TokenData{}
response := do("GET", "/api/common/WhoAmI", noH, "", 200, "") json.Unmarshal([]byte(response), &token)
token := auth.TokenData{} xsrfHeader := tester.Header{Key: "XSRF-TOKEN", Value: token.XSRFToken}
json.Unmarshal([]byte(response), &token)
xsrfHeader := tester.Header{Key: "XSRF-TOKEN", Value: token.XSRFToken} // Try to create a client
do("POST", "/api/UserClients", xsrfHeader, `{"Name":"Dupond"}`, 200, "")
// Try to create a client // Try to create an other one
do("POST", "/api/UserClients", xsrfHeader, `{"Name":"Dupond"}`, 200, "") do("POST", "/api/UserClients", xsrfHeader, `{"Name":"Boulangerie"}`, 200, "")
// Try to create an other one // Try to get the first client
do("POST", "/api/UserClients", xsrfHeader, `{"Name":"Boulangerie"}`, 200, "") do("GET", "/api/UserClients/1", xsrfHeader, "", 200, `{"ID":1,"Name":"Dupond","BankAccounts":[]}`)
// Try to get the first client // Try to get all the clients
do("GET", "/api/UserClients/1", xsrfHeader, "", 200, `{"ID":1,"Name":"Dupond","BankAccounts":[]}`) do("GET", "/api/UserClients", xsrfHeader, "", 200, `[{"ID":1,"Name":"Dupond","BankAccounts":[]},{"ID":2,"Name":"Boulangerie","BankAccounts":[]}]`)
// Try to get all the clients
do("GET", "/api/UserClients", xsrfHeader, "", 200, `[{"ID":1,"Name":"Dupond","BankAccounts":[]},{"ID":2,"Name":"Boulangerie","BankAccounts":[]}]`) // Add bank account to client
} do("POST", "/api/BankAccounts", xsrfHeader, `{"Number":"01-01","UserClientID":1,"Type":"checking-account","Amount":458,"BankOverdraft":-100}`, 200, "")
// Try to login (must pass) // Add an other bank account to client
do("GET", "/OAuth2Login", noH, "", 200, "<!DOCTYPE html>") do("POST", "/api/BankAccounts", xsrfHeader, `{"Number":"01-02","UserClientID":1,"Type":"saving-account","Amount":1287,"BankOverdraft":0}`, 200, "")
// Run the tests // Get account where id=1
tests() do("GET", "/api/BankAccounts/1", xsrfHeader, "", 200, `{"ID":1,"Number":"01-01","UserClientID":1,"Type":"checking-account","Amount":458,"BankOverdraft":-100,"Operations":[]}`)
// Try to logout (must pass) // Get all Bank account
do("GET", "/Logout", noH, "", 200, "Logout OK") do("GET", "/api/BankAccounts/", xsrfHeader, "", 200, `[{"ID":1,"Number":"01-01","UserClientID":1,"Type":"checking-account","Amount":458,"BankOverdraft":-100,"Operations":[]},{"ID":2,"Number":"01-02","UserClientID":1,"Type":"saving-account","Amount":1287,"BankOverdraft":0,"Operations":[]}]`)
// Do a in memory login with an known admin // Add a bank account to Bakery
resetData() do("POST", "/api/BankAccounts", xsrfHeader, `{"Number":"02-01","UserClientID":2,"Type":"checking-account","Amount":4745,"BankOverdraft":-500}`, 200, "")
do("POST", "/Login", noH, `{"login": "admin","password": "password"}`, 200, "")
tests() // Add operation between client and Bakery
// Try to logout (must pass) do("POST", "/api/Operations", xsrfHeader, `{"Debtor":1,"Amount":-100,"Creditor":3}`, 200, "")
do("GET", "/Logout", noH, "", 200, "Logout OK") // Get operation where id=1
do("GET", "/api/Operations/1", xsrfHeader, "", 200, `{"ID":1,"Debtor":1,"Amount":-100`)
// Get Operations for creditor (opposite operation should have been registered)
do("GET", "/api/Operations/2", xsrfHeader, "", 200, `{"ID":2,"Debtor":3,"Amount":100`)
// Add invalid operation between client and Bakery must be refused with 417 (Expectation failed)
do("POST", "/api/Operations", xsrfHeader, `{"Debtor":1,"Amount":-1789,"Creditor":3}`, 417, "Not enough money")
// Get client Dupond with his banks accounts and operations up to date (-100€ on checking-account)
do("GET", "/api/UserClients/1", xsrfHeader, "", 200, `{"ID":1,"Name":"Dupond","BankAccounts":[{"ID":1,"Number":"01-01","UserClientID":1,"Type":"checking-account","Amount":358,"BankOverdraft":-100,"Operations":null},{"ID":2,"Number":"01-02","UserClientID":1,"Type":"saving-account","Amount":1287,"BankOverdraft":0,"Operations":null}]}`)
// Get client Bakery with his banks accounts and operations up to date (+100€ on checking-account)
do("GET", "/api/UserClients/2", xsrfHeader, "", 200, `{"ID":2,"Name":"Boulangerie","BankAccounts":[{"ID":3,"Number":"02-01","UserClientID":2,"Type":"checking-account","Amount":4845,"BankOverdraft":-500,"Operations":null}]}`)
// Verify operation on client Dupond checking-account
do("GET", "/api/BankAccounts/1", xsrfHeader, "", 200, `{"ID":1,"Number":"01-01","UserClientID":1,"Type":"checking-account","Amount":358,"BankOverdraft":-100,"Operations":[{"ID":1,"Debtor":1,"Amount":-100`)
// Verify operation on client Bakery checking-account
do("GET", "/api/BankAccounts/3", xsrfHeader, "", 200, `{"ID":3,"Number":"02-01","UserClientID":2,"Type":"checking-account","Amount":4845,"BankOverdraft":-500,"Operations":[{"ID":2,"Debtor":3,"Amount":100`)
// Try to delete the first operation
do("DELETE", "/api/Operations/1", xsrfHeader, ``, 200, "")
// Try to get the first user again
do("GET", "/api/Operations/1", xsrfHeader, "", 404, `id does not exist`)
// The operation id=2 (opposite operation) should also have been deleted
do("GET", "/api/Operations/2", xsrfHeader, "", 404, `id does not exist`)
// Test that bank account have been updated after operations deletion
do("GET", "/api/BankAccounts/1", xsrfHeader, "", 200, `{"ID":1,"Number":"01-01","UserClientID":1,"Type":"checking-account","Amount":458,"BankOverdraft":-100,"Operations":[]}`)
do("GET", "/api/BankAccounts/3", xsrfHeader, "", 200, `{"ID":3,"Number":"02-01","UserClientID":2,"Type":"checking-account","Amount":4745,"BankOverdraft":-500,"Operations":[]}`)
// Try to delete the saving account of Dupond
do("DELETE", "/api/BankAccounts/2", xsrfHeader, ``, 200, "")
// Try to get the first user again
do("GET", "/api/BankAccounts/2", xsrfHeader, "", 404, `id does not exist`)
// Test that client have been updated after operations deletion and bank account deletion
// Get client Dupond with his banks accounts and operations up to date (-100€ on checking-account)
do("GET", "/api/UserClients/1", xsrfHeader, "", 200, `{"ID":1,"Name":"Dupond","BankAccounts":[{"ID":1,"Number":"01-01","UserClientID":1,"Type":"checking-account","Amount":458,"BankOverdraft":-100,"Operations":null}]}`)
// Try to delete the saving account of Dupond
do("DELETE", "/api/UserClients/2", xsrfHeader, ``, 200, "")
// Try to get the first user again
do("GET", "/api/UserClients/2", xsrfHeader, "", 404, `id does not exist`)
// Test that bank account have been deleted after client deletion
do("GET", "/api/BankAccounts/3", xsrfHeader, "", 404, `id does not exist`)
} }
// Do a in memory login with an known admin
do("POST", "/Login", noH, `{"login": "admin","password": "password"}`, 200, "")
tests()
// Try to logout (must pass)
do("GET", "/Logout", noH, "", 200, "Logout OK")
} }
func resetData() { func resetData() {
os.Remove("./data/test.db") os.RemoveAll("./data")
os.Mkdir("data", os.ModePerm) os.Mkdir("data", os.ModePerm)
os.Create("./data/test.db") os.Create("./data/test.db")
} }
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) { 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 // Create the server
resetData()
mux := CreateRootMux(1443, "../../web") mux := CreateRootMux(1443, "../../web")
ts := httptest.NewServer(mux.Mux) ts := httptest.NewServer(mux.Mux)
url, _ := url.Parse(ts.URL) url, _ := url.Parse(ts.URL)
......
...@@ -223,7 +223,7 @@ func IsAllowed(w http.ResponseWriter, r *http.Request, allowedRoles []string) bo ...@@ -223,7 +223,7 @@ func IsAllowed(w http.ResponseWriter, r *http.Request, allowedRoles []string) bo
} }
err = checkUserHasRole(user, allowedRoles) err = checkUserHasRole(user, allowedRoles)
if err != nil { if err != nil {
http.Error(w, err.Error(), 403) http.Error(w, "You're not authorize to execute this method on this ressource.", http.StatusMethodNotAllowed)
return false return false
} }
return true return true
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment