diff --git a/auth/BasicAuthManager.go b/auth/BasicAuthManager.go new file mode 100644 index 0000000..1589742 --- /dev/null +++ b/auth/BasicAuthManager.go @@ -0,0 +1,35 @@ +package auth + +import ( + "net/http" + + cdata "github.com/pip-services3-go/pip-services3-commons-go/data" + cerr "github.com/pip-services3-go/pip-services3-commons-go/errors" + services "github.com/pip-services3-go/pip-services3-rpc-go/services" +) + +type BasicAuthManager struct { +} + +func (c *BasicAuthManager) Anybody() func(res http.ResponseWriter, req *http.Request, next http.HandlerFunc) { + return func(res http.ResponseWriter, req *http.Request, next http.HandlerFunc) { + next.ServeHTTP(res, req) + } +} + +func (c *BasicAuthManager) Signed() func(res http.ResponseWriter, req *http.Request, next http.HandlerFunc) { + return func(res http.ResponseWriter, req *http.Request, next http.HandlerFunc) { + _, ok := req.Context().Value("user").(cdata.AnyValueMap) + if !ok { + services.HttpResponseSender.SendError( + res, req, + cerr.NewUnauthorizedError("", + "NOT_SIGNED", + "User must be signed in to perform this operation", + ).WithStatus(401), + ) + } else { + next.ServeHTTP(res, req) + } + } +} diff --git a/auth/OwnerAuthManager.go b/auth/OwnerAuthManager.go new file mode 100644 index 0000000..f59797a --- /dev/null +++ b/auth/OwnerAuthManager.go @@ -0,0 +1,99 @@ +package auth + +import ( + "net/http" + + "github.com/gorilla/mux" + cdata "github.com/pip-services3-go/pip-services3-commons-go/data" + cerr "github.com/pip-services3-go/pip-services3-commons-go/errors" + services "github.com/pip-services3-go/pip-services3-rpc-go/services" +) + +type OwnerAuthManager struct { +} + +func (c *OwnerAuthManager) Owner(idParam string) func(res http.ResponseWriter, req *http.Request, next http.HandlerFunc) { + if idParam == "" { + idParam = "user_id" + } + return func(res http.ResponseWriter, req *http.Request, next http.HandlerFunc) { + + _, ok := req.Context().Value("user").(cdata.AnyValueMap) + + if !ok { + services.HttpResponseSender.SendError( + res, req, + cerr.NewUnauthorizedError("", + "NOT_SIGNED", + "User must be signed in to perform this operation", + ).WithStatus(401), + ) + } else { + userId := req.URL.Query().Get(idParam) + if userId == "" { + userId = mux.Vars(req)[idParam] + } + + reqUserId, ok := req.Context().Value("user_id").(string) + if !ok || reqUserId != userId { + services.HttpResponseSender.SendError( + res, req, + cerr.NewUnauthorizedError( + "", "FORBIDDEN", + "Only data owner can perform this operation", + ).WithStatus(403), + ) + } else { + next.ServeHTTP(res, req) + } + } + } +} + +func (c *OwnerAuthManager) OwnerOrAdmin(idParam string) func(res http.ResponseWriter, req *http.Request, next http.HandlerFunc) { + if idParam == "" { + idParam = "user_id" + } + return func(res http.ResponseWriter, req *http.Request, next http.HandlerFunc) { + + user, ok := req.Context().Value("user").(cdata.AnyValueMap) + + if !ok { + services.HttpResponseSender.SendError( + res, req, + cerr.NewUnauthorizedError("", + "NOT_SIGNED", + "User must be signed in to perform this operation", + ).WithStatus(401), + ) + } else { + + userId := req.URL.Query().Get(idParam) + if userId == "" { + userId = mux.Vars(req)[idParam] + } + roles := user.GetAsArray("roles") + admin := false + for _, role := range roles.Value() { + r, ok := role.(string) + if ok && r == "admin" { + admin = true + break + } + } + + reqUserId, ok := req.Context().Value("user_id").(string) + if !ok || reqUserId != userId && !admin { + services.HttpResponseSender.SendError( + res, req, + cerr.NewUnauthorizedError("", + "FORBIDDEN", + "Only data owner can perform this operation", + ).WithStatus(403), + ) + } else { + next.ServeHTTP(res, req) + } + } + } +} diff --git a/auth/RoleAuthManager.go b/auth/RoleAuthManager.go new file mode 100644 index 0000000..2f36d1c --- /dev/null +++ b/auth/RoleAuthManager.go @@ -0,0 +1,64 @@ +package auth + +import ( + "net/http" + "strings" + + cdata "github.com/pip-services3-go/pip-services3-commons-go/data" + cerr "github.com/pip-services3-go/pip-services3-commons-go/errors" + services "github.com/pip-services3-go/pip-services3-rpc-go/services" +) + +type RoleAuthManager struct { +} + +func (c *RoleAuthManager) UserInRoles(roles []string) func(res http.ResponseWriter, req *http.Request, next http.HandlerFunc) { + return func(res http.ResponseWriter, req *http.Request, next http.HandlerFunc) { + + user, ok := req.Context().Value("user").(cdata.AnyValueMap) + if !ok { + services.HttpResponseSender.SendError( + res, req, + cerr.NewUnauthorizedError("", "NOT_SIGNED", + "User must be signed in to perform this operation").WithStatus(401)) + } else { + authorized := false + userRoles := user.GetAsArray("roles") + + if userRoles == nil { + services.HttpResponseSender.SendError( + res, req, + cerr.NewUnauthorizedError("", "NOT_SIGNED", + "User must be signed in to perform this operation").WithStatus(401)) + return + } + + for _, role := range roles { + for _, userRole := range userRoles.Value() { + r, ok := userRole.(string) + if ok && role == r { + authorized = true + } + } + } + + if !authorized { + services.HttpResponseSender.SendError( + res, req, + cerr.NewUnauthorizedError( + "", "NOT_IN_ROLE", + "User must be "+strings.Join(roles, " or ")+" to perform this operation").WithDetails("roles", roles).WithStatus(403)) + } else { + next.ServeHTTP(res, req) + } + } + } +} + +func (c *RoleAuthManager) UserInRole(role string) func(res http.ResponseWriter, req *http.Request, next http.HandlerFunc) { + return c.UserInRoles([]string{role}) +} + +func (c *RoleAuthManager) Admin() func(res http.ResponseWriter, req *http.Request, next http.HandlerFunc) { + return c.UserInRole("admin") +}