diff --git a/api/api.go b/api/api.go index 6c32111f2c3f4f73e489866f18fedd3ffa20e6a1..065d611c2cdefc4eed4635e68714dd7c481d49d6 100644 --- a/api/api.go +++ b/api/api.go @@ -36,21 +36,22 @@ func Init(dbPath string, signKey string, r *mux.Router) error { r.HandleFunc("/signin", a.SignIn).Methods("POST") - r.HandleFunc("/member", a.auth(a.ListMembers)).Methods("GET") - r.HandleFunc("/member", a.auth(a.AddMember)).Methods("POST") - r.HandleFunc("/member/{num:[0-9]+}", a.auth(a.GetMember)).Methods("GET") - r.HandleFunc("/member/{num:[0-9]+}", a.auth(a.UpdateMember)).Methods("PUT") - r.HandleFunc("/member/{num:[0-9]+}", a.auth(a.DeleteMember)).Methods("DELETE") - r.HandleFunc("/member/{num:[0-9]+}/purchase", a.auth(a.GetMemberTransactions)).Methods("GET") + r.HandleFunc("/member", a.authAdmin(a.ListMembers)).Methods("GET") + r.HandleFunc("/member", a.authAdmin(a.AddMember)).Methods("POST") + r.HandleFunc("/member/me", a.authNum(a.getMemberNum)).Methods("GET") + r.HandleFunc("/member/{num:[0-9]+}", a.authAdmin(a.GetMember)).Methods("GET") + r.HandleFunc("/member/{num:[0-9]+}", a.authAdmin(a.UpdateMember)).Methods("PUT") + r.HandleFunc("/member/{num:[0-9]+}", a.authAdmin(a.DeleteMember)).Methods("DELETE") + r.HandleFunc("/member/{num:[0-9]+}/purchase", a.authAdmin(a.GetMemberTransactions)).Methods("GET") r.HandleFunc("/product", a.auth(a.ListProducts)).Methods("GET") - r.HandleFunc("/product", a.auth(a.AddProduct)).Methods("POST") + r.HandleFunc("/product", a.authAdmin(a.AddProduct)).Methods("POST") r.HandleFunc("/product/{code:[0-9]+}", a.auth(a.GetProduct)).Methods("GET") - r.HandleFunc("/product/{code:[0-9]+}", a.auth(a.UpdateProduct)).Methods("PUT") - r.HandleFunc("/product/{code:[0-9]+}", a.auth(a.DeleteProduct)).Methods("DELETE") + r.HandleFunc("/product/{code:[0-9]+}", a.authAdmin(a.UpdateProduct)).Methods("PUT") + r.HandleFunc("/product/{code:[0-9]+}", a.authAdmin(a.DeleteProduct)).Methods("DELETE") r.HandleFunc("/transaction", a.auth(a.ListTransactions)).Methods("GET") - r.HandleFunc("/transaction/{id:[0-9]+}", a.auth(a.GetTransaction)).Methods("GET") + r.HandleFunc("/transaction/{id:[0-9]+}", a.authNumRole(a.GetTransaction)).Methods("GET") r.HandleFunc("/transaction/mine", a.authNum(a.getTransactionsByMember)).Methods("GET") r.HandleFunc("/purchase", a.authNum(a.AddPurchase)).Methods("POST") diff --git a/api/auth.go b/api/auth.go index 7f8e9960e578b553af2d7e74522222a63a0a696f..b8c747bde045f0446a9ac63cb80983d7c8ea4094 100644 --- a/api/auth.go +++ b/api/auth.go @@ -75,7 +75,6 @@ func (a *api) authNum(fn func(int, http.ResponseWriter, *http.Request)) func(htt token := req.Header.Get("x-authentication") ok, claims := a.validateToken(token) if !ok { - log.Print("foo") w.WriteHeader(http.StatusUnauthorized) return } @@ -88,6 +87,45 @@ func (a *api) authNum(fn func(int, http.ResponseWriter, *http.Request)) func(htt } } +func (a *api) authAdmin(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 || role != "admin" { + w.WriteHeader(http.StatusUnauthorized) + return + } + fn(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") + ok, claims := a.validateToken(token) + if !ok { + w.WriteHeader(http.StatusUnauthorized) + return + } + num, ok := claims["num"].(float64) + if !ok { + w.WriteHeader(http.StatusUnauthorized) + return + } + role, ok := claims["role"].(string) + if !ok { + w.WriteHeader(http.StatusUnauthorized) + return + } + fn(int(num), role, w, req) + } +} + func (a *api) newToken(num int, role string) (string, error) { token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{ "num": num, diff --git a/api/auth_test.go b/api/auth_test.go index 534937f2b237ad3b16de212caa0e663d842a0b0f..3f5dbef69d9b39324c935a72463e56aaa4bd7035 100644 --- a/api/auth_test.go +++ b/api/auth_test.go @@ -15,6 +15,7 @@ func TestSignIn(t *testing.T) { } member.Num = 10 member.Name = "foo" + member.Role = "admin" member.Password = "password" resp := tapi.do("POST", "/member", member, nil) if resp.StatusCode != http.StatusCreated { diff --git a/api/member.go b/api/member.go index 60fa3e587e8966a5491dc7e73883c5c723d39cea..b274b903aaa7f88ae4025a7a5e2db49fc3f89085 100644 --- a/api/member.go +++ b/api/member.go @@ -4,6 +4,7 @@ import ( "encoding/json" "log" "net/http" + "strconv" "github.com/gorilla/mux" "gorm.io/gorm" @@ -81,14 +82,19 @@ func (a *api) ListMembers(w http.ResponseWriter, req *http.Request) { func (a *api) GetMember(w http.ResponseWriter, req *http.Request) { vars := mux.Vars(req) + num, _ := strconv.Atoi(vars["num"]) + a.getMemberNum(num, w, req) +} + +func (a *api) getMemberNum(num int, w http.ResponseWriter, req *http.Request) { var member Member - err := a.db.Where("num = ?", vars["num"]).First(&member).Error + err := a.db.Where("num = ?", num).First(&member).Error if err != nil { if err.Error() == "record not found" { w.WriteHeader(http.StatusNotFound) return } - log.Printf("Can't get member %s: %v", vars["num"], err) + log.Printf("Can't get member %d: %v", num, err) w.WriteHeader(http.StatusInternalServerError) return } diff --git a/api/transaction.go b/api/transaction.go index ee73e3054fb2e65a6e8582cd6b3e1e02a60be0b5..59100ddcd9a5918c75b3233d0ca650ede837641f 100644 --- a/api/transaction.go +++ b/api/transaction.go @@ -42,7 +42,7 @@ func (a *api) ListTransactions(w http.ResponseWriter, req *http.Request) { } } -func (a *api) GetTransaction(w http.ResponseWriter, req *http.Request) { +func (a *api) GetTransaction(num int, role string, w http.ResponseWriter, req *http.Request) { vars := mux.Vars(req) var transaction Transaction err := a.db.Preload("Purchase.Product"). @@ -57,6 +57,12 @@ func (a *api) GetTransaction(w http.ResponseWriter, req *http.Request) { w.WriteHeader(http.StatusInternalServerError) return } + + if transaction.MemberNum != num && role != "admin" { + w.WriteHeader(http.StatusUnauthorized) + return + } + w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusOK) err = json.NewEncoder(w).Encode(transaction) diff --git a/src/Dashboard.js b/src/Dashboard.js index c8b9aa02bfb101e2d99a31a21013156066ee24ff..d6ebe60caea2980f6267d94df44e1a8e19c11d0f 100644 --- a/src/Dashboard.js +++ b/src/Dashboard.js @@ -19,7 +19,7 @@ class Dashboard extends React.Component { render() { return ( <Fetcher - url={"/api/member/"+this.context.num.toString()} + url={"/api/member/me"} onFetch={member => this.setState({ balance: member.balance, name: member.name})} > <Container> <Row> diff --git a/src/Head.js b/src/Head.js index 7422b9a003f5662ac92da4c84d88f05038ab476a..fe5da85cce0404a0f1c4e8bb9bdff9319e19f9f5 100644 --- a/src/Head.js +++ b/src/Head.js @@ -13,7 +13,6 @@ function Head(props) { <Nav className="mr-auto"> <Nav.Link href="/">Dashboard</Nav.Link> <Nav.Link href="/products">Productos</Nav.Link> - <Nav.Link href="/members">Socias</Nav.Link> </Nav> <Form inline> <Button