From f5255a655c039cc96b04b04dc0a98262b0474198 Mon Sep 17 00:00:00 2001 From: meskio <meskio@sindominio.net> Date: Mon, 21 Dec 2020 19:46:10 +0100 Subject: [PATCH] Add order permitions --- api/api.go | 4 ++-- api/api_test.go | 16 +++++++++++++++- api/auth.go | 44 ++++++++++++++++++++++++++++++++++++++++++++ api/member_test.go | 22 ++++++++++++++++++++-- api/order_test.go | 24 ++++++++++++------------ 5 files changed, 93 insertions(+), 17 deletions(-) diff --git a/api/api.go b/api/api.go index 39fafa7..a392615 100644 --- a/api/api.go +++ b/api/api.go @@ -57,11 +57,11 @@ func Init(dbPath string, signKey string, mail *Mail, r *mux.Router) error { r.HandleFunc("/topup", a.authAdminNum(a.AddTopup)).Methods("POST") r.HandleFunc("/order", a.auth(a.ListOrders)).Methods("GET") - r.HandleFunc("/order", a.authNum(a.AddOrder)).Methods("POST") + r.HandleFunc("/order", a.authOrderNum(a.AddOrder)).Methods("POST") r.HandleFunc("/order/{id:[0-9]+}", a.authNum(a.GetOrder)).Methods("GET") r.HandleFunc("/order/{id:[0-9]+}", a.authNumRole(a.DeleteOrder)).Methods("DELETE") r.HandleFunc("/order/active", a.auth(a.ListActiveOrders)).Methods("GET") - r.HandleFunc("/order/picks", a.authNum(a.ListOrderPicks)).Methods("GET") + r.HandleFunc("/order/picks", a.authOrderNum(a.ListOrderPicks)).Methods("GET") r.HandleFunc("/order/{id:[0-9]+}/purchase", a.authNum(a.AddOrderPurchase)).Methods("POST") return nil } diff --git a/api/api_test.go b/api/api_test.go index 534fea8..a4eb323 100644 --- a/api/api_test.go +++ b/api/api_test.go @@ -36,6 +36,7 @@ type testAPI struct { server *httptest.Server testPath string token string + tokenOrder string tokenAdmin string } @@ -63,6 +64,15 @@ func newTestAPI(t *testing.T) *testAPI { if err != nil { t.Fatal("Can't generate token:", err) } + tokenOrder := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{ + "num": testMemberOrder.Num, + "role": "order", + "exp": time.Now().Add(time.Hour * 24).Unix(), + }) + tokenOrderString, err := tokenOrder.SignedString([]byte(signKey)) + if err != nil { + t.Fatal("Can't generate token:", err) + } tokenAdmin := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{ "num": testMemberAdmin.Num, "role": "admin", @@ -73,13 +83,17 @@ func newTestAPI(t *testing.T) *testAPI { t.Fatal("Can't generate token:", err) } - return &testAPI{t, server.URL, &http.Client{}, server, testPath, tokenString, tokenAdminString} + return &testAPI{t, server.URL, &http.Client{}, server, testPath, tokenString, tokenOrderString, tokenAdminString} } func (ta *testAPI) do(method string, url string, body interface{}, respBody interface{}) *http.Response { return ta.doToken(ta.token, method, url, body, respBody) } +func (ta *testAPI) doOrder(method string, url string, body interface{}, respBody interface{}) *http.Response { + return ta.doToken(ta.tokenOrder, method, url, body, respBody) +} + func (ta *testAPI) doAdmin(method string, url string, body interface{}, respBody interface{}) *http.Response { return ta.doToken(ta.tokenAdmin, method, url, body, respBody) } diff --git a/api/auth.go b/api/auth.go index e348b95..a905c21 100644 --- a/api/auth.go +++ b/api/auth.go @@ -246,6 +246,50 @@ func (a *api) authAdminNum(fn func(int, http.ResponseWriter, *http.Request)) fun } } +func roleOrder(role string) bool { + return role == "admin" || role == "order" +} + +func (a *api) authOrder(fn func(http.ResponseWriter, *http.Request)) func(http.ResponseWriter, *http.Request) { + return func(w http.ResponseWriter, req *http.Request) { + token := req.Header.Get("x-authentication") + ok, claims := a.validateToken(token) + if !ok { + w.WriteHeader(http.StatusUnauthorized) + return + } + role, ok := claims["role"].(string) + if !ok || !roleOrder(role) { + w.WriteHeader(http.StatusUnauthorized) + return + } + fn(w, req) + } +} + +func (a *api) authOrderNum(fn func(int, http.ResponseWriter, *http.Request)) func(http.ResponseWriter, *http.Request) { + return func(w http.ResponseWriter, req *http.Request) { + token := req.Header.Get("x-authentication") + ok, claims := a.validateToken(token) + if !ok { + w.WriteHeader(http.StatusUnauthorized) + return + } + role, ok := claims["role"].(string) + if !ok || !roleOrder(role) { + log.Println(role) + w.WriteHeader(http.StatusUnauthorized) + return + } + num, ok := claims["num"].(float64) + if !ok { + w.WriteHeader(http.StatusUnauthorized) + return + } + fn(int(num), w, req) + } +} + func (a *api) authNumRole(fn func(int, string, http.ResponseWriter, *http.Request)) func(http.ResponseWriter, *http.Request) { return func(w http.ResponseWriter, req *http.Request) { token := req.Header.Get("x-authentication") diff --git a/api/member_test.go b/api/member_test.go index 045ebe0..10db059 100644 --- a/api/member_test.go +++ b/api/member_test.go @@ -9,6 +9,7 @@ import ( var ( testMemberLogin = "foo" + testMemberOrderLogin = "foobar" testMemberAdminLogin = "bar" ) @@ -24,9 +25,21 @@ var testMember = db.MemberReq{ Password: "password", } -var testMemberAdmin = db.MemberReq{ +var testMemberOrder = db.MemberReq{ Member: db.Member{ Num: 20, + Login: &testMemberOrderLogin, + Name: "FooBar Faz", + Email: "foobar@example.com", + Role: "order", + Balance: 12000, + }, + Password: "password", +} + +var testMemberAdmin = db.MemberReq{ + Member: db.Member{ + Num: 30, Login: &testMemberAdminLogin, Name: "Bar Baz", Email: "bar@example.com", @@ -47,7 +60,7 @@ func TestMemberAddList(t *testing.T) { t.Fatal("Can't get members:", resp.Status) } - if len(members) != 2 { + if len(members) != 3 { t.Fatal("Wrong number of members", len(members), members) } if members[0].Name != testMember.Name { @@ -153,6 +166,11 @@ func (tapi *testAPI) addTestMember() { tapi.t.Fatal("Can't create member:", resp.Status) } + resp = tapi.doAdmin("POST", "/member", testMemberOrder, nil) + if resp.StatusCode != http.StatusCreated { + tapi.t.Fatal("Can't create member:", resp.Status) + } + resp = tapi.doAdmin("POST", "/member", testMemberAdmin, nil) if resp.StatusCode != http.StatusCreated { tapi.t.Fatal("Can't create member:", resp.Status) diff --git a/api/order_test.go b/api/order_test.go index eae2fa9..1f312e2 100644 --- a/api/order_test.go +++ b/api/order_test.go @@ -76,7 +76,7 @@ func TestOrderDelete(t *testing.T) { order := testOrder order.Deadline = time.Now().Add(-24 * time.Hour) - resp := tapi.do("POST", "/order", order, nil) + resp := tapi.doOrder("POST", "/order", order, nil) if resp.StatusCode != http.StatusCreated { t.Fatal("Can't create order:", resp.Status) } @@ -103,7 +103,7 @@ func TestOrderDelete(t *testing.T) { t.Error("Deactivated wrong orders:", orders) } - resp = tapi.do("DELETE", fmt.Sprintf("/order/%d", orders[0].ID), nil, nil) + resp = tapi.doOrder("DELETE", fmt.Sprintf("/order/%d", orders[0].ID), nil, nil) if resp.StatusCode != http.StatusOK { t.Fatal("Can't delete order:", resp.Status) } @@ -198,7 +198,7 @@ func TestOrderNoDeactivation(t *testing.T) { order := testOrder now := time.Now() order.Deadline = time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, time.Local) - resp := tapi.do("POST", "/order", order, nil) + resp := tapi.doOrder("POST", "/order", order, nil) if resp.StatusCode != http.StatusCreated { t.Fatal("Can't create order:", resp.Status) } @@ -234,13 +234,13 @@ func TestOrderDeactivation(t *testing.T) { order := testOrder order.Deadline = time.Now().Add(-24 * time.Hour) - resp := tapi.do("POST", "/order", order, nil) + resp := tapi.doOrder("POST", "/order", order, nil) if resp.StatusCode != http.StatusCreated { t.Fatal("Can't create order:", resp.Status) } var orders []db.Order - resp = tapi.do("GET", "/order/active", nil, &orders) + resp = tapi.doOrder("GET", "/order/active", nil, &orders) if resp.StatusCode != http.StatusOK { t.Fatal("Can't get transactions:", resp.Status) } @@ -280,7 +280,7 @@ func TestOrderDeactivation(t *testing.T) { total := 3 * testProduct.Price var transactions []db.Transaction - resp = tapi.do("GET", "/transaction/mine", nil, &transactions) + resp = tapi.doOrder("GET", "/transaction/mine", nil, &transactions) if resp.StatusCode != http.StatusOK { t.Fatal("Can't get transactions:", resp.Status) } @@ -295,12 +295,12 @@ func TestOrderDeactivation(t *testing.T) { } var member db.Member - resp = tapi.do("GET", "/member/me", nil, &member) + resp = tapi.doOrder("GET", "/member/me", nil, &member) if resp.StatusCode != http.StatusOK { t.Fatal("Can't member:", resp.Status) } - if member.Balance != testMember.Balance+total { - t.Fatal("Wrong member balance:", member.Balance, testMember.Balance, total) + if member.Balance != testMemberOrder.Balance+total { + t.Fatal("Wrong member balance:", member.Balance, testMemberOrder.Balance, total) } } @@ -429,13 +429,13 @@ func TestOrderPicks(t *testing.T) { testOrderOld := testOrder testOrderOld.Deadline = time.Now().Add(-24 * time.Hour) - resp := tapi.do("POST", "/order", testOrderOld, nil) + resp := tapi.doOrder("POST", "/order", testOrderOld, nil) if resp.StatusCode != http.StatusCreated { tapi.t.Fatal("Can't create old order:", resp.Status) } var orders []db.Order - resp = tapi.do("GET", "/order/picks", nil, &orders) + resp = tapi.doOrder("GET", "/order/picks", nil, &orders) if resp.StatusCode != http.StatusOK { t.Fatal("Can't get orders picks:", resp.Status) } @@ -452,7 +452,7 @@ func TestOrderPicks(t *testing.T) { } func (tapi *testAPI) addTestOrder() { - resp := tapi.do("POST", "/order", testOrder, nil) + resp := tapi.doOrder("POST", "/order", testOrder, nil) if resp.StatusCode != http.StatusCreated { tapi.t.Fatal("Can't create order:", resp.Status) } -- GitLab