Added methods to give users access to a list
This commit is contained in:
parent
d31f16aff1
commit
b1c3e92f66
10 changed files with 185 additions and 0 deletions
|
@ -25,3 +25,17 @@ Authorization: Bearer {{auth_token}}
|
|||
|
||||
###
|
||||
|
||||
# Get all users who have access to that list
|
||||
GET http://localhost:8080/api/v1/lists/10/users
|
||||
Authorization: Bearer {{auth_token}}
|
||||
|
||||
###
|
||||
|
||||
# Give a user access to that list
|
||||
PUT http://localhost:8080/api/v1/lists/1/users
|
||||
Authorization: Bearer {{auth_token}}
|
||||
Content-Type: application/json
|
||||
|
||||
{"user_id":2, "right": 5}
|
||||
|
||||
###
|
||||
|
|
|
@ -495,3 +495,38 @@ func IsErrCannotDeleteLastTeamMember(err error) bool {
|
|||
func (err ErrCannotDeleteLastTeamMember) Error() string {
|
||||
return fmt.Sprintf("This user is already a member of that team. [Team ID: %d, User ID: %d]", err.TeamID, err.UserID)
|
||||
}
|
||||
|
||||
// ====================
|
||||
// User <-> List errors
|
||||
// ====================
|
||||
|
||||
// ErrInvalidUserRight represents an error where a user right is invalid
|
||||
type ErrInvalidUserRight struct {
|
||||
Right UserRight
|
||||
}
|
||||
|
||||
// IsErrInvalidUserRight checks if an error is ErrInvalidUserRight.
|
||||
func IsErrInvalidUserRight(err error) bool {
|
||||
_, ok := err.(ErrInvalidUserRight)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrInvalidUserRight) Error() string {
|
||||
return fmt.Sprintf("The right is invalid [Right: %d]", err.Right)
|
||||
}
|
||||
|
||||
// ErrUserAlreadyHasAccess represents an error where a user already has access to a list/namespace
|
||||
type ErrUserAlreadyHasAccess struct {
|
||||
UserID int64
|
||||
ListID int64
|
||||
}
|
||||
|
||||
// IsErrUserAlreadyHasAccess checks if an error is ErrUserAlreadyHasAccess.
|
||||
func IsErrUserAlreadyHasAccess(err error) bool {
|
||||
_, ok := err.(ErrUserAlreadyHasAccess)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrUserAlreadyHasAccess) Error() string {
|
||||
return fmt.Sprintf("This user already has access to that list. [User ID: %d, List ID: %d]", err.UserID, err.ListID)
|
||||
}
|
||||
|
|
20
models/list_users.go
Normal file
20
models/list_users.go
Normal file
|
@ -0,0 +1,20 @@
|
|||
package models
|
||||
|
||||
// ListUser represents a list <-> user relation
|
||||
type ListUser struct {
|
||||
ID int64 `xorm:"int(11) autoincr not null unique pk" json:"id" param:"namespace"`
|
||||
UserID int64 `xorm:"int(11) not null" json:"user_id" param:"user"`
|
||||
ListID int64 `xorm:"int(11) not null" json:"list_id" param:"list"`
|
||||
Right TeamRight `xorm:"int(11)" json:"right"`
|
||||
|
||||
Created int64 `xorm:"created" json:"created"`
|
||||
Updated int64 `xorm:"updated" json:"updated"`
|
||||
|
||||
CRUDable `xorm:"-" json:"-"`
|
||||
Rights `xorm:"-" json:"-"`
|
||||
}
|
||||
|
||||
// TableName is the table name for ListUser
|
||||
func (ListUser) TableName() string {
|
||||
return "users_list"
|
||||
}
|
40
models/list_users_create.go
Normal file
40
models/list_users_create.go
Normal file
|
@ -0,0 +1,40 @@
|
|||
package models
|
||||
|
||||
// Create creates a new list <-> user relation
|
||||
func (ul *ListUser) Create(user *User) (err error) {
|
||||
|
||||
// Check if the right is valid
|
||||
if err := ul.Right.isValid(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Check if the list exists
|
||||
l, err := GetListByID(ul.ListID)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Check if the user exists
|
||||
if _, _, err = GetUserByID(ul.UserID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Check if the user already has access or is owner of that list
|
||||
// We explicitly DONT check for teams here
|
||||
if l.OwnerID == ul.UserID {
|
||||
return ErrUserAlreadyHasAccess{UserID: ul.UserID, ListID: ul.ListID}
|
||||
}
|
||||
|
||||
exist, err := x.Where("list_id = ? AND user_id = ?", ul.ListID, ul.UserID).Get(&ListUser{})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if exist {
|
||||
return ErrUserAlreadyHasAccess{UserID: ul.UserID, ListID: ul.ListID}
|
||||
}
|
||||
|
||||
// Insert user <-> list relation
|
||||
_, err = x.Insert(ul)
|
||||
|
||||
return
|
||||
}
|
23
models/list_users_readall.go
Normal file
23
models/list_users_readall.go
Normal file
|
@ -0,0 +1,23 @@
|
|||
package models
|
||||
|
||||
// ReadAll gets all users who have access to a list
|
||||
func (ul *ListUser) ReadAll(user *User) (interface{}, error) {
|
||||
// Check if the user has access to the list
|
||||
l, err := GetListByID(ul.ListID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !l.CanRead(user) {
|
||||
return nil, ErrNeedToHaveListReadAccess{}
|
||||
}
|
||||
|
||||
// Get all users
|
||||
all := []*User{}
|
||||
err = x.
|
||||
Select("users.*").
|
||||
Join("INNER", "users_list", "user_id = users.id").
|
||||
Where("users_list.list_id = ?", ul.ListID).
|
||||
Find(&all)
|
||||
|
||||
return all, err
|
||||
}
|
34
models/list_users_rights.go
Normal file
34
models/list_users_rights.go
Normal file
|
@ -0,0 +1,34 @@
|
|||
package models
|
||||
|
||||
// UserRight defines the rights users can have for lists/namespaces
|
||||
type UserRight int
|
||||
|
||||
// define unknown user right
|
||||
const (
|
||||
UserRightUnknown = -1
|
||||
)
|
||||
|
||||
// Enumerate all the user rights
|
||||
const (
|
||||
// Can read lists in a User
|
||||
UserRightRead UserRight = iota
|
||||
// Can write tasks in a User like lists and todo tasks. Cannot create new lists.
|
||||
UserRightWrite
|
||||
// Can manage a list/namespace, can do everything
|
||||
UserRightAdmin
|
||||
)
|
||||
|
||||
func (r UserRight) isValid() error {
|
||||
if r != UserRightAdmin && r != UserRightRead && r != UserRightWrite {
|
||||
return ErrInvalidUserRight{r}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// CanCreate checks if the user can create a new user <-> list relation
|
||||
func (lu *ListUser) CanCreate(doer *User) bool {
|
||||
// Get the list and check if the user has write access on it
|
||||
l, _ := GetListByID(lu.ListID)
|
||||
return l.CanWrite(doer)
|
||||
}
|
|
@ -40,6 +40,7 @@ func init() {
|
|||
new(TeamList),
|
||||
new(TeamNamespace),
|
||||
new(Namespace),
|
||||
new(ListUser),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -63,6 +63,13 @@ func (c *WebHandler) CreateWeb(ctx echo.Context) error {
|
|||
return echo.NewHTTPError(http.StatusBadRequest, "This user is already a member of that team.")
|
||||
}
|
||||
|
||||
if models.IsErrUserAlreadyHasAccess(err) {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, "This user already has access to this list.")
|
||||
}
|
||||
if models.IsErrInvalidUserRight(err) {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, "The right is invalid.")
|
||||
}
|
||||
|
||||
return echo.NewHTTPError(http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,10 @@ func (c *WebHandler) ReadAllWeb(ctx echo.Context) error {
|
|||
|
||||
lists, err := c.CObject.ReadAll(¤tUser)
|
||||
if err != nil {
|
||||
if models.IsErrNeedToHaveListReadAccess(err) {
|
||||
return echo.NewHTTPError(http.StatusForbidden, "You need to have read access to this list.")
|
||||
}
|
||||
|
||||
return echo.NewHTTPError(http.StatusInternalServerError, "An error occured.")
|
||||
}
|
||||
|
||||
|
|
|
@ -110,6 +110,13 @@ func RegisterRoutes(e *echo.Echo) {
|
|||
a.PUT("/lists/:list/teams", listTeamHandler.CreateWeb)
|
||||
a.DELETE("/lists/:list/teams/:team", listTeamHandler.DeleteWeb)
|
||||
|
||||
listUserHandler := &crud.WebHandler{
|
||||
CObject: &models.ListUser{},
|
||||
}
|
||||
a.GET("/lists/:list/users", listUserHandler.ReadAllWeb)
|
||||
a.PUT("/lists/:list/users", listUserHandler.CreateWeb)
|
||||
a.DELETE("/lists/:list/users/:user", listUserHandler.DeleteWeb)
|
||||
|
||||
namespaceHandler := &crud.WebHandler{
|
||||
CObject: &models.Namespace{},
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue