From bae9c7f35e97a9674f618df1ed752186827da981 Mon Sep 17 00:00:00 2001 From: konrad Date: Thu, 12 Jul 2018 13:43:42 +0200 Subject: [PATCH] Added right check for namespaces --- models/namespaces.go | 39 ++++++++++++++++++++++----------- routes/api/v1/namespace_show.go | 16 ++------------ routes/crud/read_one.go | 16 +++++++++----- 3 files changed, 38 insertions(+), 33 deletions(-) diff --git a/models/namespaces.go b/models/namespaces.go index 94c17c80daa..03db3a0695b 100644 --- a/models/namespaces.go +++ b/models/namespaces.go @@ -70,18 +70,6 @@ func (n *Namespace) IsAdmin(user *User) bool { return false } -// HasNamespaceAccess checks if the User has namespace read access -func (user *User) HasNamespaceAccess(namespace *Namespace) (err error) { - // Owners always have access - if user.ID == namespace.Owner.ID { - return nil - } - - // Check if the user is in a team which has access to the namespace - - return ErrUserDoesNotHaveAccessToNamespace{UserID: user.ID, NamespaceID: namespace.ID} -} - // CanWrite checks if a user has write access to a namespace func (n *Namespace) CanWrite(user *User) bool { // Owners always have access @@ -115,7 +103,8 @@ func GetNamespaceByID(id int64) (namespace Namespace, err error) { // ReadOne gets one namespace func (n *Namespace) ReadOne(id int64) (err error) { - exists, err := x.ID(id).Get(n) + getN := Namespace{} + exists, err := x.ID(id).Get(&getN) if err != nil { return } @@ -124,6 +113,8 @@ func (n *Namespace) ReadOne(id int64) (err error) { return ErrNamespaceDoesNotExist{ID: id} } + *n = getN + return } @@ -174,3 +165,25 @@ func (n *Namespace) ReadAll(doer *User) (interface{}, error) { return all, nil } + +func (n *Namespace) CanRead(user *User) bool { + // Owners always have access + if user.ID == n.Owner.ID { + return true + } + + // Check if the user is in a team which has access to the namespace + all := Namespace{} + // TODO respect individual rights + exists, _ := x.Select("namespaces.*"). + Table("namespaces"). + Join("LEFT", "team_namespaces", "namespaces.id = team_namespaces.namespace_id"). + Join("LEFT", "team_members", "team_members.team_id = team_namespaces.team_id"). + Where("team_members.user_id = ?", user.ID). + Or("namespaces.owner_id = ?", user.ID). + And("namespaces.id = ?", n.ID). + GroupBy("namespaces.id"). + Get(&all) + + return exists +} diff --git a/routes/api/v1/namespace_show.go b/routes/api/v1/namespace_show.go index 071dcf65d97..e96bd77bd24 100644 --- a/routes/api/v1/namespace_show.go +++ b/routes/api/v1/namespace_show.go @@ -30,18 +30,7 @@ func ShowNamespace(c echo.Context) error { // "500": // "$ref": "#/responses/Message" - namespace, err := getNamespace(c) - if err != nil { - if models.IsErrNamespaceDoesNotExist(err) { - return c.JSON(http.StatusNotFound, models.Message{"Namespace not found."}) - } - if models.IsErrUserDoesNotHaveAccessToNamespace(err) { - return c.JSON(http.StatusForbidden, models.Message{"You don't have access to this namespace."}) - } - return c.JSON(http.StatusInternalServerError, models.Message{"An error occured."}) - } - - return c.JSON(http.StatusOK, namespace) + return echo.NewHTTPError(http.StatusNotImplemented) } func getNamespace(c echo.Context) (namespace models.Namespace, err error) { @@ -64,8 +53,7 @@ func getNamespace(c echo.Context) (namespace models.Namespace, err error) { if err != nil { return } - err = user.HasNamespaceAccess(&namespace) - if err != nil { + if !namespace.CanRead(&user) { return } diff --git a/routes/crud/read_one.go b/routes/crud/read_one.go index 6ddd0df1b74..8b8250c0c31 100644 --- a/routes/crud/read_one.go +++ b/routes/crud/read_one.go @@ -1,7 +1,6 @@ package crud import ( - "fmt" "git.kolaente.de/konrad/list/models" "github.com/labstack/echo" "net/http" @@ -16,9 +15,6 @@ func (c *WebHandler) ReadOneWeb(ctx echo.Context) error { return echo.NewHTTPError(http.StatusBadRequest, "Invalid ID.") } - // TODO check rights - //c.CObject.CanRead(doer) - // Get our object err = c.CObject.ReadOne(id) if err != nil { @@ -30,10 +26,18 @@ func (c *WebHandler) ReadOneWeb(ctx echo.Context) error { return echo.NewHTTPError(http.StatusNotFound) } - fmt.Println(err) - return echo.NewHTTPError(http.StatusInternalServerError, "An error occured.") } + // Check rights + // We can only check the rights on a full object, which is why we need to check it afterwards + currentUser, err := models.GetCurrentUser(ctx) + if err != nil { + return echo.NewHTTPError(http.StatusInternalServerError, "Could not determine the current user.") + } + if !c.CObject.CanRead(¤tUser) { + return echo.NewHTTPError(http.StatusForbidden, "You don't have the right to see this") + } + return ctx.JSON(http.StatusOK, c.CObject) }