diff --git a/models/crudable.go b/models/crudable.go index 206c9b34..0a85b6ae 100644 --- a/models/crudable.go +++ b/models/crudable.go @@ -2,7 +2,7 @@ package models // CRUDable defines the crud methods type CRUDable interface { - Create(*User) error + Create(*User, int64) error ReadOne(int64) error ReadAll(*User) (interface{}, error) Update(int64, *User) error diff --git a/models/error.go b/models/error.go index e6f2b1b1..a25efa4c 100644 --- a/models/error.go +++ b/models/error.go @@ -159,6 +159,22 @@ func (err ErrNeedToBeListAdmin) Error() string { return fmt.Sprintf("You need to be list owner to do that [ListID: %d, UserID: %d]", err.ListID, err.UserID) } +// ErrNeedToBeListWriter represents an error, where the user is not the owner of that list (used i.e. when deleting a list) +type ErrNeedToBeListWriter struct { + ListID int64 + UserID int64 +} + +// IsErrNeedToBeListWriter checks if an error is a ErrListDoesNotExist. +func IsErrNeedToBeListWriter(err error) bool { + _, ok := err.(ErrNeedToBeListWriter) + return ok +} + +func (err ErrNeedToBeListWriter) Error() string { + return fmt.Sprintf("You need to have write acces to the list to do that [ListID: %d, UserID: %d]", err.ListID, err.UserID) +} + // ================ // List item errors // ================ diff --git a/models/list_create_update.go b/models/list_create_update.go index 04ba48a6..17063b3c 100644 --- a/models/list_create_update.go +++ b/models/list_create_update.go @@ -43,7 +43,7 @@ func (l *List) Update(id int64, doer *User) (err error) { } // Create implements the create method of CRUDable -func (l *List) Create(doer *User) (err error) { +func (l *List) Create(doer *User, id int64) (err error) { // Check rights user, _, err := GetUserByID(doer.ID) if err != nil { diff --git a/models/list_items.go b/models/list_items.go index 53977e68..6edab85a 100644 --- a/models/list_items.go +++ b/models/list_items.go @@ -14,6 +14,9 @@ type ListItem struct { Updated int64 `xorm:"updated" json:"updated"` CreatedBy User `xorm:"-" json:"createdBy"` + + CRUDable `xorm:"-" json:"-"` + Rights `xorm:"-" json:"-"` } // TableName returns the table name for listitems diff --git a/models/list_items_create_update.go b/models/list_items_create_update.go index 3c082a5e..da501292 100644 --- a/models/list_items_create_update.go +++ b/models/list_items_create_update.go @@ -38,3 +38,38 @@ func CreateOrUpdateListItem(item *ListItem) (newItem *ListItem, err error) { return &finalItem, err } + +// Create is the implementation to create a list item +func (i *ListItem) Create(doer *User, lID int64) (err error) { + i.ListID = lID + + // Check rights + user, _, err := GetUserByID(doer.ID) + if err != nil { + return + } + i.CreatedBy = user // Needed because we return the full item object + i.CreatedByID = user.ID + + // Get the list to check if the user has the right to write to that list + list, err := GetListByID(lID) + if err != nil { + return + } + + if !list.CanWrite(&user) { + return ErrNeedToBeListWriter{ListID: lID, UserID: user.ID} + } + + // Check if we have at least a text + if i.Text == "" { + return ErrListItemCannotBeEmpty{} + } + + _, err = x.Insert(i) + if err != nil { + return + } + + return +} diff --git a/models/lists.go b/models/lists.go index 62e6b160..c39e18e8 100644 --- a/models/lists.go +++ b/models/lists.go @@ -90,5 +90,33 @@ func (l *List) IsAdmin(user *User) bool { // Check Namespace rights // TODO + // Check individual rights + // TODO + return false } + +// CanWrite return whether the user can write on that list or not +func (l *List) CanWrite(user *User) bool { + // Admins always have write access + if l.IsAdmin(user) { + return true + } + + // Owners always have write access + if l.Owner.ID == user.ID { + return true + } + + // Check Namespace rights + // TODO + // TODO find a way to prioritize: what happens if a user has namespace write access but is not in that list? + + // Check Team rights + // TODO + + // Check individual rights + // TODO + + return false +} \ No newline at end of file diff --git a/routes/crud/create.go b/routes/crud/create.go index 9284a91a..6881d0ce 100644 --- a/routes/crud/create.go +++ b/routes/crud/create.go @@ -1,10 +1,9 @@ package crud import ( + "git.kolaente.de/konrad/list/models" "github.com/labstack/echo" "net/http" - "fmt" - "git.kolaente.de/konrad/list/models" ) // CreateWeb is the handler to create an object @@ -23,18 +22,30 @@ func (c *WebHandler) CreateWeb(ctx echo.Context) error { // Get an ID if we have one var id int64 = 0 if ctx.Param("id") != "" { - id, err := models.GetIntURLParam("id", ctx) + id, err = models.GetIntURLParam("id", ctx) if err != nil { - + return echo.NewHTTPError(http.StatusBadRequest, "Bad id.") } } // Create - err = c.CObject.Create(¤tUser) + err = c.CObject.Create(¤tUser, id) if err != nil { - fmt.Println(err) + if models.IsErrListDoesNotExist(err) { + return echo.NewHTTPError(http.StatusBadRequest, "The list does not exist.") + } + if models.IsErrListItemCannotBeEmpty(err) { + return echo.NewHTTPError(http.StatusBadRequest, "You must provide at least a list item text.") + } + if models.IsErrUserDoesNotExist(err) { + return echo.NewHTTPError(http.StatusBadRequest, "The user does not exist.") + } + if models.IsErrNeedToBeListWriter(err) { + return echo.NewHTTPError(http.StatusForbidden, "You need to have write access on that list.") + } + return echo.NewHTTPError(http.StatusInternalServerError) } return ctx.JSON(http.StatusOK, c.CObject) -} \ No newline at end of file +} diff --git a/routes/crud/delete.go b/routes/crud/delete.go index 611e8d41..95d895be 100644 --- a/routes/crud/delete.go +++ b/routes/crud/delete.go @@ -1,9 +1,9 @@ package crud import ( + "git.kolaente.de/konrad/list/models" "github.com/labstack/echo" "net/http" - "git.kolaente.de/konrad/list/models" ) // DeleteWeb is the web handler to delete something @@ -34,4 +34,4 @@ func (c *WebHandler) DeleteWeb(ctx echo.Context) error { } return ctx.JSON(http.StatusOK, models.Message{"Successfully deleted."}) -} \ No newline at end of file +} diff --git a/routes/crud/read_all.go b/routes/crud/read_all.go index 36938a03..188c6961 100644 --- a/routes/crud/read_all.go +++ b/routes/crud/read_all.go @@ -1,10 +1,10 @@ package crud import ( - "github.com/labstack/echo" - "net/http" "fmt" "git.kolaente.de/konrad/list/models" + "github.com/labstack/echo" + "net/http" ) // ReadAllWeb is the webhandler to get all objects of a type @@ -21,4 +21,4 @@ func (c *WebHandler) ReadAllWeb(ctx echo.Context) error { } return ctx.JSON(http.StatusOK, lists) -} \ No newline at end of file +} diff --git a/routes/crud/read_one.go b/routes/crud/read_one.go index 38b7d21a..d78c7799 100644 --- a/routes/crud/read_one.go +++ b/routes/crud/read_one.go @@ -1,8 +1,8 @@ package crud import ( - "github.com/labstack/echo" "git.kolaente.de/konrad/list/models" + "github.com/labstack/echo" "net/http" ) diff --git a/routes/crud/update.go b/routes/crud/update.go index 9a05cacd..b43673ba 100644 --- a/routes/crud/update.go +++ b/routes/crud/update.go @@ -1,9 +1,9 @@ package crud import ( + "git.kolaente.de/konrad/list/models" "github.com/labstack/echo" "net/http" - "git.kolaente.de/konrad/list/models" ) // UpdateWeb is the webhandler to update an object diff --git a/routes/routes.go b/routes/routes.go index 362b7895..e78dbf41 100644 --- a/routes/routes.go +++ b/routes/routes.go @@ -93,9 +93,13 @@ func RegisterRoutes(e *echo.Echo) { a.GET("/lists", listHandler.ReadAllWeb) a.GET("/lists/:id", listHandler.ReadOneWeb) a.POST("/lists/:id", listHandler.UpdateWeb) - a.PUT("/lists/:id", apiv1.AddListItem) a.DELETE("/lists/:id", listHandler.DeleteWeb) + a.PUT("/namespaces/:id/lists", listHandler.CreateWeb) + itemHandler := &crud.WebHandler{ + CObject: &models.ListItem{}, + } + a.PUT("/lists/:id", itemHandler.CreateWeb) a.DELETE("/item/:id", apiv1.DeleteListItemByIDtemByID) a.POST("/item/:id", apiv1.UpdateListItem) @@ -105,5 +109,4 @@ func RegisterRoutes(e *echo.Echo) { a.POST("/namespaces/:id", apiv1.UpdateNamespace) a.DELETE("/namespaces/:id", apiv1.DeleteNamespaceByID) a.GET("/namespaces/:id/lists", apiv1.GetListsByNamespaceID) - a.PUT("/namespaces/:id/lists", listHandler.CreateWeb) }