Added right check for namespaces

This commit is contained in:
konrad 2018-07-12 13:43:42 +02:00 committed by kolaente
parent fb4fa25f2f
commit bae9c7f35e
No known key found for this signature in database
GPG key ID: F40E70337AB24C9B
3 changed files with 38 additions and 33 deletions

View file

@ -70,18 +70,6 @@ func (n *Namespace) IsAdmin(user *User) bool {
return false 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 // CanWrite checks if a user has write access to a namespace
func (n *Namespace) CanWrite(user *User) bool { func (n *Namespace) CanWrite(user *User) bool {
// Owners always have access // Owners always have access
@ -115,7 +103,8 @@ func GetNamespaceByID(id int64) (namespace Namespace, err error) {
// ReadOne gets one namespace // ReadOne gets one namespace
func (n *Namespace) ReadOne(id int64) (err error) { 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 { if err != nil {
return return
} }
@ -124,6 +113,8 @@ func (n *Namespace) ReadOne(id int64) (err error) {
return ErrNamespaceDoesNotExist{ID: id} return ErrNamespaceDoesNotExist{ID: id}
} }
*n = getN
return return
} }
@ -174,3 +165,25 @@ func (n *Namespace) ReadAll(doer *User) (interface{}, error) {
return all, nil 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
}

View file

@ -30,18 +30,7 @@ func ShowNamespace(c echo.Context) error {
// "500": // "500":
// "$ref": "#/responses/Message" // "$ref": "#/responses/Message"
namespace, err := getNamespace(c) return echo.NewHTTPError(http.StatusNotImplemented)
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)
} }
func getNamespace(c echo.Context) (namespace models.Namespace, err error) { 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 { if err != nil {
return return
} }
err = user.HasNamespaceAccess(&namespace) if !namespace.CanRead(&user) {
if err != nil {
return return
} }

View file

@ -1,7 +1,6 @@
package crud package crud
import ( import (
"fmt"
"git.kolaente.de/konrad/list/models" "git.kolaente.de/konrad/list/models"
"github.com/labstack/echo" "github.com/labstack/echo"
"net/http" "net/http"
@ -16,9 +15,6 @@ func (c *WebHandler) ReadOneWeb(ctx echo.Context) error {
return echo.NewHTTPError(http.StatusBadRequest, "Invalid ID.") return echo.NewHTTPError(http.StatusBadRequest, "Invalid ID.")
} }
// TODO check rights
//c.CObject.CanRead(doer)
// Get our object // Get our object
err = c.CObject.ReadOne(id) err = c.CObject.ReadOne(id)
if err != nil { if err != nil {
@ -30,10 +26,18 @@ func (c *WebHandler) ReadOneWeb(ctx echo.Context) error {
return echo.NewHTTPError(http.StatusNotFound) return echo.NewHTTPError(http.StatusNotFound)
} }
fmt.Println(err)
return echo.NewHTTPError(http.StatusInternalServerError, "An error occured.") 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(&currentUser) {
return echo.NewHTTPError(http.StatusForbidden, "You don't have the right to see this")
}
return ctx.JSON(http.StatusOK, c.CObject) return ctx.JSON(http.StatusOK, c.CObject)
} }