New structure #7
12
main.go
12
main.go
|
@ -1,9 +1,11 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/models"
|
||||
"code.vikunja.io/api/models/mail"
|
||||
"code.vikunja.io/api/routes"
|
||||
"code.vikunja.io/api/pkg/config"
|
||||
"code.vikunja.io/api/pkg/log"
|
||||
"code.vikunja.io/api/pkg/mail"
|
||||
"code.vikunja.io/api/pkg/models"
|
||||
"code.vikunja.io/api/pkg/routes"
|
||||
|
||||
"context"
|
||||
"github.com/spf13/viper"
|
||||
|
@ -18,10 +20,10 @@ var Version = "0.1"
|
|||
func main() {
|
||||
|
||||
// Init logging
|
||||
models.InitLogger()
|
||||
log.InitLogger()
|
||||
|
||||
// Init Config
|
||||
err := models.InitConfig()
|
||||
err := config.InitConfig()
|
||||
if err != nil {
|
||||
models.Log.Error(err.Error())
|
||||
os.Exit(1)
|
||||
|
|
|
@ -1,39 +0,0 @@
|
|||
package models
|
||||
|
||||
// CanDelete checks if the user can delete an task
|
||||
func (i *ListTask) CanDelete(doer *User) bool {
|
||||
// Get the task
|
||||
lI, err := GetListTaskByID(i.ID)
|
||||
if err != nil {
|
||||
Log.Error("Error occurred during CanDelete for ListTask: %s", err)
|
||||
return false
|
||||
}
|
||||
|
||||
// A user can delete an task if he has write acces to its list
|
||||
list := &List{ID: lI.ListID}
|
||||
list.ReadOne()
|
||||
return list.CanWrite(doer)
|
||||
}
|
||||
|
||||
// CanUpdate determines if a user has the right to update a list task
|
||||
func (i *ListTask) CanUpdate(doer *User) bool {
|
||||
// Get the task
|
||||
lI, err := GetListTaskByID(i.ID)
|
||||
if err != nil {
|
||||
Log.Error("Error occurred during CanDelete for ListTask: %s", err)
|
||||
return false
|
||||
}
|
||||
|
||||
// A user can update an task if he has write acces to its list
|
||||
list := &List{ID: lI.ListID}
|
||||
list.ReadOne()
|
||||
return list.CanWrite(doer)
|
||||
}
|
||||
|
||||
// CanCreate determines if a user has the right to create a list task
|
||||
func (i *ListTask) CanCreate(doer *User) bool {
|
||||
// A user can create an task if he has write acces to its list
|
||||
list := &List{ID: i.ListID}
|
||||
list.ReadOne()
|
||||
return list.CanWrite(doer)
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
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 INDEX" json:"user_id" param:"user"`
|
||||
ListID int64 `xorm:"int(11) not null INDEX" json:"list_id" param:"list"`
|
||||
Right UserRight `xorm:"int(11) INDEX" 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"
|
||||
}
|
||||
|
||||
type userWithRight struct {
|
||||
User `xorm:"extends"`
|
||||
Right UserRight `json:"right"`
|
||||
}
|
|
@ -1,60 +0,0 @@
|
|||
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 := List{ID: lu.ListID}
|
||||
if err := l.GetSimpleByID(); err != nil {
|
||||
Log.Error("Error occurred during CanCreate for ListUser: %s", err)
|
||||
return false
|
||||
}
|
||||
return l.CanWrite(doer)
|
||||
}
|
||||
|
||||
// CanDelete checks if the user can delete a user <-> list relation
|
||||
func (lu *ListUser) CanDelete(doer *User) bool {
|
||||
// Get the list and check if the user has write access on it
|
||||
l := List{ID: lu.ListID}
|
||||
if err := l.GetSimpleByID(); err != nil {
|
||||
Log.Error("Error occurred during CanDelete for ListUser: %s", err)
|
||||
return false
|
||||
}
|
||||
return l.CanWrite(doer)
|
||||
}
|
||||
|
||||
// CanUpdate checks if the user can update a user <-> list relation
|
||||
func (lu *ListUser) CanUpdate(doer *User) bool {
|
||||
// Get the list and check if the user has write access on it
|
||||
l := List{ID: lu.ListID}
|
||||
if err := l.GetSimpleByID(); err != nil {
|
||||
Log.Error("Error occurred during CanUpdate for ListUser: %s", err)
|
||||
return false
|
||||
}
|
||||
return l.CanWrite(doer)
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
package models
|
||||
|
||||
// NamespaceUser represents a namespace <-> user relation
|
||||
type NamespaceUser struct {
|
||||
ID int64 `xorm:"int(11) autoincr not null unique pk" json:"id" param:"namespace"`
|
||||
UserID int64 `xorm:"int(11) not null INDEX" json:"user_id" param:"user"`
|
||||
NamespaceID int64 `xorm:"int(11) not null INDEX" json:"namespace_id" param:"namespace"`
|
||||
Right UserRight `xorm:"int(11) INDEX" 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 NamespaceUser
|
||||
func (NamespaceUser) TableName() string {
|
||||
return "users_namespace"
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
package models
|
||||
|
||||
// CanCreate checks if the user can create a new user <-> namespace relation
|
||||
func (nu *NamespaceUser) CanCreate(doer *User) bool {
|
||||
// Get the namespace and check if the user has write access on it
|
||||
n, err := GetNamespaceByID(nu.NamespaceID)
|
||||
if err != nil {
|
||||
Log.Error("Error occurred during CanCreate for NamespaceUser: %s", err)
|
||||
return false
|
||||
}
|
||||
return n.CanWrite(doer)
|
||||
}
|
||||
|
||||
// CanDelete checks if the user can delete a user <-> namespace relation
|
||||
func (nu *NamespaceUser) CanDelete(doer *User) bool {
|
||||
// Get the namespace and check if the user has write access on it
|
||||
n, err := GetNamespaceByID(nu.NamespaceID)
|
||||
if err != nil {
|
||||
Log.Error("Error occurred during CanCreate for NamespaceUser: %s", err)
|
||||
return false
|
||||
}
|
||||
return n.CanWrite(doer)
|
||||
}
|
||||
|
||||
// CanUpdate checks if the user can update a user <-> namespace relation
|
||||
func (nu *NamespaceUser) CanUpdate(doer *User) bool {
|
||||
// Get the namespace and check if the user has write access on it
|
||||
n, err := GetNamespaceByID(nu.NamespaceID)
|
||||
if err != nil {
|
||||
Log.Error("Error occurred during CanCreate for NamespaceUser: %s", err)
|
||||
return false
|
||||
}
|
||||
return n.CanWrite(doer)
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
package models
|
||||
|
||||
// Rights defines rights methods
|
||||
type Rights interface {
|
||||
IsAdmin(*User) bool
|
||||
CanWrite(*User) bool
|
||||
CanRead(*User) bool
|
||||
CanDelete(*User) bool
|
||||
CanUpdate(*User) bool
|
||||
CanCreate(*User) bool
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
package models
|
||||
|
||||
// TeamList defines the relation between a team and a list
|
||||
type TeamList struct {
|
||||
ID int64 `xorm:"int(11) autoincr not null unique pk" json:"id"`
|
||||
TeamID int64 `xorm:"int(11) not null INDEX" json:"team_id" param:"team"`
|
||||
ListID int64 `xorm:"int(11) not null INDEX" json:"list_id" param:"list"`
|
||||
Right TeamRight `xorm:"int(11) INDEX" json:"right"`
|
||||
|
||||
Created int64 `xorm:"created" json:"created"`
|
||||
Updated int64 `xorm:"updated" json:"updated"`
|
||||
|
||||
CRUDable `xorm:"-" json:"-"`
|
||||
Rights `xorm:"-" json:"-"`
|
||||
}
|
||||
|
||||
// TableName makes beautiful table names
|
||||
func (TeamList) TableName() string {
|
||||
return "team_list"
|
||||
}
|
||||
|
||||
type teamWithRight struct {
|
||||
Team `xorm:"extends"`
|
||||
Right TeamRight `json:"right"`
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
package models
|
||||
|
||||
// CanCreate checks if the user can create a team <-> list relation
|
||||
func (tl *TeamList) CanCreate(user *User) bool {
|
||||
l := List{ID: tl.ListID}
|
||||
if err := l.GetSimpleByID(); err != nil {
|
||||
Log.Error("Error occurred during CanCreate for TeamList: %s", err)
|
||||
return false
|
||||
}
|
||||
return l.IsAdmin(user)
|
||||
}
|
||||
|
||||
// CanDelete checks if the user can delete a team <-> list relation
|
||||
func (tl *TeamList) CanDelete(user *User) bool {
|
||||
l := List{ID: tl.ListID}
|
||||
if err := l.GetSimpleByID(); err != nil {
|
||||
Log.Error("Error occurred during CanDelete for TeamList: %s", err)
|
||||
return false
|
||||
}
|
||||
return l.IsAdmin(user)
|
||||
}
|
||||
|
||||
// CanUpdate checks if the user can update a team <-> list relation
|
||||
func (tl *TeamList) CanUpdate(user *User) bool {
|
||||
l := List{ID: tl.ListID}
|
||||
if err := l.GetSimpleByID(); err != nil {
|
||||
Log.Error("Error occurred during CanUpdate for TeamList: %s", err)
|
||||
return false
|
||||
}
|
||||
return l.IsAdmin(user)
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
package models
|
||||
|
||||
// CanCreate checks if the user can add a new tem member
|
||||
func (tm *TeamMember) CanCreate(user *User) bool {
|
||||
return tm.IsAdmin(user)
|
||||
}
|
||||
|
||||
// CanDelete checks if the user can delete a new team member
|
||||
func (tm *TeamMember) CanDelete(user *User) bool {
|
||||
return tm.IsAdmin(user)
|
||||
}
|
||||
|
||||
// IsAdmin checks if the user is team admin
|
||||
func (tm *TeamMember) IsAdmin(user *User) bool {
|
||||
// A user can add a member to a team if he is admin of that team
|
||||
exists, err := x.Where("user_id = ? AND team_id = ? AND admin = ?", user.ID, tm.TeamID, true).
|
||||
Get(&TeamMember{})
|
||||
if err != nil {
|
||||
Log.Error("Error occurred during IsAdmin for TeamMember: %s", err)
|
||||
return false
|
||||
}
|
||||
return exists
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
package models
|
||||
|
||||
// TeamNamespace defines the relationship between a Team and a Namespace
|
||||
type TeamNamespace struct {
|
||||
ID int64 `xorm:"int(11) autoincr not null unique pk" json:"id"`
|
||||
TeamID int64 `xorm:"int(11) not null INDEX" json:"team_id" param:"team"`
|
||||
NamespaceID int64 `xorm:"int(11) not null INDEX" json:"namespace_id" param:"namespace"`
|
||||
Right TeamRight `xorm:"int(11) INDEX" json:"right"`
|
||||
|
||||
Created int64 `xorm:"created" json:"created"`
|
||||
Updated int64 `xorm:"updated" json:"updated"`
|
||||
|
||||
CRUDable `xorm:"-" json:"-"`
|
||||
Rights `xorm:"-" json:"-"`
|
||||
}
|
||||
|
||||
// TableName makes beautiful table names
|
||||
func (TeamNamespace) TableName() string {
|
||||
return "team_namespaces"
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
package models
|
||||
|
||||
// CanCreate checks if one can create a new team <-> namespace relation
|
||||
func (tn *TeamNamespace) CanCreate(user *User) bool {
|
||||
n, err := GetNamespaceByID(tn.NamespaceID)
|
||||
if err != nil {
|
||||
Log.Error("Error occurred during CanCreate for TeamNamespace: %s", err)
|
||||
return false
|
||||
}
|
||||
return n.IsAdmin(user)
|
||||
}
|
||||
|
||||
// CanDelete checks if a user can remove a team from a namespace. Only namespace admins can do that.
|
||||
func (tn *TeamNamespace) CanDelete(user *User) bool {
|
||||
n, err := GetNamespaceByID(tn.NamespaceID)
|
||||
if err != nil {
|
||||
Log.Error("Error occurred during CanDelete for TeamNamespace: %s", err)
|
||||
return false
|
||||
}
|
||||
return n.IsAdmin(user)
|
||||
}
|
||||
|
||||
// CanUpdate checks if a user can update a team from a namespace. Only namespace admins can do that.
|
||||
func (tn *TeamNamespace) CanUpdate(user *User) bool {
|
||||
n, err := GetNamespaceByID(tn.NamespaceID)
|
||||
if err != nil {
|
||||
Log.Error("Error occurred during CanUpdate for TeamNamespace: %s", err)
|
||||
return false
|
||||
}
|
||||
return n.IsAdmin(user)
|
||||
}
|
|
@ -1,80 +0,0 @@
|
|||
package models
|
||||
|
||||
// TeamRight defines the rights teams can have for lists/namespaces
|
||||
type TeamRight int
|
||||
|
||||
// define unknown team right
|
||||
const (
|
||||
TeamRightUnknown = -1
|
||||
)
|
||||
|
||||
// Enumerate all the team rights
|
||||
const (
|
||||
// Can read lists in a Team
|
||||
TeamRightRead TeamRight = iota
|
||||
// Can write tasks in a Team like lists and todo tasks. Cannot create new lists.
|
||||
TeamRightWrite
|
||||
// Can manage a list/namespace, can do everything
|
||||
TeamRightAdmin
|
||||
)
|
||||
|
||||
func (r TeamRight) isValid() error {
|
||||
if r != TeamRightAdmin && r != TeamRightRead && r != TeamRightWrite {
|
||||
return ErrInvalidTeamRight{r}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// CanCreate checks if the user can create a new team
|
||||
func (t *Team) CanCreate(user *User) bool {
|
||||
// This is currently a dummy function, later on we could imagine global limits etc.
|
||||
return true
|
||||
}
|
||||
|
||||
// CanUpdate checks if the user can update a team
|
||||
func (t *Team) CanUpdate(user *User) bool {
|
||||
|
||||
// Check if the current user is in the team and has admin rights in it
|
||||
exists, err := x.Where("team_id = ?", t.ID).
|
||||
And("user_id = ?", user.ID).
|
||||
And("admin = ?", true).
|
||||
Get(&TeamMember{})
|
||||
if err != nil {
|
||||
Log.Error("Error occurred during CanUpdate for Team: %s", err)
|
||||
return false
|
||||
}
|
||||
|
||||
return exists
|
||||
}
|
||||
|
||||
// CanDelete checks if a user can delete a team
|
||||
func (t *Team) CanDelete(user *User) bool {
|
||||
return t.IsAdmin(user)
|
||||
}
|
||||
|
||||
// IsAdmin returns true when the user is admin of a team
|
||||
func (t *Team) IsAdmin(user *User) bool {
|
||||
exists, err := x.Where("team_id = ?", t.ID).
|
||||
And("user_id = ?", user.ID).
|
||||
And("admin = ?", true).
|
||||
Get(&TeamMember{})
|
||||
if err != nil {
|
||||
Log.Error("Error occurred during CanUpdate for Team: %s", err)
|
||||
return false
|
||||
}
|
||||
return exists
|
||||
}
|
||||
|
||||
// CanRead returns true if the user has read access to the team
|
||||
func (t *Team) CanRead(user *User) bool {
|
||||
// Check if the user is in the team
|
||||
exists, err := x.Where("team_id = ?", t.ID).
|
||||
And("user_id = ?", user.ID).
|
||||
Get(&TeamMember{})
|
||||
if err != nil {
|
||||
Log.Error("Error occurred during CanUpdate for Team: %s", err)
|
||||
return false
|
||||
}
|
||||
return exists
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package models
|
||||
package config
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
|
@ -1,4 +1,4 @@
|
|||
package models
|
||||
package errs
|
||||
|
||||
import (
|
||||
"fmt"
|
12
pkg/list/init.go
Normal file
12
pkg/list/init.go
Normal file
|
@ -0,0 +1,12 @@
|
|||
package list
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/models"
|
||||
"github.com/go-xorm/xorm"
|
||||
)
|
||||
|
||||
var x *xorm.Engine
|
||||
|
||||
func init() {
|
||||
x = models.GetEngine()
|
||||
}
|
|
@ -1,4 +1,10 @@
|
|||
package models
|
||||
package list
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/errs"
|
||||
"code.vikunja.io/api/pkg/models"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
)
|
||||
|
||||
// List represents a list of tasks
|
||||
type List struct {
|
||||
|
@ -8,14 +14,14 @@ type List struct {
|
|||
OwnerID int64 `xorm:"int(11) INDEX" json:"-"`
|
||||
NamespaceID int64 `xorm:"int(11) INDEX" json:"-" param:"namespace"`
|
||||
|
||||
Owner User `xorm:"-" json:"owner"`
|
||||
Owner user.User `xorm:"-" json:"owner"`
|
||||
Tasks []*ListTask `xorm:"-" json:"tasks"`
|
||||
|
||||
Created int64 `xorm:"created" json:"created"`
|
||||
Updated int64 `xorm:"updated" json:"updated"`
|
||||
|
||||
CRUDable `xorm:"-" json:"-"`
|
||||
Rights `xorm:"-" json:"-"`
|
||||
models.CRUDable `xorm:"-" json:"-"`
|
||||
models.Rights `xorm:"-" json:"-"`
|
||||
}
|
||||
|
||||
// GetListsByNamespaceID gets all lists in a namespace
|
||||
|
@ -25,9 +31,9 @@ func GetListsByNamespaceID(nID int64) (lists []*List, err error) {
|
|||
}
|
||||
|
||||
// ReadAll gets all lists a user has access to
|
||||
func (l *List) ReadAll(user *User) (interface{}, error) {
|
||||
func (l *List) ReadAll(u *user.User) (interface{}, error) {
|
||||
lists := []*List{}
|
||||
fullUser, err := GetUserByID(user.ID)
|
||||
fullUser, err := user.GetUserByID(u.ID)
|
||||
if err != nil {
|
||||
return lists, err
|
||||
}
|
||||
|
@ -53,7 +59,7 @@ func (l *List) ReadAll(user *User) (interface{}, error) {
|
|||
Find(&lists)
|
||||
|
||||
// Add more list details
|
||||
addListDetails(lists)
|
||||
AddListDetails(lists)
|
||||
|
||||
return lists, err
|
||||
}
|
||||
|
@ -72,14 +78,14 @@ func (l *List) ReadOne() (err error) {
|
|||
}
|
||||
|
||||
// Get list owner
|
||||
l.Owner, err = GetUserByID(l.OwnerID)
|
||||
l.Owner, err = user.GetUserByID(l.OwnerID)
|
||||
return
|
||||
}
|
||||
|
||||
// GetSimpleByID gets a list with only the basic items, aka no tasks or user objects. Returns an error if the list does not exist.
|
||||
func (l *List) GetSimpleByID() (err error) {
|
||||
if l.ID < 1 {
|
||||
return ErrListDoesNotExist{ID: l.ID}
|
||||
return errs.ErrListDoesNotExist{ID: l.ID}
|
||||
}
|
||||
|
||||
// We need to re-init our list object, because otherwise xorm creates a "where for every item in that list object,
|
||||
|
@ -92,14 +98,14 @@ func (l *List) GetSimpleByID() (err error) {
|
|||
}
|
||||
|
||||
if !exists {
|
||||
return ErrListDoesNotExist{ID: l.ID}
|
||||
return errs.ErrListDoesNotExist{ID: l.ID}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Adds owner user objects and list tasks to all lists in the slice
|
||||
func addListDetails(lists []*List) (err error) {
|
||||
func AddListDetails(lists []*List) (err error) {
|
||||
var listIDs []int64
|
||||
var ownerIDs []int64
|
||||
for _, l := range lists {
|
||||
|
@ -108,14 +114,14 @@ func addListDetails(lists []*List) (err error) {
|
|||
}
|
||||
|
||||
// Get all tasks
|
||||
tasks := []*ListTask{}
|
||||
err = x.In("list_id", listIDs).Find(&tasks)
|
||||
ts := []*ListTask{}
|
||||
err = x.In("list_id", listIDs).Find(&ts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Get all list owners
|
||||
owners := []*User{}
|
||||
owners := []*user.User{}
|
||||
err = x.In("id", ownerIDs).Find(&owners)
|
||||
if err != nil {
|
||||
return
|
||||
|
@ -132,7 +138,7 @@ func addListDetails(lists []*List) (err error) {
|
|||
}
|
||||
|
||||
// Tasks
|
||||
for _, task := range tasks {
|
||||
for _, task := range ts {
|
||||
if task.ListID == list.ID {
|
||||
lists[in].Tasks = append(lists[in].Tasks, task)
|
||||
}
|
|
@ -1,6 +1,8 @@
|
|||
package models
|
||||
package list
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/errs"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
)
|
||||
|
@ -10,7 +12,7 @@ func TestList_Create(t *testing.T) {
|
|||
//assert.NoError(t, PrepareTestDatabase())
|
||||
|
||||
// Get our doer
|
||||
doer, err := GetUserByID(1)
|
||||
doer, err := user.GetUserByID(1)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Dummy list for testing
|
||||
|
@ -53,18 +55,18 @@ func TestList_Create(t *testing.T) {
|
|||
// Try updating a nonexistant list
|
||||
err = dummylist.Update()
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrListDoesNotExist(err))
|
||||
assert.True(t, errs.IsErrListDoesNotExist(err))
|
||||
|
||||
// Delete a nonexistant list
|
||||
err = dummylist.Delete()
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrListDoesNotExist(err))
|
||||
assert.True(t, errs.IsErrListDoesNotExist(err))
|
||||
|
||||
// Check failing with no title
|
||||
list2 := List{}
|
||||
err = list2.Create(&doer)
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrListTitleCannotBeEmpty(err))
|
||||
assert.True(t, errs.IsErrListTitleCannotBeEmpty(err))
|
||||
|
||||
// Check creation with a nonexistant namespace
|
||||
list3 := List{
|
||||
|
@ -75,11 +77,11 @@ func TestList_Create(t *testing.T) {
|
|||
|
||||
err = list3.Create(&doer)
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrNamespaceDoesNotExist(err))
|
||||
assert.True(t, errs.IsErrNamespaceDoesNotExist(err))
|
||||
|
||||
// Try creating with a nonexistant owner
|
||||
nUser := &User{ID: 9482385}
|
||||
nUser := &user.User{ID: 9482385}
|
||||
err = dummylist.Create(nUser)
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrUserDoesNotExist(err))
|
||||
assert.True(t, errs.IsErrUserDoesNotExist(err))
|
||||
}
|
|
@ -1,16 +1,22 @@
|
|||
package models
|
||||
package list
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/errs"
|
||||
"code.vikunja.io/api/pkg/namespace"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
)
|
||||
|
||||
// CreateOrUpdateList updates a list or creates it if it doesn't exist
|
||||
func CreateOrUpdateList(list *List) (err error) {
|
||||
|
||||
// Check we have at least a title
|
||||
if list.Title == "" {
|
||||
return ErrListTitleCannotBeEmpty{}
|
||||
return errs.ErrListTitleCannotBeEmpty{}
|
||||
}
|
||||
|
||||
// Check if the namespace exists
|
||||
if list.NamespaceID != 0 {
|
||||
_, err = GetNamespaceByID(list.NamespaceID)
|
||||
_, err = namespace.GetNamespaceByID(list.NamespaceID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -42,15 +48,15 @@ func (l *List) Update() (err error) {
|
|||
}
|
||||
|
||||
// Create implements the create method of CRUDable
|
||||
func (l *List) Create(doer *User) (err error) {
|
||||
func (l *List) Create(doer *user.User) (err error) {
|
||||
// Check rights
|
||||
user, err := GetUserByID(doer.ID)
|
||||
u, err := user.GetUserByID(doer.ID)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
l.OwnerID = user.ID
|
||||
l.Owner.ID = user.ID
|
||||
l.OwnerID = u.ID
|
||||
l.Owner.ID = u.ID
|
||||
l.ID = 0 // Otherwise only the first time a new list would be created
|
||||
|
||||
return CreateOrUpdateList(l)
|
|
@ -1,4 +1,4 @@
|
|||
package models
|
||||
package list
|
||||
|
||||
// Delete implements the delete method of CRUDable
|
||||
func (l *List) Delete() (err error) {
|
|
@ -1,76 +1,83 @@
|
|||
package models
|
||||
package list
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/log"
|
||||
"code.vikunja.io/api/pkg/models"
|
||||
"code.vikunja.io/api/pkg/namespace"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
)
|
||||
|
||||
// IsAdmin returns whether the user has admin rights on the list or not
|
||||
func (l *List) IsAdmin(user *User) bool {
|
||||
func (l *List) IsAdmin(u *user.User) bool {
|
||||
// Owners are always admins
|
||||
if l.Owner.ID == user.ID {
|
||||
if l.Owner.ID == u.ID {
|
||||
return true
|
||||
}
|
||||
|
||||
// Check individual rights
|
||||
if l.checkListUserRight(user, UserRightAdmin) {
|
||||
if l.checkListUserRight(u, models.UserRightAdmin) {
|
||||
return true
|
||||
}
|
||||
|
||||
return l.checkListTeamRight(user, TeamRightAdmin)
|
||||
return l.checkListTeamRight(u, models.TeamRightAdmin)
|
||||
}
|
||||
|
||||
// CanWrite return whether the user can write on that list or not
|
||||
func (l *List) CanWrite(user *User) bool {
|
||||
func (l *List) CanWrite(user *user.User) bool {
|
||||
// Admins always have write access
|
||||
if l.IsAdmin(user) {
|
||||
return true
|
||||
}
|
||||
|
||||
// Check individual rights
|
||||
if l.checkListUserRight(user, UserRightWrite) {
|
||||
if l.checkListUserRight(user, models.UserRightWrite) {
|
||||
return true
|
||||
}
|
||||
|
||||
return l.checkListTeamRight(user, TeamRightWrite)
|
||||
return l.checkListTeamRight(user, models.TeamRightWrite)
|
||||
}
|
||||
|
||||
// CanRead checks if a user has read access to a list
|
||||
func (l *List) CanRead(user *User) bool {
|
||||
func (l *List) CanRead(user *user.User) bool {
|
||||
// Admins always have read access
|
||||
if l.IsAdmin(user) {
|
||||
return true
|
||||
}
|
||||
|
||||
// Check individual rights
|
||||
if l.checkListUserRight(user, UserRightRead) {
|
||||
if l.checkListUserRight(user, models.UserRightRead) {
|
||||
return true
|
||||
}
|
||||
|
||||
return l.checkListTeamRight(user, TeamRightRead)
|
||||
return l.checkListTeamRight(user, models.TeamRightRead)
|
||||
}
|
||||
|
||||
// CanDelete checks if the user can delete a list
|
||||
func (l *List) CanDelete(doer *User) bool {
|
||||
func (l *List) CanDelete(doer *user.User) bool {
|
||||
if err := l.GetSimpleByID(); err != nil {
|
||||
Log.Error("Error occurred during CanDelete for List: %s", err)
|
||||
log.Log.Error("Error occurred during CanDelete for List: %s", err)
|
||||
return false
|
||||
}
|
||||
return l.IsAdmin(doer)
|
||||
}
|
||||
|
||||
// CanUpdate checks if the user can update a list
|
||||
func (l *List) CanUpdate(doer *User) bool {
|
||||
func (l *List) CanUpdate(doer *user.User) bool {
|
||||
if err := l.GetSimpleByID(); err != nil {
|
||||
Log.Error("Error occurred during CanUpdate for List: %s", err)
|
||||
log.Log.Error("Error occurred during CanUpdate for List: %s", err)
|
||||
return false
|
||||
}
|
||||
return l.CanWrite(doer)
|
||||
}
|
||||
|
||||
// CanCreate checks if the user can update a list
|
||||
func (l *List) CanCreate(doer *User) bool {
|
||||
func (l *List) CanCreate(doer *user.User) bool {
|
||||
// A user can create a list if he has write access to the namespace
|
||||
n, _ := GetNamespaceByID(l.NamespaceID)
|
||||
n, _ := namespace.GetNamespaceByID(l.NamespaceID)
|
||||
return n.CanWrite(doer)
|
||||
}
|
||||
|
||||
func (l *List) checkListTeamRight(user *User, r TeamRight) bool {
|
||||
func (l *List) checkListTeamRight(user *user.User, r models.TeamRight) bool {
|
||||
exists, err := x.Select("l.*").
|
||||
Table("list").
|
||||
Alias("l").
|
||||
|
@ -82,14 +89,14 @@ func (l *List) checkListTeamRight(user *User, r TeamRight) bool {
|
|||
user.ID, r, user.ID, r, l.ID).
|
||||
Exist(&List{})
|
||||
if err != nil {
|
||||
Log.Error("Error occurred during checkListTeamRight for List: %s", err)
|
||||
log.Log.Error("Error occurred during checkListTeamRight for List: %s", err)
|
||||
return false
|
||||
}
|
||||
|
||||
return exists
|
||||
}
|
||||
|
||||
func (l *List) checkListUserRight(user *User, r UserRight) bool {
|
||||
func (l *List) checkListUserRight(user *user.User, r models.UserRight) bool {
|
||||
exists, err := x.Select("l.*").
|
||||
Table("list").
|
||||
Alias("l").
|
||||
|
@ -103,7 +110,7 @@ func (l *List) checkListUserRight(user *User, r UserRight) bool {
|
|||
user.ID, r, user.ID, r, user.ID, l.ID).
|
||||
Exist(&List{})
|
||||
if err != nil {
|
||||
Log.Error("Error occurred during checkListUserRight for List: %s", err)
|
||||
log.Log.Error("Error occurred during checkListUserRight for List: %s", err)
|
||||
return false
|
||||
}
|
||||
|
|
@ -1,4 +1,10 @@
|
|||
package models
|
||||
package list
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/errs"
|
||||
"code.vikunja.io/api/pkg/models"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
)
|
||||
|
||||
// ListTask represents an task in a todolist
|
||||
type ListTask struct {
|
||||
|
@ -13,10 +19,10 @@ type ListTask struct {
|
|||
Created int64 `xorm:"created" json:"created"`
|
||||
Updated int64 `xorm:"updated" json:"updated"`
|
||||
|
||||
CreatedBy User `xorm:"-" json:"createdBy"`
|
||||
CreatedBy user.User `xorm:"-" json:"createdBy"`
|
||||
|
||||
CRUDable `xorm:"-" json:"-"`
|
||||
Rights `xorm:"-" json:"-"`
|
||||
models.CRUDable `xorm:"-" json:"-"`
|
||||
models.Rights `xorm:"-" json:"-"`
|
||||
}
|
||||
|
||||
// TableName returns the table name for listtasks
|
||||
|
@ -52,16 +58,16 @@ func GetTasksByListID(listID int64) (tasks []*ListTask, err error) {
|
|||
}
|
||||
}
|
||||
|
||||
var users []User
|
||||
var users []user.User
|
||||
err = x.In("id", userIDs).Find(&users)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for in, task := range tasks {
|
||||
for _, user := range users {
|
||||
if task.CreatedByID == user.ID {
|
||||
tasks[in].CreatedBy = user
|
||||
for _, u := range users {
|
||||
if task.CreatedByID == u.ID {
|
||||
tasks[in].CreatedBy = u
|
||||
break
|
||||
}
|
||||
}
|
||||
|
@ -76,7 +82,7 @@ func GetTasksByListID(listID int64) (tasks []*ListTask, err error) {
|
|||
// GetListTaskByID returns all tasks a list has
|
||||
func GetListTaskByID(listTaskID int64) (listTask ListTask, err error) {
|
||||
if listTaskID < 1 {
|
||||
return ListTask{}, ErrListTaskDoesNotExist{listTaskID}
|
||||
return ListTask{}, errs.ErrListTaskDoesNotExist{listTaskID}
|
||||
}
|
||||
|
||||
exists, err := x.ID(listTaskID).Get(&listTask)
|
||||
|
@ -85,14 +91,14 @@ func GetListTaskByID(listTaskID int64) (listTask ListTask, err error) {
|
|||
}
|
||||
|
||||
if !exists {
|
||||
return ListTask{}, ErrListTaskDoesNotExist{listTaskID}
|
||||
return ListTask{}, errs.ErrListTaskDoesNotExist{listTaskID}
|
||||
}
|
||||
|
||||
user, err := GetUserByID(listTask.CreatedByID)
|
||||
u, err := user.GetUserByID(listTask.CreatedByID)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
listTask.CreatedBy = user
|
||||
listTask.CreatedBy = u
|
||||
|
||||
return
|
||||
}
|
|
@ -1,16 +1,18 @@
|
|||
package models
|
||||
package list
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/errs"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"github.com/imdario/mergo"
|
||||
)
|
||||
|
||||
// Create is the implementation to create a list task
|
||||
func (i *ListTask) Create(doer *User) (err error) {
|
||||
func (i *ListTask) Create(doer *user.User) (err error) {
|
||||
i.ID = 0
|
||||
|
||||
// Check if we have at least a text
|
||||
if i.Text == "" {
|
||||
return ErrListTaskCannotBeEmpty{}
|
||||
return errs.ErrListTaskCannotBeEmpty{}
|
||||
}
|
||||
|
||||
// Check if the list exists
|
||||
|
@ -19,13 +21,13 @@ func (i *ListTask) Create(doer *User) (err error) {
|
|||
return
|
||||
}
|
||||
|
||||
user, err := GetUserByID(doer.ID)
|
||||
u, err := user.GetUserByID(doer.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
i.CreatedByID = user.ID
|
||||
i.CreatedBy = user
|
||||
i.CreatedByID = u.ID
|
||||
i.CreatedBy = u
|
||||
_, err = x.Cols("text", "description", "done", "due_date_unix", "reminder_unix", "created_by_id", "list_id", "created", "updated").Insert(i)
|
||||
return err
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package models
|
||||
package list
|
||||
|
||||
// Delete implements the delete method for listTask
|
||||
func (i *ListTask) Delete() (err error) {
|
44
pkg/list/list_tasks_rights.go
Normal file
44
pkg/list/list_tasks_rights.go
Normal file
|
@ -0,0 +1,44 @@
|
|||
package list
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/log"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
)
|
||||
|
||||
// CanDelete checks if the user can delete an task
|
||||
func (i *ListTask) CanDelete(doer *user.User) bool {
|
||||
// Get the task
|
||||
lI, err := GetListTaskByID(i.ID)
|
||||
if err != nil {
|
||||
log.Log.Error("Error occurred during CanDelete for ListTask: %s", err)
|
||||
return false
|
||||
}
|
||||
|
||||
// A user can delete an task if he has write acces to its list
|
||||
l := &List{ID: lI.ListID}
|
||||
l.ReadOne()
|
||||
return l.CanWrite(doer)
|
||||
}
|
||||
|
||||
// CanUpdate determines if a user has the right to update a list task
|
||||
func (i *ListTask) CanUpdate(doer *user.User) bool {
|
||||
// Get the task
|
||||
lI, err := GetListTaskByID(i.ID)
|
||||
if err != nil {
|
||||
log.Log.Error("Error occurred during CanDelete for ListTask: %s", err)
|
||||
return false
|
||||
}
|
||||
|
||||
// A user can update an task if he has write acces to its list
|
||||
l := &List{ID: lI.ListID}
|
||||
l.ReadOne()
|
||||
return l.CanWrite(doer)
|
||||
}
|
||||
|
||||
// CanCreate determines if a user has the right to create a list task
|
||||
func (i *ListTask) CanCreate(doer *user.User) bool {
|
||||
// A user can create an task if he has write acces to its list
|
||||
l := &List{ID: i.ListID}
|
||||
l.ReadOne()
|
||||
return l.CanWrite(doer)
|
||||
}
|
|
@ -1,6 +1,8 @@
|
|||
package models
|
||||
package list
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/errs"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
)
|
||||
|
@ -16,7 +18,7 @@ func TestListTask_Create(t *testing.T) {
|
|||
}
|
||||
|
||||
// Add one point to a list
|
||||
doer, err := GetUserByID(1)
|
||||
doer, err := user.GetUserByID(1)
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.True(t, listtask.CanCreate(&doer))
|
||||
|
@ -44,31 +46,31 @@ func TestListTask_Create(t *testing.T) {
|
|||
listtask.ID = 0
|
||||
err = listtask.Delete()
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrListTaskDoesNotExist(err))
|
||||
assert.True(t, errs.IsErrListTaskDoesNotExist(err))
|
||||
|
||||
// Try adding a list task with an empty text
|
||||
listtask.Text = ""
|
||||
err = listtask.Create(&doer)
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrListTaskCannotBeEmpty(err))
|
||||
assert.True(t, errs.IsErrListTaskCannotBeEmpty(err))
|
||||
|
||||
// Try adding one to a nonexistant list
|
||||
listtask.ListID = 99993939
|
||||
listtask.Text = "Lorem Ipsum"
|
||||
err = listtask.Create(&doer)
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrListDoesNotExist(err))
|
||||
assert.True(t, errs.IsErrListDoesNotExist(err))
|
||||
|
||||
// Try updating a nonexistant task
|
||||
listtask.ID = 94829352
|
||||
err = listtask.Update()
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrListTaskDoesNotExist(err))
|
||||
assert.True(t, errs.IsErrListTaskDoesNotExist(err))
|
||||
|
||||
// Try inserting an task with a nonexistant user
|
||||
nUser := &User{ID: 9482385}
|
||||
nUser := &user.User{ID: 9482385}
|
||||
listtask.ListID = 1
|
||||
err = listtask.Create(nUser)
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrUserDoesNotExist(err))
|
||||
assert.True(t, errs.IsErrUserDoesNotExist(err))
|
||||
}
|
|
@ -1,6 +1,8 @@
|
|||
package models
|
||||
package list
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/errs"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
@ -16,18 +18,18 @@ func TestList_ReadAll(t *testing.T) {
|
|||
assert.Equal(t, len(lists), 2)
|
||||
|
||||
// Get all lists our user has access to
|
||||
user, err := GetUserByID(1)
|
||||
u, err := user.GetUserByID(1)
|
||||
assert.NoError(t, err)
|
||||
|
||||
lists2 := List{}
|
||||
lists3, err := lists2.ReadAll(&user)
|
||||
lists3, err := lists2.ReadAll(&u)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, reflect.TypeOf(lists3).Kind(), reflect.Slice)
|
||||
s := reflect.ValueOf(lists3)
|
||||
assert.Equal(t, s.Len(), 1)
|
||||
|
||||
// Try getting lists for a nonexistant user
|
||||
_, err = lists2.ReadAll(&User{ID: 984234})
|
||||
_, err = lists2.ReadAll(&user.User{ID: 984234})
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrUserDoesNotExist(err))
|
||||
assert.True(t, errs.IsErrUserDoesNotExist(err))
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package models
|
||||
package log
|
||||
|
||||
import (
|
||||
"github.com/op/go-logging"
|
|
@ -1,8 +1,8 @@
|
|||
package mail
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/log"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"github.com/spf13/viper"
|
||||
"gopkg.in/gomail.v2"
|
||||
"time"
|
||||
|
@ -16,8 +16,7 @@ func StartMailDaemon() {
|
|||
Queue = make(chan *gomail.Message, viper.GetInt("mailer.queuelength"))
|
||||
|
||||
if viper.GetString("mailer.host") == "" {
|
||||
//models.Log.Warning("Mailer seems to be not configured! Please see the config docs for more details.")
|
||||
fmt.Println("Mailer seems to be not configured! Please see the config docs for more details.")
|
||||
log.Log.Warning("Mailer seems to be not configured! Please see the config docs for more details.")
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -36,23 +35,21 @@ func StartMailDaemon() {
|
|||
}
|
||||
if !open {
|
||||
if s, err = d.Dial(); err != nil {
|
||||
// models.Log.Error("Error during connect to smtp server: %s", err)
|
||||
fmt.Printf("Error during connect to smtp server: %s \n", err)
|
||||
log.Log.Error("Error during connect to smtp server: %s", err)
|
||||
}
|
||||
open = true
|
||||
}
|
||||
if err := gomail.Send(s, m); err != nil {
|
||||
// models.Log.Error("Error when sending mail: %s", err)
|
||||
fmt.Printf("Error when sending mail: %s \n", err)
|
||||
log.Log.Error("Error when sending mail: %s", err)
|
||||
}
|
||||
// Close the connection to the SMTP server if no email was sent in
|
||||
// the last 30 seconds.
|
||||
case <-time.After(viper.GetDuration("mailer.queuetimeout") * time.Second):
|
||||
if open {
|
||||
if err := s.Close(); err != nil {
|
||||
fmt.Printf("Error closing the mail server connection: %s\n", err)
|
||||
log.Log.Error("Error closing the mail server connection: %s\n", err)
|
||||
}
|
||||
fmt.Println("Closed connection to mailserver")
|
||||
log.Log.Infof("Closed connection to mailserver")
|
||||
open = false
|
||||
}
|
||||
}
|
|
@ -2,7 +2,7 @@ package mail
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"code.vikunja.io/api/models/utils"
|
||||
"code.vikunja.io/api/pkg/utils"
|
||||
"github.com/labstack/gommon/log"
|
||||
"github.com/spf13/viper"
|
||||
"gopkg.in/gomail.v2"
|
|
@ -2,9 +2,9 @@ package models
|
|||
|
||||
// CRUDable defines the crud methods
|
||||
type CRUDable interface {
|
||||
Create(*User) error
|
||||
Create(*user.User) error
|
||||
ReadOne() error
|
||||
ReadAll(*User) (interface{}, error)
|
||||
ReadAll(*user.User) (interface{}, error)
|
||||
Update() error
|
||||
Delete() error
|
||||
}
|
|
@ -40,6 +40,11 @@ func getEngine() (*xorm.Engine, error) {
|
|||
return xorm.NewEngine("sqlite3", path)
|
||||
}
|
||||
|
||||
// GetEngine returns the databse engine
|
||||
func GetEngine() *xorm.Engine {
|
||||
return x
|
||||
}
|
||||
|
||||
func init() {
|
||||
tables = append(tables,
|
||||
new(User),
|
11
pkg/models/rights.go
Normal file
11
pkg/models/rights.go
Normal file
|
@ -0,0 +1,11 @@
|
|||
package models
|
||||
|
||||
// Rights defines rights methods
|
||||
type Rights interface {
|
||||
IsAdmin(*user.User) bool
|
||||
CanWrite(*user.User) bool
|
||||
CanRead(*user.User) bool
|
||||
CanDelete(*user.User) bool
|
||||
CanUpdate(*user.User) bool
|
||||
CanCreate(*user.User) bool
|
||||
}
|
29
pkg/models/team_right.go
Normal file
29
pkg/models/team_right.go
Normal file
|
@ -0,0 +1,29 @@
|
|||
package models
|
||||
|
||||
import "code.vikunja.io/api/pkg/errs"
|
||||
|
||||
// TeamRight defines the rights teams can have for lists/namespaces
|
||||
type TeamRight int
|
||||
|
||||
// define unknown team right
|
||||
const (
|
||||
TeamRightUnknown = -1
|
||||
)
|
||||
|
||||
// Enumerate all the team rights
|
||||
const (
|
||||
// Can read lists in a Team
|
||||
TeamRightRead TeamRight = iota
|
||||
// Can write tasks in a Team like lists and todo tasks. Cannot create new lists.
|
||||
TeamRightWrite
|
||||
// Can manage a list/namespace, can do everything
|
||||
TeamRightAdmin
|
||||
)
|
||||
|
||||
func (r TeamRight) IsValid() error {
|
||||
if r != TeamRightAdmin && r != TeamRightRead && r != TeamRightWrite {
|
||||
return errs.ErrInvalidTeamRight{r}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
package models
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/models/mail"
|
||||
"code.vikunja.io/api/pkg/mail"
|
||||
"fmt"
|
||||
"github.com/go-xorm/core"
|
||||
"github.com/go-xorm/xorm"
|
29
pkg/models/user_right.go
Normal file
29
pkg/models/user_right.go
Normal file
|
@ -0,0 +1,29 @@
|
|||
package models
|
||||
|
||||
import "code.vikunja.io/api/pkg/errs"
|
||||
|
||||
// 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 errs.ErrInvalidUserRight{r}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
12
pkg/namespace/init.go
Normal file
12
pkg/namespace/init.go
Normal file
|
@ -0,0 +1,12 @@
|
|||
package namespace
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/models"
|
||||
"github.com/go-xorm/xorm"
|
||||
)
|
||||
|
||||
var x *xorm.Engine
|
||||
|
||||
func init() {
|
||||
x = models.GetEngine()
|
||||
}
|
|
@ -1,4 +1,11 @@
|
|||
package models
|
||||
package namespace
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/errs"
|
||||
"code.vikunja.io/api/pkg/list"
|
||||
"code.vikunja.io/api/pkg/models"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
)
|
||||
|
||||
// Namespace holds informations about a namespace
|
||||
type Namespace struct {
|
||||
|
@ -7,13 +14,13 @@ type Namespace struct {
|
|||
Description string `xorm:"varchar(1000)" json:"description"`
|
||||
OwnerID int64 `xorm:"int(11) not null INDEX" json:"-"`
|
||||
|
||||
Owner User `xorm:"-" json:"owner"`
|
||||
Owner user.User `xorm:"-" json:"owner"`
|
||||
|
||||
Created int64 `xorm:"created" json:"created"`
|
||||
Updated int64 `xorm:"updated" json:"updated"`
|
||||
|
||||
CRUDable `xorm:"-" json:"-"`
|
||||
Rights `xorm:"-" json:"-"`
|
||||
models.CRUDable `xorm:"-" json:"-"`
|
||||
models.Rights `xorm:"-" json:"-"`
|
||||
}
|
||||
|
||||
// TableName makes beautiful table names
|
||||
|
@ -24,7 +31,7 @@ func (Namespace) TableName() string {
|
|||
// GetNamespaceByID returns a namespace object by its ID
|
||||
func GetNamespaceByID(id int64) (namespace Namespace, err error) {
|
||||
if id < 1 {
|
||||
return namespace, ErrNamespaceDoesNotExist{ID: id}
|
||||
return namespace, errs.ErrNamespaceDoesNotExist{ID: id}
|
||||
}
|
||||
|
||||
namespace.ID = id
|
||||
|
@ -34,11 +41,11 @@ func GetNamespaceByID(id int64) (namespace Namespace, err error) {
|
|||
}
|
||||
|
||||
if !exists {
|
||||
return namespace, ErrNamespaceDoesNotExist{ID: id}
|
||||
return namespace, errs.ErrNamespaceDoesNotExist{ID: id}
|
||||
}
|
||||
|
||||
// Get the namespace Owner
|
||||
namespace.Owner, err = GetUserByID(namespace.OwnerID)
|
||||
namespace.Owner, err = user.GetUserByID(namespace.OwnerID)
|
||||
if err != nil {
|
||||
return namespace, err
|
||||
}
|
||||
|
@ -53,11 +60,11 @@ func (n *Namespace) ReadOne() (err error) {
|
|||
}
|
||||
|
||||
// ReadAll gets all namespaces a user has access to
|
||||
func (n *Namespace) ReadAll(doer *User) (interface{}, error) {
|
||||
func (n *Namespace) ReadAll(doer *user.User) (interface{}, error) {
|
||||
|
||||
type namespaceWithLists struct {
|
||||
Namespace `xorm:"extends"`
|
||||
Lists []*List `xorm:"-" json:"lists"`
|
||||
Lists []*list.List `xorm:"-" json:"lists"`
|
||||
}
|
||||
|
||||
all := []*namespaceWithLists{}
|
||||
|
@ -78,7 +85,7 @@ func (n *Namespace) ReadAll(doer *User) (interface{}, error) {
|
|||
}
|
||||
|
||||
// Get all users
|
||||
users := []*User{}
|
||||
users := []*user.User{}
|
||||
err = x.Select("users.*").
|
||||
Table("namespaces").
|
||||
Join("LEFT", "team_namespaces", "namespaces.id = team_namespaces.namespace_id").
|
||||
|
@ -100,7 +107,7 @@ func (n *Namespace) ReadAll(doer *User) (interface{}, error) {
|
|||
}
|
||||
|
||||
// Get all lists
|
||||
lists := []*List{}
|
||||
lists := []*list.List{}
|
||||
err = x.Table(&lists).
|
||||
In("namespace_id", namespaceids).
|
||||
Find(&lists)
|
||||
|
@ -109,7 +116,7 @@ func (n *Namespace) ReadAll(doer *User) (interface{}, error) {
|
|||
}
|
||||
|
||||
// More details for the lists
|
||||
addListDetails(lists)
|
||||
list.AddListDetails(lists)
|
||||
|
||||
// Put objects in our namespace list
|
||||
for i, n := range all {
|
|
@ -1,15 +1,20 @@
|
|||
package models
|
||||
package namespace
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/errs"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
)
|
||||
|
||||
// Create implements the creation method via the interface
|
||||
func (n *Namespace) Create(doer *User) (err error) {
|
||||
func (n *Namespace) Create(doer *user.User) (err error) {
|
||||
// Check if we have at least a name
|
||||
if n.Name == "" {
|
||||
return ErrNamespaceNameCannotBeEmpty{NamespaceID: 0, UserID: doer.ID}
|
||||
return errs.ErrNamespaceNameCannotBeEmpty{NamespaceID: 0, UserID: doer.ID}
|
||||
}
|
||||
n.ID = 0 // This would otherwise prevent the creation of new lists after one was created
|
||||
|
||||
// Check if the User exists
|
||||
n.Owner, err = GetUserByID(doer.ID)
|
||||
n.Owner, err = user.GetUserByID(doer.ID)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
|
@ -1,4 +1,8 @@
|
|||
package models
|
||||
package namespace
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/list"
|
||||
)
|
||||
|
||||
// Delete deletes a namespace
|
||||
func (n *Namespace) Delete() (err error) {
|
||||
|
@ -16,23 +20,23 @@ func (n *Namespace) Delete() (err error) {
|
|||
}
|
||||
|
||||
// Delete all lists with their tasks
|
||||
lists, err := GetListsByNamespaceID(n.ID)
|
||||
lists, err := list.GetListsByNamespaceID(n.ID)
|
||||
var listIDs []int64
|
||||
// We need to do that for here because we need the list ids to delete two times:
|
||||
// 1) to delete the lists itself
|
||||
// 2) to delete the list tasks
|
||||
for _, list := range lists {
|
||||
listIDs = append(listIDs, list.ID)
|
||||
for _, l := range lists {
|
||||
listIDs = append(listIDs, l.ID)
|
||||
}
|
||||
|
||||
// Delete tasks
|
||||
_, err = x.In("list_id", listIDs).Delete(&ListTask{})
|
||||
_, err = x.In("list_id", listIDs).Delete(&list.ListTask{})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Delete the lists
|
||||
_, err = x.In("id", listIDs).Delete(&List{})
|
||||
_, err = x.In("id", listIDs).Delete(&list.List{})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
|
@ -1,106 +1,112 @@
|
|||
package models
|
||||
package namespace
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/log"
|
||||
"code.vikunja.io/api/pkg/models"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
)
|
||||
|
||||
// IsAdmin returns true or false if the user is admin on that namespace or not
|
||||
func (n *Namespace) IsAdmin(user *User) bool {
|
||||
func (n *Namespace) IsAdmin(u *user.User) bool {
|
||||
// Owners always have admin rights
|
||||
if user.ID == n.Owner.ID {
|
||||
if u.ID == n.Owner.ID {
|
||||
return true
|
||||
}
|
||||
|
||||
// Check user rights
|
||||
if n.checkUserRights(user, UserRightAdmin) {
|
||||
if n.checkUserRights(u, models.UserRightAdmin) {
|
||||
return true
|
||||
}
|
||||
|
||||
// Check if that user is in a team which has admin rights to that namespace
|
||||
return n.checkTeamRights(user, TeamRightAdmin)
|
||||
return n.checkTeamRights(u, models.TeamRightAdmin)
|
||||
}
|
||||
|
||||
// CanWrite checks if a user has write access to a namespace
|
||||
func (n *Namespace) CanWrite(user *User) bool {
|
||||
func (n *Namespace) CanWrite(u *user.User) bool {
|
||||
// Admins always have write access
|
||||
if n.IsAdmin(user) {
|
||||
if n.IsAdmin(u) {
|
||||
return true
|
||||
}
|
||||
|
||||
// Check user rights
|
||||
if n.checkUserRights(user, UserRightWrite) {
|
||||
if n.checkUserRights(u, models.UserRightWrite) {
|
||||
return true
|
||||
}
|
||||
|
||||
// Check if that user is in a team which has write rights to that namespace
|
||||
return n.checkTeamRights(user, TeamRightWrite)
|
||||
return n.checkTeamRights(u, models.TeamRightWrite)
|
||||
}
|
||||
|
||||
// CanRead checks if a user has read access to that namespace
|
||||
func (n *Namespace) CanRead(user *User) bool {
|
||||
func (n *Namespace) CanRead(u *user.User) bool {
|
||||
// Admins always have read access
|
||||
if n.IsAdmin(user) {
|
||||
if n.IsAdmin(u) {
|
||||
return true
|
||||
}
|
||||
|
||||
// Check user rights
|
||||
if n.checkUserRights(user, UserRightRead) {
|
||||
if n.checkUserRights(u, models.UserRightRead) {
|
||||
return true
|
||||
}
|
||||
|
||||
// Check if the user is in a team which has access to the namespace
|
||||
return n.checkTeamRights(user, TeamRightRead)
|
||||
return n.checkTeamRights(u, models.TeamRightRead)
|
||||
}
|
||||
|
||||
// CanUpdate checks if the user can update the namespace
|
||||
func (n *Namespace) CanUpdate(user *User) bool {
|
||||
func (n *Namespace) CanUpdate(u *user.User) bool {
|
||||
nn, err := GetNamespaceByID(n.ID)
|
||||
if err != nil {
|
||||
Log.Error("Error occurred during CanUpdate for Namespace: %s", err)
|
||||
log.Log.Error("Error occurred during CanUpdate for Namespace: %s", err)
|
||||
return false
|
||||
}
|
||||
return nn.IsAdmin(user)
|
||||
return nn.IsAdmin(u)
|
||||
}
|
||||
|
||||
// CanDelete checks if the user can delete a namespace
|
||||
func (n *Namespace) CanDelete(user *User) bool {
|
||||
func (n *Namespace) CanDelete(u *user.User) bool {
|
||||
nn, err := GetNamespaceByID(n.ID)
|
||||
if err != nil {
|
||||
Log.Error("Error occurred during CanDelete for Namespace: %s", err)
|
||||
log.Log.Error("Error occurred during CanDelete for Namespace: %s", err)
|
||||
return false
|
||||
}
|
||||
return nn.IsAdmin(user)
|
||||
return nn.IsAdmin(u)
|
||||
}
|
||||
|
||||
// CanCreate checks if the user can create a new namespace
|
||||
func (n *Namespace) CanCreate(user *User) bool {
|
||||
func (n *Namespace) CanCreate(u *user.User) bool {
|
||||
// This is currently a dummy function, later on we could imagine global limits etc.
|
||||
return true
|
||||
}
|
||||
|
||||
func (n *Namespace) checkTeamRights(user *User, r TeamRight) bool {
|
||||
func (n *Namespace) checkTeamRights(u *user.User, r models.TeamRight) bool {
|
||||
exists, err := 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("namespaces.id = ? "+
|
||||
"AND (team_members.user_id = ? AND team_namespaces.right = ?) "+
|
||||
"OR namespaces.owner_id = ? ", n.ID, user.ID, r, user.ID).
|
||||
"OR namespaces.owner_id = ? ", n.ID, u.ID, r, u.ID).
|
||||
Get(&Namespace{})
|
||||
if err != nil {
|
||||
Log.Error("Error occurred during checkTeamRights for Namespace: %s, TeamRight: %d", err, r)
|
||||
log.Log.Error("Error occurred during checkTeamRights for Namespace: %s, TeamRight: %d", err, r)
|
||||
return false
|
||||
}
|
||||
|
||||
return exists
|
||||
}
|
||||
|
||||
func (n *Namespace) checkUserRights(user *User, r UserRight) bool {
|
||||
func (n *Namespace) checkUserRights(u *user.User, r models.UserRight) bool {
|
||||
exists, err := x.Select("namespaces.*").
|
||||
Table("namespaces").
|
||||
Join("LEFT", "users_namespace", "users_namespace.namespace_id = namespaces.id").
|
||||
Where("namespaces.id = ? AND ("+
|
||||
"namespaces.owner_id = ? "+
|
||||
"OR (users_namespace.user_id = ? AND users_namespace.right = ?))", n.ID, user.ID, user.ID, r).
|
||||
"OR (users_namespace.user_id = ? AND users_namespace.right = ?))", n.ID, u.ID, u.ID, r).
|
||||
Get(&Namespace{})
|
||||
if err != nil {
|
||||
Log.Error("Error occurred during checkUserRights for Namespace: %s, UserRight: %d", err, r)
|
||||
log.Log.Error("Error occurred during checkUserRights for Namespace: %s, UserRight: %d", err, r)
|
||||
return false
|
||||
}
|
||||
|
|
@ -1,6 +1,8 @@
|
|||
package models
|
||||
package namespace
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/errs"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
@ -17,7 +19,7 @@ func TestNamespace_Create(t *testing.T) {
|
|||
}
|
||||
|
||||
// Doer
|
||||
doer, err := GetUserByID(1)
|
||||
doer, err := user.GetUserByID(1)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Try creating it
|
||||
|
@ -36,14 +38,14 @@ func TestNamespace_Create(t *testing.T) {
|
|||
n2 := Namespace{}
|
||||
err = n2.Create(&doer)
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrNamespaceNameCannotBeEmpty(err))
|
||||
assert.True(t, errs.IsErrNamespaceNameCannotBeEmpty(err))
|
||||
|
||||
// Try inserting one with a nonexistant user
|
||||
nUser := &User{ID: 9482385}
|
||||
nUser := &user.User{ID: 9482385}
|
||||
dnsp2 := dummynamespace
|
||||
err = dnsp2.Create(nUser)
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrUserDoesNotExist(err))
|
||||
assert.True(t, errs.IsErrUserDoesNotExist(err))
|
||||
|
||||
// Update it
|
||||
assert.True(t, dummynamespace.CanUpdate(&doer))
|
||||
|
@ -55,19 +57,19 @@ func TestNamespace_Create(t *testing.T) {
|
|||
dummynamespace.Owner.ID = 94829838572
|
||||
err = dummynamespace.Update()
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrUserDoesNotExist(err))
|
||||
assert.True(t, errs.IsErrUserDoesNotExist(err))
|
||||
|
||||
// Try updating without a name
|
||||
dummynamespace.Name = ""
|
||||
err = dummynamespace.Update()
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrNamespaceNameCannotBeEmpty(err))
|
||||
assert.True(t, errs.IsErrNamespaceNameCannotBeEmpty(err))
|
||||
|
||||
// Try updating a nonexistant one
|
||||
n := Namespace{ID: 284729, Name: "Lorem"}
|
||||
err = n.Update()
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrNamespaceDoesNotExist(err))
|
||||
assert.True(t, errs.IsErrNamespaceDoesNotExist(err))
|
||||
|
||||
// Delete it
|
||||
assert.True(t, dummynamespace.CanDelete(&doer))
|
||||
|
@ -77,12 +79,12 @@ func TestNamespace_Create(t *testing.T) {
|
|||
// Try deleting a nonexistant one
|
||||
err = n.Delete()
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrNamespaceDoesNotExist(err))
|
||||
assert.True(t, errs.IsErrNamespaceDoesNotExist(err))
|
||||
|
||||
// Check if it was successfully deleted
|
||||
err = dummynamespace.ReadOne()
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrNamespaceDoesNotExist(err))
|
||||
assert.True(t, errs.IsErrNamespaceDoesNotExist(err))
|
||||
|
||||
// Get all namespaces of a user
|
||||
nsps, err := n.ReadAll(&doer)
|
|
@ -1,10 +1,15 @@
|
|||
package models
|
||||
package namespace
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/errs"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
)
|
||||
|
||||
// Update implements the update method via the interface
|
||||
func (n *Namespace) Update() (err error) {
|
||||
// Check if we have at least a name
|
||||
if n.Name == "" {
|
||||
return ErrNamespaceNameCannotBeEmpty{NamespaceID: n.ID}
|
||||
return errs.ErrNamespaceNameCannotBeEmpty{NamespaceID: n.ID}
|
||||
}
|
||||
|
||||
// Check if the namespace exists
|
||||
|
@ -16,7 +21,7 @@ func (n *Namespace) Update() (err error) {
|
|||
// Check if the (new) owner exists
|
||||
n.OwnerID = n.Owner.ID
|
||||
if currentNamespace.OwnerID != n.OwnerID {
|
||||
n.Owner, err = GetUserByID(n.OwnerID)
|
||||
n.Owner, err = user.GetUserByID(n.OwnerID)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
package v1
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/models"
|
||||
"code.vikunja.io/api/pkg/models"
|
||||
"github.com/labstack/echo"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
@ -33,10 +33,10 @@ func GetListsByNamespaceID(c echo.Context) error {
|
|||
// Get our namespace
|
||||
namespace, err := getNamespace(c)
|
||||
if err != nil {
|
||||
if models.IsErrNamespaceDoesNotExist(err) {
|
||||
if models.errs.IsErrNamespaceDoesNotExist(err) {
|
||||
return c.JSON(http.StatusNotFound, models.Message{"Namespace not found."})
|
||||
}
|
||||
if models.IsErrUserDoesNotHaveAccessToNamespace(err) {
|
||||
if models.errs.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 occurred."})
|
||||
|
@ -45,7 +45,7 @@ func GetListsByNamespaceID(c echo.Context) error {
|
|||
// Get the lists
|
||||
lists, err := models.GetListsByNamespaceID(namespace.ID)
|
||||
if err != nil {
|
||||
if models.IsErrNamespaceDoesNotExist(err) {
|
||||
if models.errs.IsErrNamespaceDoesNotExist(err) {
|
||||
return c.JSON(http.StatusNotFound, models.Message{"Namespace not found."})
|
||||
}
|
||||
return c.JSON(http.StatusInternalServerError, models.Message{"An error occurred."})
|
|
@ -1,7 +1,7 @@
|
|||
package v1
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/models"
|
||||
"code.vikunja.io/api/pkg/models"
|
||||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
"github.com/dgrijalva/jwt-go"
|
58
pkg/routes/api/v1/swagger/options.go
Normal file
58
pkg/routes/api/v1/swagger/options.go
Normal file
|
@ -0,0 +1,58 @@
|
|||
package swagger
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/list"
|
||||
"code.vikunja.io/api/pkg/namespace"
|
||||
"code.vikunja.io/api/pkg/sharing"
|
||||
"code.vikunja.io/api/pkg/team"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
)
|
||||
|
||||
// not actually a response, just a hack to get go-swagger to include definitions
|
||||
// of the various XYZOption structs
|
||||
|
||||
// parameterBodies
|
||||
// swagger:response parameterBodies
|
||||
type swaggerParameterBodies struct {
|
||||
// in:body
|
||||
UserLogin user.UserLogin
|
||||
|
||||
// in:body
|
||||
APIUserPassword user.APIUserPassword
|
||||
|
||||
// in:body
|
||||
List list.List
|
||||
|
||||
// in:body
|
||||
ListTask list.ListTask
|
||||
|
||||
// in:body
|
||||
Namespace namespace.Namespace
|
||||
|
||||
// in:body
|
||||
Team team.Team
|
||||
|
||||
// in:body
|
||||
TeamMember team.TeamMember
|
||||
|
||||
// in:body
|
||||
TeamList sharing.TeamList
|
||||
|
||||
// in:body
|
||||
TeamNamespace sharing.TeamNamespace
|
||||
|
||||
// in:body
|
||||
ListUser sharing.ListUser
|
||||
|
||||
// in:body
|
||||
NamespaceUser sharing.NamespaceUser
|
||||
|
||||
// in:body
|
||||
PasswordReset user.PasswordReset
|
||||
|
||||
// in:body
|
||||
PasswordTokenRequest user.PasswordTokenRequest
|
||||
|
||||
// in:body
|
||||
EmailConfirm user.EmailConfirm
|
||||
}
|
|
@ -1,6 +1,13 @@
|
|||
package swagger
|
||||
|
||||
import "code.vikunja.io/api/models"
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/list"
|
||||
"code.vikunja.io/api/pkg/models"
|
||||
"code.vikunja.io/api/pkg/namespace"
|
||||
"code.vikunja.io/api/pkg/sharing"
|
||||
"code.vikunja.io/api/pkg/team"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
)
|
||||
|
||||
// Message
|
||||
// swagger:response Message
|
||||
|
@ -17,7 +24,7 @@ type swaggerResponseMessage struct {
|
|||
// swagger:response User
|
||||
type swaggerResponseUser struct {
|
||||
// in:body
|
||||
Body models.User `json:"body"`
|
||||
Body user.User `json:"body"`
|
||||
}
|
||||
|
||||
// Token
|
||||
|
@ -41,14 +48,14 @@ type swaggerResponseToken struct {
|
|||
// swagger:response List
|
||||
type swaggerResponseLIst struct {
|
||||
// in:body
|
||||
Body models.List `json:"body"`
|
||||
Body list.List `json:"body"`
|
||||
}
|
||||
|
||||
// ListTask
|
||||
// swagger:response ListTask
|
||||
type swaggerResponseLIstTask struct {
|
||||
// in:body
|
||||
Body models.ListTask `json:"body"`
|
||||
Body list.ListTask `json:"body"`
|
||||
}
|
||||
|
||||
// ================
|
||||
|
@ -59,7 +66,7 @@ type swaggerResponseLIstTask struct {
|
|||
// swagger:response Namespace
|
||||
type swaggerResponseNamespace struct {
|
||||
// in:body
|
||||
Body models.Namespace `json:"body"`
|
||||
Body namespace.Namespace `json:"body"`
|
||||
}
|
||||
|
||||
// ================
|
||||
|
@ -70,40 +77,40 @@ type swaggerResponseNamespace struct {
|
|||
// swagger:response Team
|
||||
type swaggerResponseTeam struct {
|
||||
// in:body
|
||||
Body models.Team `json:"body"`
|
||||
Body team.Team `json:"body"`
|
||||
}
|
||||
|
||||
// TeamMember
|
||||
// swagger:response TeamMember
|
||||
type swaggerResponseTeamMember struct {
|
||||
// in:body
|
||||
Body models.TeamMember `json:"body"`
|
||||
Body team.TeamMember `json:"body"`
|
||||
}
|
||||
|
||||
// TeamList
|
||||
// swagger:response TeamList
|
||||
type swaggerResponseTeamList struct {
|
||||
// in:body
|
||||
Body models.TeamList `json:"body"`
|
||||
Body sharing.TeamList `json:"body"`
|
||||
}
|
||||
|
||||
// TeamNamespace
|
||||
// swagger:response TeamNamespace
|
||||
type swaggerResponseTeamNamespace struct {
|
||||
// in:body
|
||||
Body models.TeamNamespace `json:"body"`
|
||||
Body sharing.TeamNamespace `json:"body"`
|
||||
}
|
||||
|
||||
// UserList
|
||||
// swagger:response UserList
|
||||
type swaggerResponseUserList struct {
|
||||
// in:body
|
||||
Body models.ListUser `json:"body"`
|
||||
Body sharing.ListUser `json:"body"`
|
||||
}
|
||||
|
||||
// UserNamespace
|
||||
// swagger:response UserNamespace
|
||||
type swaggerResponseUserNamespace struct {
|
||||
// in:body
|
||||
Body models.NamespaceUser `json:"body"`
|
||||
Body sharing.NamespaceUser `json:"body"`
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
package v1
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/models"
|
||||
"code.vikunja.io/api/pkg/models"
|
||||
"fmt"
|
||||
"github.com/dgrijalva/jwt-go"
|
||||
"github.com/labstack/echo"
|
|
@ -1,8 +1,8 @@
|
|||
package v1
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/models"
|
||||
"code.vikunja.io/api/routes/crud"
|
||||
"code.vikunja.io/api/pkg/models"
|
||||
"code.vikunja.io/api/pkg/routes/crud"
|
||||
"github.com/labstack/echo"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
@ -62,7 +62,7 @@ func userAddOrUpdate(c echo.Context) error {
|
|||
var exists = true
|
||||
_, err := models.GetUserByID(datUser.ID)
|
||||
if err != nil {
|
||||
if models.IsErrUserDoesNotExist(err) {
|
||||
if models.errs.IsErrUserDoesNotExist(err) {
|
||||
exists = false
|
||||
} else {
|
||||
return c.JSON(http.StatusInternalServerError, models.Message{"Could not check if the user exists."})
|
|
@ -1,8 +1,8 @@
|
|||
package v1
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/models"
|
||||
"code.vikunja.io/api/routes/crud"
|
||||
"code.vikunja.io/api/pkg/models"
|
||||
"code.vikunja.io/api/pkg/routes/crud"
|
||||
"github.com/labstack/echo"
|
||||
"net/http"
|
||||
)
|
|
@ -1,8 +1,8 @@
|
|||
package v1
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/models"
|
||||
"code.vikunja.io/api/routes/crud"
|
||||
"code.vikunja.io/api/pkg/models"
|
||||
"code.vikunja.io/api/pkg/routes/crud"
|
||||
"github.com/labstack/echo"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
@ -26,7 +26,7 @@ func UserDelete(c echo.Context) error {
|
|||
_, err = models.GetUserByID(userID)
|
||||
|
||||
if err != nil {
|
||||
if models.IsErrUserDoesNotExist(err) {
|
||||
if models.errs.IsErrUserDoesNotExist(err) {
|
||||
return c.JSON(http.StatusNotFound, models.Message{"The user does not exist."})
|
||||
}
|
||||
return c.JSON(http.StatusInternalServerError, models.Message{"Could not get user."})
|
|
@ -1,8 +1,8 @@
|
|||
package v1
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/models"
|
||||
"code.vikunja.io/api/routes/crud"
|
||||
"code.vikunja.io/api/pkg/models"
|
||||
"code.vikunja.io/api/pkg/routes/crud"
|
||||
"github.com/labstack/echo"
|
||||
"net/http"
|
||||
)
|
|
@ -1,8 +1,8 @@
|
|||
package v1
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/models"
|
||||
"code.vikunja.io/api/routes/crud"
|
||||
"code.vikunja.io/api/pkg/models"
|
||||
"code.vikunja.io/api/pkg/routes/crud"
|
||||
"github.com/labstack/echo"
|
||||
"net/http"
|
||||
)
|
|
@ -1,8 +1,8 @@
|
|||
package v1
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/models"
|
||||
"code.vikunja.io/api/routes/crud"
|
||||
"code.vikunja.io/api/pkg/models"
|
||||
"code.vikunja.io/api/pkg/routes/crud"
|
||||
"github.com/labstack/echo"
|
||||
"net/http"
|
||||
)
|
|
@ -1,8 +1,8 @@
|
|||
package v1
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/models"
|
||||
"code.vikunja.io/api/routes/crud"
|
||||
"code.vikunja.io/api/pkg/models"
|
||||
"code.vikunja.io/api/pkg/routes/crud"
|
||||
"github.com/labstack/echo"
|
||||
"net/http"
|
||||
)
|
|
@ -1,7 +1,8 @@
|
|||
package crud
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/models"
|
||||
"code.vikunja.io/api/pkg/log"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"github.com/labstack/echo"
|
||||
"net/http"
|
||||
)
|
||||
|
@ -17,14 +18,14 @@ func (c *WebHandler) CreateWeb(ctx echo.Context) error {
|
|||
}
|
||||
|
||||
// Get the user to pass for later checks
|
||||
currentUser, err := models.GetCurrentUser(ctx)
|
||||
currentUser, err := user.GetCurrentUser(ctx)
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusInternalServerError, "Could not determine the current user.")
|
||||
}
|
||||
|
||||
// Check rights
|
||||
if !currentStruct.CanCreate(¤tUser) {
|
||||
models.Log.Noticef("%s [ID: %d] tried to create while not having the rights for it", currentUser.Username, currentUser.ID)
|
||||
log.Log.Noticef("%s [ID: %d] tried to create while not having the rights for it", currentUser.Username, currentUser.ID)
|
||||
return echo.NewHTTPError(http.StatusForbidden)
|
||||
}
|
||||
|
|
@ -1,7 +1,9 @@
|
|||
package crud
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/models"
|
||||
"code.vikunja.io/api/pkg/log"
|
||||
"code.vikunja.io/api/pkg/models"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"github.com/labstack/echo"
|
||||
"net/http"
|
||||
)
|
||||
|
@ -18,12 +20,12 @@ func (c *WebHandler) DeleteWeb(ctx echo.Context) error {
|
|||
}
|
||||
|
||||
// Check if the user has the right to delete
|
||||
user, err := models.GetCurrentUser(ctx)
|
||||
currentUser, err := user.GetCurrentUser(ctx)
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusInternalServerError)
|
||||
}
|
||||
if !currentStruct.CanDelete(&user) {
|
||||
models.Log.Noticef("%s [ID: %d] tried to delete while not having the rights for it", user.Username, user.ID)
|
||||
if !currentStruct.CanDelete(¤tUser) {
|
||||
log.Log.Noticef("%s [ID: %d] tried to delete while not having the rights for it", currentUser.Username, currentUser.ID)
|
||||
return echo.NewHTTPError(http.StatusForbidden)
|
||||
}
|
||||
|
|
@ -1,7 +1,9 @@
|
|||
package crud
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/models"
|
||||
"code.vikunja.io/api/pkg/errs"
|
||||
"code.vikunja.io/api/pkg/log"
|
||||
"code.vikunja.io/api/pkg/models"
|
||||
"github.com/labstack/echo"
|
||||
"net/http"
|
||||
)
|
||||
|
@ -20,10 +22,10 @@ type CObject interface {
|
|||
|
||||
// HandleHTTPError does what it says
|
||||
func HandleHTTPError(err error) *echo.HTTPError {
|
||||
if a, has := err.(models.HTTPErrorProcessor); has {
|
||||
if a, has := err.(errs.HTTPErrorProcessor); has {
|
||||
errDetails := a.HTTPError()
|
||||
return echo.NewHTTPError(errDetails.HTTPCode, errDetails)
|
||||
}
|
||||
models.Log.Error(err.Error())
|
||||
log.Log.Error(err.Error())
|
||||
return echo.NewHTTPError(http.StatusInternalServerError)
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
package crud
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/models"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"github.com/labstack/echo"
|
||||
"net/http"
|
||||
)
|
||||
|
@ -11,7 +11,7 @@ func (c *WebHandler) ReadAllWeb(ctx echo.Context) error {
|
|||
// Get our model
|
||||
currentStruct := c.EmptyStruct()
|
||||
|
||||
currentUser, err := models.GetCurrentUser(ctx)
|
||||
currentUser, err := user.GetCurrentUser(ctx)
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusInternalServerError, "Could not determine the current user.")
|
||||
}
|
|
@ -1,7 +1,8 @@
|
|||
package crud
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/models"
|
||||
"code.vikunja.io/api/pkg/log"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"github.com/labstack/echo"
|
||||
"net/http"
|
||||
)
|
||||
|
@ -24,12 +25,12 @@ func (c *WebHandler) ReadOneWeb(ctx echo.Context) error {
|
|||
|
||||
// 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)
|
||||
currentUser, err := user.GetCurrentUser(ctx)
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusInternalServerError, "Could not determine the current user.")
|
||||
}
|
||||
if !currentStruct.CanRead(¤tUser) {
|
||||
models.Log.Noticef("%s [ID: %d] tried to read while not having the rights for it", currentUser.Username, currentUser.ID)
|
||||
log.Log.Noticef("%s [ID: %d] tried to read while not having the rights for it", currentUser.Username, currentUser.ID)
|
||||
return echo.NewHTTPError(http.StatusForbidden, "You don't have the right to see this")
|
||||
}
|
||||
|
|
@ -1,7 +1,8 @@
|
|||
package crud
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/models"
|
||||
"code.vikunja.io/api/pkg/log"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"github.com/labstack/echo"
|
||||
"net/http"
|
||||
)
|
||||
|
@ -18,12 +19,12 @@ func (c *WebHandler) UpdateWeb(ctx echo.Context) error {
|
|||
}
|
||||
|
||||
// Check if the user has the right to do that
|
||||
currentUser, err := models.GetCurrentUser(ctx)
|
||||
currentUser, err := user.GetCurrentUser(ctx)
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusInternalServerError, "Could not determine the current user.")
|
||||
}
|
||||
if !currentStruct.CanUpdate(¤tUser) {
|
||||
models.Log.Noticef("%s [ID: %d] tried to update while not having the rights for it", currentUser.Username, currentUser.ID)
|
||||
log.Log.Noticef("%s [ID: %d] tried to update while not having the rights for it", currentUser.Username, currentUser.ID)
|
||||
return echo.NewHTTPError(http.StatusForbidden)
|
||||
}
|
||||
|
|
@ -27,13 +27,16 @@
|
|||
package routes
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/list"
|
||||
"code.vikunja.io/api/pkg/namespace"
|
||||
"code.vikunja.io/api/pkg/sharing"
|
||||
"code.vikunja.io/api/pkg/team"
|
||||
"github.com/labstack/echo"
|
||||
"github.com/labstack/echo/middleware"
|
||||
|
||||
"code.vikunja.io/api/models"
|
||||
apiv1 "code.vikunja.io/api/routes/api/v1"
|
||||
_ "code.vikunja.io/api/routes/api/v1/swagger" // for docs generation
|
||||
"code.vikunja.io/api/routes/crud"
|
||||
apiv1 "code.vikunja.io/api/pkg/routes/api/v1"
|
||||
_ "code.vikunja.io/api/pkg/routes/api/v1/swagger" // for docs generation
|
||||
"code.vikunja.io/api/pkg/routes/crud"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
|
@ -81,7 +84,7 @@ func RegisterRoutes(e *echo.Echo) {
|
|||
|
||||
listHandler := &crud.WebHandler{
|
||||
EmptyStruct: func() crud.CObject {
|
||||
return &models.List{}
|
||||
return &list.List{}
|
||||
},
|
||||
}
|
||||
a.GET("/lists", listHandler.ReadAllWeb)
|
||||
|
@ -92,7 +95,7 @@ func RegisterRoutes(e *echo.Echo) {
|
|||
|
||||
taskHandler := &crud.WebHandler{
|
||||
EmptyStruct: func() crud.CObject {
|
||||
return &models.ListTask{}
|
||||
return &list.ListTask{}
|
||||
},
|
||||
}
|
||||
a.PUT("/lists/:list", taskHandler.CreateWeb)
|
||||
|
@ -101,7 +104,7 @@ func RegisterRoutes(e *echo.Echo) {
|
|||
|
||||
listTeamHandler := &crud.WebHandler{
|
||||
EmptyStruct: func() crud.CObject {
|
||||
return &models.TeamList{}
|
||||
return &sharing.TeamList{}
|
||||
},
|
||||
}
|
||||
a.GET("/lists/:list/teams", listTeamHandler.ReadAllWeb)
|
||||
|
@ -111,7 +114,7 @@ func RegisterRoutes(e *echo.Echo) {
|
|||
|
||||
listUserHandler := &crud.WebHandler{
|
||||
EmptyStruct: func() crud.CObject {
|
||||
return &models.ListUser{}
|
||||
return &sharing.ListUser{}
|
||||
},
|
||||
}
|
||||
a.GET("/lists/:list/users", listUserHandler.ReadAllWeb)
|
||||
|
@ -121,7 +124,7 @@ func RegisterRoutes(e *echo.Echo) {
|
|||
|
||||
namespaceHandler := &crud.WebHandler{
|
||||
EmptyStruct: func() crud.CObject {
|
||||
return &models.Namespace{}
|
||||
return &namespace.Namespace{}
|
||||
},
|
||||
}
|
||||
a.GET("/namespaces", namespaceHandler.ReadAllWeb)
|
||||
|
@ -133,7 +136,7 @@ func RegisterRoutes(e *echo.Echo) {
|
|||
|
||||
namespaceTeamHandler := &crud.WebHandler{
|
||||
EmptyStruct: func() crud.CObject {
|
||||
return &models.TeamNamespace{}
|
||||
return &sharing.TeamNamespace{}
|
||||
},
|
||||
}
|
||||
a.GET("/namespaces/:namespace/teams", namespaceTeamHandler.ReadAllWeb)
|
||||
|
@ -143,7 +146,7 @@ func RegisterRoutes(e *echo.Echo) {
|
|||
|
||||
namespaceUserHandler := &crud.WebHandler{
|
||||
EmptyStruct: func() crud.CObject {
|
||||
return &models.NamespaceUser{}
|
||||
return &sharing.NamespaceUser{}
|
||||
},
|
||||
}
|
||||
a.GET("/namespaces/:namespace/users", namespaceUserHandler.ReadAllWeb)
|
||||
|
@ -153,7 +156,7 @@ func RegisterRoutes(e *echo.Echo) {
|
|||
|
||||
teamHandler := &crud.WebHandler{
|
||||
EmptyStruct: func() crud.CObject {
|
||||
return &models.Team{}
|
||||
return &team.Team{}
|
||||
},
|
||||
}
|
||||
a.GET("/teams", teamHandler.ReadAllWeb)
|
||||
|
@ -164,7 +167,7 @@ func RegisterRoutes(e *echo.Echo) {
|
|||
|
||||
teamMemberHandler := &crud.WebHandler{
|
||||
EmptyStruct: func() crud.CObject {
|
||||
return &models.TeamMember{}
|
||||
return &team.TeamMember{}
|
||||
},
|
||||
}
|
||||
a.PUT("/teams/:team/members", teamMemberHandler.CreateWeb)
|
12
pkg/sharing/init.go
Normal file
12
pkg/sharing/init.go
Normal file
|
@ -0,0 +1,12 @@
|
|||
package sharing
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/models"
|
||||
"github.com/go-xorm/xorm"
|
||||
)
|
||||
|
||||
var x *xorm.Engine
|
||||
|
||||
func init() {
|
||||
x = models.GetEngine()
|
||||
}
|
30
pkg/sharing/list_users.go
Normal file
30
pkg/sharing/list_users.go
Normal file
|
@ -0,0 +1,30 @@
|
|||
package sharing
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/models"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
)
|
||||
|
||||
// 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 INDEX" json:"user_id" param:"user"`
|
||||
ListID int64 `xorm:"int(11) not null INDEX" json:"list_id" param:"list"`
|
||||
Right models.UserRight `xorm:"int(11) INDEX" json:"right"`
|
||||
|
||||
Created int64 `xorm:"created" json:"created"`
|
||||
Updated int64 `xorm:"updated" json:"updated"`
|
||||
|
||||
models.CRUDable `xorm:"-" json:"-"`
|
||||
models.Rights `xorm:"-" json:"-"`
|
||||
}
|
||||
|
||||
// TableName is the table name for ListUser
|
||||
func (ListUser) TableName() string {
|
||||
return "users_list"
|
||||
}
|
||||
|
||||
type userWithRight struct {
|
||||
user.User `xorm:"extends"`
|
||||
Right models.UserRight `json:"right"`
|
||||
}
|
|
@ -1,28 +1,34 @@
|
|||
package models
|
||||
package sharing
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/errs"
|
||||
"code.vikunja.io/api/pkg/list"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
)
|
||||
|
||||
// Create creates a new list <-> user relation
|
||||
func (ul *ListUser) Create(user *User) (err error) {
|
||||
func (ul *ListUser) Create(u *user.User) (err error) {
|
||||
|
||||
// Check if the right is valid
|
||||
if err := ul.Right.isValid(); err != nil {
|
||||
if err := ul.Right.IsValid(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Check if the list exists
|
||||
l := &List{ID: ul.ListID}
|
||||
l := &list.List{ID: ul.ListID}
|
||||
if err = l.GetSimpleByID(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Check if the user exists
|
||||
if _, err = GetUserByID(ul.UserID); err != nil {
|
||||
if _, err = user.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}
|
||||
return errs.ErrUserAlreadyHasAccess{UserID: ul.UserID, ListID: ul.ListID}
|
||||
}
|
||||
|
||||
exist, err := x.Where("list_id = ? AND user_id = ?", ul.ListID, ul.UserID).Get(&ListUser{})
|
||||
|
@ -30,7 +36,7 @@ func (ul *ListUser) Create(user *User) (err error) {
|
|||
return
|
||||
}
|
||||
if exist {
|
||||
return ErrUserAlreadyHasAccess{UserID: ul.UserID, ListID: ul.ListID}
|
||||
return errs.ErrUserAlreadyHasAccess{UserID: ul.UserID, ListID: ul.ListID}
|
||||
}
|
||||
|
||||
// Insert user <-> list relation
|
|
@ -1,10 +1,15 @@
|
|||
package models
|
||||
package sharing
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/errs"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
)
|
||||
|
||||
// Delete deletes a list <-> user relation
|
||||
func (lu *ListUser) Delete() (err error) {
|
||||
|
||||
// Check if the user exists
|
||||
_, err = GetUserByID(lu.UserID)
|
||||
_, err = user.GetUserByID(lu.UserID)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -16,7 +21,7 @@ func (lu *ListUser) Delete() (err error) {
|
|||
return
|
||||
}
|
||||
if !has {
|
||||
return ErrUserDoesNotHaveAccessToList{ListID: lu.ListID, UserID: lu.UserID}
|
||||
return errs.ErrUserDoesNotHaveAccessToList{ListID: lu.ListID, UserID: lu.UserID}
|
||||
}
|
||||
|
||||
_, err = x.Where("user_id = ? AND list_id = ?", lu.UserID, lu.ListID).
|
|
@ -1,14 +1,20 @@
|
|||
package models
|
||||
package sharing
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/errs"
|
||||
"code.vikunja.io/api/pkg/list"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
)
|
||||
|
||||
// ReadAll gets all users who have access to a list
|
||||
func (ul *ListUser) ReadAll(user *User) (interface{}, error) {
|
||||
func (ul *ListUser) ReadAll(u *user.User) (interface{}, error) {
|
||||
// Check if the user has access to the list
|
||||
l := &List{ID: ul.ListID}
|
||||
l := &list.List{ID: ul.ListID}
|
||||
if err := l.GetSimpleByID(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !l.CanRead(user) {
|
||||
return nil, ErrNeedToHaveListReadAccess{}
|
||||
if !l.CanRead(u) {
|
||||
return nil, errs.ErrNeedToHaveListReadAccess{}
|
||||
}
|
||||
|
||||
// Get all users
|
40
pkg/sharing/list_users_rights.go
Normal file
40
pkg/sharing/list_users_rights.go
Normal file
|
@ -0,0 +1,40 @@
|
|||
package sharing
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/list"
|
||||
"code.vikunja.io/api/pkg/log"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
)
|
||||
|
||||
// CanCreate checks if the user can create a new user <-> list relation
|
||||
func (lu *ListUser) CanCreate(doer *user.User) bool {
|
||||
// Get the list and check if the user has write access on it
|
||||
l := list.List{ID: lu.ListID}
|
||||
if err := l.GetSimpleByID(); err != nil {
|
||||
log.Log.Error("Error occurred during CanCreate for ListUser: %s", err)
|
||||
return false
|
||||
}
|
||||
return l.CanWrite(doer)
|
||||
}
|
||||
|
||||
// CanDelete checks if the user can delete a user <-> list relation
|
||||
func (lu *ListUser) CanDelete(doer *user.User) bool {
|
||||
// Get the list and check if the user has write access on it
|
||||
l := list.List{ID: lu.ListID}
|
||||
if err := l.GetSimpleByID(); err != nil {
|
||||
log.Log.Error("Error occurred during CanDelete for ListUser: %s", err)
|
||||
return false
|
||||
}
|
||||
return l.CanWrite(doer)
|
||||
}
|
||||
|
||||
// CanUpdate checks if the user can update a user <-> list relation
|
||||
func (lu *ListUser) CanUpdate(doer *user.User) bool {
|
||||
// Get the list and check if the user has write access on it
|
||||
l := list.List{ID: lu.ListID}
|
||||
if err := l.GetSimpleByID(); err != nil {
|
||||
log.Log.Error("Error occurred during CanUpdate for ListUser: %s", err)
|
||||
return false
|
||||
}
|
||||
return l.CanWrite(doer)
|
||||
}
|
|
@ -1,10 +1,10 @@
|
|||
package models
|
||||
package sharing
|
||||
|
||||
// Update updates a user <-> list relation
|
||||
func (lu *ListUser) Update() (err error) {
|
||||
|
||||
// Check if the right is valid
|
||||
if err := lu.Right.isValid(); err != nil {
|
||||
if err := lu.Right.IsValid(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
22
pkg/sharing/namespace_users.go
Normal file
22
pkg/sharing/namespace_users.go
Normal file
|
@ -0,0 +1,22 @@
|
|||
package sharing
|
||||
|
||||
import "code.vikunja.io/api/pkg/models"
|
||||
|
||||
// NamespaceUser represents a namespace <-> user relation
|
||||
type NamespaceUser struct {
|
||||
ID int64 `xorm:"int(11) autoincr not null unique pk" json:"id" param:"namespace"`
|
||||
UserID int64 `xorm:"int(11) not null INDEX" json:"user_id" param:"user"`
|
||||
NamespaceID int64 `xorm:"int(11) not null INDEX" json:"namespace_id" param:"namespace"`
|
||||
Right models.UserRight `xorm:"int(11) INDEX" json:"right"`
|
||||
|
||||
Created int64 `xorm:"created" json:"created"`
|
||||
Updated int64 `xorm:"updated" json:"updated"`
|
||||
|
||||
models.CRUDable `xorm:"-" json:"-"`
|
||||
models.Rights `xorm:"-" json:"-"`
|
||||
}
|
||||
|
||||
// TableName is the table name for NamespaceUser
|
||||
func (NamespaceUser) TableName() string {
|
||||
return "users_namespace"
|
||||
}
|
|
@ -1,31 +1,37 @@
|
|||
package models
|
||||
package sharing
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/errs"
|
||||
"code.vikunja.io/api/pkg/namespace"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
)
|
||||
|
||||
// Create creates a new namespace <-> user relation
|
||||
func (un *NamespaceUser) Create(user *User) (err error) {
|
||||
func (un *NamespaceUser) Create(u *user.User) (err error) {
|
||||
|
||||
// Reset the id
|
||||
un.ID = 0
|
||||
|
||||
// Check if the right is valid
|
||||
if err := un.Right.isValid(); err != nil {
|
||||
if err := un.Right.IsValid(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Check if the namespace exists
|
||||
l, err := GetNamespaceByID(un.NamespaceID)
|
||||
l, err := namespace.GetNamespaceByID(un.NamespaceID)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Check if the user exists
|
||||
if _, err = GetUserByID(un.UserID); err != nil {
|
||||
if _, err = user.GetUserByID(un.UserID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Check if the user already has access or is owner of that namespace
|
||||
// We explicitly DO NOT check for teams here
|
||||
if l.OwnerID == un.UserID {
|
||||
return ErrUserAlreadyHasNamespaceAccess{UserID: un.UserID, NamespaceID: un.NamespaceID}
|
||||
return errs.ErrUserAlreadyHasNamespaceAccess{UserID: un.UserID, NamespaceID: un.NamespaceID}
|
||||
}
|
||||
|
||||
exist, err := x.Where("namespace_id = ? AND user_id = ?", un.NamespaceID, un.UserID).Get(&NamespaceUser{})
|
||||
|
@ -33,7 +39,7 @@ func (un *NamespaceUser) Create(user *User) (err error) {
|
|||
return
|
||||
}
|
||||
if exist {
|
||||
return ErrUserAlreadyHasNamespaceAccess{UserID: un.UserID, NamespaceID: un.NamespaceID}
|
||||
return errs.ErrUserAlreadyHasNamespaceAccess{UserID: un.UserID, NamespaceID: un.NamespaceID}
|
||||
}
|
||||
|
||||
// Insert user <-> namespace relation
|
|
@ -1,10 +1,15 @@
|
|||
package models
|
||||
package sharing
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/errs"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
)
|
||||
|
||||
// Delete deletes a namespace <-> user relation
|
||||
func (nu *NamespaceUser) Delete() (err error) {
|
||||
|
||||
// Check if the user exists
|
||||
_, err = GetUserByID(nu.UserID)
|
||||
_, err = user.GetUserByID(nu.UserID)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -16,7 +21,7 @@ func (nu *NamespaceUser) Delete() (err error) {
|
|||
return
|
||||
}
|
||||
if !has {
|
||||
return ErrUserDoesNotHaveAccessToNamespace{NamespaceID: nu.NamespaceID, UserID: nu.UserID}
|
||||
return errs.ErrUserDoesNotHaveAccessToNamespace{NamespaceID: nu.NamespaceID, UserID: nu.UserID}
|
||||
}
|
||||
|
||||
_, err = x.Where("user_id = ? AND namespace_id = ?", nu.UserID, nu.NamespaceID).
|
|
@ -1,14 +1,20 @@
|
|||
package models
|
||||
package sharing
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/errs"
|
||||
"code.vikunja.io/api/pkg/namespace"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
)
|
||||
|
||||
// ReadAll gets all users who have access to a namespace
|
||||
func (un *NamespaceUser) ReadAll(user *User) (interface{}, error) {
|
||||
func (un *NamespaceUser) ReadAll(u *user.User) (interface{}, error) {
|
||||
// Check if the user has access to the namespace
|
||||
l, err := GetNamespaceByID(un.NamespaceID)
|
||||
l, err := namespace.GetNamespaceByID(un.NamespaceID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !l.CanRead(user) {
|
||||
return nil, ErrNeedToHaveNamespaceReadAccess{}
|
||||
if !l.CanRead(u) {
|
||||
return nil, errs.ErrNeedToHaveNamespaceReadAccess{}
|
||||
}
|
||||
|
||||
// Get all users
|
40
pkg/sharing/namespace_users_rights.go
Normal file
40
pkg/sharing/namespace_users_rights.go
Normal file
|
@ -0,0 +1,40 @@
|
|||
package sharing
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/log"
|
||||
"code.vikunja.io/api/pkg/namespace"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
)
|
||||
|
||||
// CanCreate checks if the user can create a new user <-> namespace relation
|
||||
func (nu *NamespaceUser) CanCreate(doer *user.User) bool {
|
||||
// Get the namespace and check if the user has write access on it
|
||||
n, err := namespace.GetNamespaceByID(nu.NamespaceID)
|
||||
if err != nil {
|
||||
log.Log.Error("Error occurred during CanCreate for NamespaceUser: %s", err)
|
||||
return false
|
||||
}
|
||||
return n.CanWrite(doer)
|
||||
}
|
||||
|
||||
// CanDelete checks if the user can delete a user <-> namespace relation
|
||||
func (nu *NamespaceUser) CanDelete(doer *user.User) bool {
|
||||
// Get the namespace and check if the user has write access on it
|
||||
n, err := namespace.GetNamespaceByID(nu.NamespaceID)
|
||||
if err != nil {
|
||||
log.Log.Error("Error occurred during CanDelete for NamespaceUser: %s", err)
|
||||
return false
|
||||
}
|
||||
return n.CanWrite(doer)
|
||||
}
|
||||
|
||||
// CanUpdate checks if the user can update a user <-> namespace relation
|
||||
func (nu *NamespaceUser) CanUpdate(doer *user.User) bool {
|
||||
// Get the namespace and check if the user has write access on it
|
||||
n, err := namespace.GetNamespaceByID(nu.NamespaceID)
|
||||
if err != nil {
|
||||
log.Log.Error("Error occurred during CanUpdate for NamespaceUser: %s", err)
|
||||
return false
|
||||
}
|
||||
return n.CanWrite(doer)
|
||||
}
|
|
@ -1,10 +1,10 @@
|
|||
package models
|
||||
package sharing
|
||||
|
||||
// Update updates a user <-> namespace relation
|
||||
func (nu *NamespaceUser) Update() (err error) {
|
||||
|
||||
// Check if the right is valid
|
||||
if err := nu.Right.isValid(); err != nil {
|
||||
if err := nu.Right.IsValid(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
30
pkg/sharing/team_list.go
Normal file
30
pkg/sharing/team_list.go
Normal file
|
@ -0,0 +1,30 @@
|
|||
package sharing
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/models"
|
||||
"code.vikunja.io/api/pkg/team"
|
||||
)
|
||||
|
||||
// TeamList defines the relation between a team and a list
|
||||
type TeamList struct {
|
||||
ID int64 `xorm:"int(11) autoincr not null unique pk" json:"id"`
|
||||
TeamID int64 `xorm:"int(11) not null INDEX" json:"team_id" param:"team"`
|
||||
ListID int64 `xorm:"int(11) not null INDEX" json:"list_id" param:"list"`
|
||||
Right models.TeamRight `xorm:"int(11) INDEX" json:"right"`
|
||||
|
||||
Created int64 `xorm:"created" json:"created"`
|
||||
Updated int64 `xorm:"updated" json:"updated"`
|
||||
|
||||
models.CRUDable `xorm:"-" json:"-"`
|
||||
models.Rights `xorm:"-" json:"-"`
|
||||
}
|
||||
|
||||
// TableName makes beautiful table names
|
||||
func (TeamList) TableName() string {
|
||||
return "team_list"
|
||||
}
|
||||
|
||||
type teamWithRight struct {
|
||||
team.Team `xorm:"extends"`
|
||||
Right models.TeamRight `json:"right"`
|
||||
}
|
|
@ -1,21 +1,28 @@
|
|||
package models
|
||||
package sharing
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/errs"
|
||||
"code.vikunja.io/api/pkg/list"
|
||||
"code.vikunja.io/api/pkg/team"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
)
|
||||
|
||||
// Create creates a new team <-> list relation
|
||||
func (tl *TeamList) Create(doer *User) (err error) {
|
||||
func (tl *TeamList) Create(doer *user.User) (err error) {
|
||||
|
||||
// Check if the rights are valid
|
||||
if err = tl.Right.isValid(); err != nil {
|
||||
if err = tl.Right.IsValid(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Check if the team exists
|
||||
_, err = GetTeamByID(tl.TeamID)
|
||||
_, err = team.GetTeamByID(tl.TeamID)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Check if the list exists
|
||||
l := &List{ID: tl.ListID}
|
||||
l := &list.List{ID: tl.ListID}
|
||||
if err := l.GetSimpleByID(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -28,7 +35,7 @@ func (tl *TeamList) Create(doer *User) (err error) {
|
|||
return
|
||||
}
|
||||
if exists {
|
||||
return ErrTeamAlreadyHasAccess{tl.TeamID, tl.ListID}
|
||||
return errs.ErrTeamAlreadyHasAccess{tl.TeamID, tl.ListID}
|
||||
}
|
||||
|
||||
// Insert the new team
|
|
@ -1,10 +1,15 @@
|
|||
package models
|
||||
package sharing
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/errs"
|
||||
"code.vikunja.io/api/pkg/team"
|
||||
)
|
||||
|
||||
// Delete deletes a team <-> list relation based on the list & team id
|
||||
func (tl *TeamList) Delete() (err error) {
|
||||
|
||||
// Check if the team exists
|
||||
_, err = GetTeamByID(tl.TeamID)
|
||||
_, err = team.GetTeamByID(tl.TeamID)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -16,7 +21,7 @@ func (tl *TeamList) Delete() (err error) {
|
|||
return
|
||||
}
|
||||
if !has {
|
||||
return ErrTeamDoesNotHaveAccessToList{TeamID: tl.TeamID, ListID: tl.ListID}
|
||||
return errs.ErrTeamDoesNotHaveAccessToList{TeamID: tl.TeamID, ListID: tl.ListID}
|
||||
}
|
||||
|
||||
// Delete the relation
|
|
@ -1,14 +1,20 @@
|
|||
package models
|
||||
package sharing
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/errs"
|
||||
"code.vikunja.io/api/pkg/list"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
)
|
||||
|
||||
// ReadAll implements the method to read all teams of a list
|
||||
func (tl *TeamList) ReadAll(user *User) (interface{}, error) {
|
||||
func (tl *TeamList) ReadAll(u *user.User) (interface{}, error) {
|
||||
// Check if the user can read the namespace
|
||||
l := &List{ID: tl.ListID}
|
||||
l := &list.List{ID: tl.ListID}
|
||||
if err := l.GetSimpleByID(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !l.CanRead(user) {
|
||||
return nil, ErrNeedToHaveListReadAccess{ListID: tl.ListID, UserID: user.ID}
|
||||
if !l.CanRead(u) {
|
||||
return nil, errs.ErrNeedToHaveListReadAccess{ListID: tl.ListID, UserID: u.ID}
|
||||
}
|
||||
|
||||
// Get the teams
|
37
pkg/sharing/team_list_rights.go
Normal file
37
pkg/sharing/team_list_rights.go
Normal file
|
@ -0,0 +1,37 @@
|
|||
package sharing
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/list"
|
||||
"code.vikunja.io/api/pkg/log"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
)
|
||||
|
||||
// CanCreate checks if the user can create a team <-> list relation
|
||||
func (tl *TeamList) CanCreate(u *user.User) bool {
|
||||
l := list.List{ID: tl.ListID}
|
||||
if err := l.GetSimpleByID(); err != nil {
|
||||
log.Log.Error("Error occurred during CanCreate for TeamList: %s", err)
|
||||
return false
|
||||
}
|
||||
return l.IsAdmin(u)
|
||||
}
|
||||
|
||||
// CanDelete checks if the user can delete a team <-> list relation
|
||||
func (tl *TeamList) CanDelete(user *user.User) bool {
|
||||
l := list.List{ID: tl.ListID}
|
||||
if err := l.GetSimpleByID(); err != nil {
|
||||
log.Log.Error("Error occurred during CanDelete for TeamList: %s", err)
|
||||
return false
|
||||
}
|
||||
return l.IsAdmin(user)
|
||||
}
|
||||
|
||||
// CanUpdate checks if the user can update a team <-> list relation
|
||||
func (tl *TeamList) CanUpdate(user *user.User) bool {
|
||||
l := list.List{ID: tl.ListID}
|
||||
if err := l.GetSimpleByID(); err != nil {
|
||||
log.Log.Error("Error occurred during CanUpdate for TeamList: %s", err)
|
||||
return false
|
||||
}
|
||||
return l.IsAdmin(user)
|
||||
}
|
|
@ -1,6 +1,9 @@
|
|||
package models
|
||||
package sharing
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/errs"
|
||||
"code.vikunja.io/api/pkg/models"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
@ -11,82 +14,82 @@ func TestTeamList(t *testing.T) {
|
|||
tl := TeamList{
|
||||
TeamID: 1,
|
||||
ListID: 1,
|
||||
Right: TeamRightAdmin,
|
||||
Right: models.TeamRightAdmin,
|
||||
}
|
||||
|
||||
// Dummyuser
|
||||
user, err := GetUserByID(1)
|
||||
u, err := user.GetUserByID(1)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Check normal creation
|
||||
assert.True(t, tl.CanCreate(&user))
|
||||
err = tl.Create(&user)
|
||||
assert.True(t, tl.CanCreate(&u))
|
||||
err = tl.Create(&u)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Check again
|
||||
err = tl.Create(&user)
|
||||
err = tl.Create(&u)
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrTeamAlreadyHasAccess(err))
|
||||
assert.True(t, errs.IsErrTeamAlreadyHasAccess(err))
|
||||
|
||||
// Check with wrong rights
|
||||
tl2 := tl
|
||||
tl2.Right = TeamRightUnknown
|
||||
err = tl2.Create(&user)
|
||||
tl2.Right = models.TeamRightUnknown
|
||||
err = tl2.Create(&u)
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrInvalidTeamRight(err))
|
||||
assert.True(t, errs.IsErrInvalidTeamRight(err))
|
||||
|
||||
// Check with inexistant team
|
||||
tl3 := tl
|
||||
tl3.TeamID = 3253
|
||||
err = tl3.Create(&user)
|
||||
err = tl3.Create(&u)
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrTeamDoesNotExist(err))
|
||||
assert.True(t, errs.IsErrTeamDoesNotExist(err))
|
||||
|
||||
// Check with inexistant list
|
||||
tl4 := tl
|
||||
tl4.ListID = 3252
|
||||
err = tl4.Create(&user)
|
||||
err = tl4.Create(&u)
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrListDoesNotExist(err))
|
||||
assert.True(t, errs.IsErrListDoesNotExist(err))
|
||||
|
||||
// Test Read all
|
||||
teams, err := tl.ReadAll(&user)
|
||||
teams, err := tl.ReadAll(&u)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, reflect.TypeOf(teams).Kind(), reflect.Slice)
|
||||
s := reflect.ValueOf(teams)
|
||||
assert.Equal(t, s.Len(), 1)
|
||||
|
||||
// Test Read all for nonexistant list
|
||||
_, err = tl4.ReadAll(&user)
|
||||
_, err = tl4.ReadAll(&u)
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrListDoesNotExist(err))
|
||||
assert.True(t, errs.IsErrListDoesNotExist(err))
|
||||
|
||||
// Test Read all for a list where the user is owner of the namespace this list belongs to
|
||||
tl5 := tl
|
||||
tl5.ListID = 2
|
||||
_, err = tl5.ReadAll(&user)
|
||||
_, err = tl5.ReadAll(&u)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Test read all for a list where the user not has access
|
||||
tl6 := tl
|
||||
tl6.ListID = 3
|
||||
_, err = tl6.ReadAll(&user)
|
||||
_, err = tl6.ReadAll(&u)
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrNeedToHaveListReadAccess(err))
|
||||
assert.True(t, errs.IsErrNeedToHaveListReadAccess(err))
|
||||
|
||||
// Delete
|
||||
assert.True(t, tl.CanDelete(&user))
|
||||
assert.True(t, tl.CanDelete(&u))
|
||||
err = tl.Delete()
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Delete a nonexistant team
|
||||
err = tl3.Delete()
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrTeamDoesNotExist(err))
|
||||
assert.True(t, errs.IsErrTeamDoesNotExist(err))
|
||||
|
||||
// Delete with a nonexistant list
|
||||
err = tl4.Delete()
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrTeamDoesNotHaveAccessToList(err))
|
||||
assert.True(t, errs.IsErrTeamDoesNotHaveAccessToList(err))
|
||||
|
||||
}
|
|
@ -1,10 +1,10 @@
|
|||
package models
|
||||
package sharing
|
||||
|
||||
// Update updates a team <-> list relation
|
||||
func (tl *TeamList) Update() (err error) {
|
||||
|
||||
// Check if the right is valid
|
||||
if err := tl.Right.isValid(); err != nil {
|
||||
if err := tl.Right.IsValid(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
22
pkg/sharing/team_namespace.go
Normal file
22
pkg/sharing/team_namespace.go
Normal file
|
@ -0,0 +1,22 @@
|
|||
package sharing
|
||||
|
||||
import "code.vikunja.io/api/pkg/models"
|
||||
|
||||
// TeamNamespace defines the relationship between a Team and a Namespace
|
||||
type TeamNamespace struct {
|
||||
ID int64 `xorm:"int(11) autoincr not null unique pk" json:"id"`
|
||||
TeamID int64 `xorm:"int(11) not null INDEX" json:"team_id" param:"team"`
|
||||
NamespaceID int64 `xorm:"int(11) not null INDEX" json:"namespace_id" param:"namespace"`
|
||||
Right models.TeamRight `xorm:"int(11) INDEX" json:"right"`
|
||||
|
||||
Created int64 `xorm:"created" json:"created"`
|
||||
Updated int64 `xorm:"updated" json:"updated"`
|
||||
|
||||
models.CRUDable `xorm:"-" json:"-"`
|
||||
models.Rights `xorm:"-" json:"-"`
|
||||
}
|
||||
|
||||
// TableName makes beautiful table names
|
||||
func (TeamNamespace) TableName() string {
|
||||
return "team_namespaces"
|
||||
}
|
|
@ -1,21 +1,28 @@
|
|||
package models
|
||||
package sharing
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/errs"
|
||||
"code.vikunja.io/api/pkg/namespace"
|
||||
"code.vikunja.io/api/pkg/team"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
)
|
||||
|
||||
// Create creates a new team <-> namespace relation
|
||||
func (tn *TeamNamespace) Create(doer *User) (err error) {
|
||||
func (tn *TeamNamespace) Create(doer *user.User) (err error) {
|
||||
|
||||
// Check if the rights are valid
|
||||
if err = tn.Right.isValid(); err != nil {
|
||||
if err = tn.Right.IsValid(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Check if the team exists
|
||||
_, err = GetTeamByID(tn.TeamID)
|
||||
_, err = team.GetTeamByID(tn.TeamID)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Check if the namespace exists
|
||||
_, err = GetNamespaceByID(tn.NamespaceID)
|
||||
_, err = namespace.GetNamespaceByID(tn.NamespaceID)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -28,7 +35,7 @@ func (tn *TeamNamespace) Create(doer *User) (err error) {
|
|||
return
|
||||
}
|
||||
if exists {
|
||||
return ErrTeamAlreadyHasAccess{tn.TeamID, tn.NamespaceID}
|
||||
return errs.ErrTeamAlreadyHasAccess{tn.TeamID, tn.NamespaceID}
|
||||
}
|
||||
|
||||
// Insert the new team
|
|
@ -1,10 +1,15 @@
|
|||
package models
|
||||
package sharing
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/errs"
|
||||
"code.vikunja.io/api/pkg/team"
|
||||
)
|
||||
|
||||
// Delete deletes a team <-> namespace relation based on the namespace & team id
|
||||
func (tn *TeamNamespace) Delete() (err error) {
|
||||
|
||||
// Check if the team exists
|
||||
_, err = GetTeamByID(tn.TeamID)
|
||||
_, err = team.GetTeamByID(tn.TeamID)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -16,7 +21,7 @@ func (tn *TeamNamespace) Delete() (err error) {
|
|||
return
|
||||
}
|
||||
if !has {
|
||||
return ErrTeamDoesNotHaveAccessToNamespace{TeamID: tn.TeamID, NamespaceID: tn.NamespaceID}
|
||||
return errs.ErrTeamDoesNotHaveAccessToNamespace{TeamID: tn.TeamID, NamespaceID: tn.NamespaceID}
|
||||
}
|
||||
|
||||
// Delete the relation
|
|
@ -1,14 +1,20 @@
|
|||
package models
|
||||
package sharing
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/errs"
|
||||
"code.vikunja.io/api/pkg/namespace"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
)
|
||||
|
||||
// ReadAll implements the method to read all teams of a namespace
|
||||
func (tn *TeamNamespace) ReadAll(user *User) (interface{}, error) {
|
||||
func (tn *TeamNamespace) ReadAll(user *user.User) (interface{}, error) {
|
||||
// Check if the user can read the namespace
|
||||
n, err := GetNamespaceByID(tn.NamespaceID)
|
||||
n, err := namespace.GetNamespaceByID(tn.NamespaceID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !n.CanRead(user) {
|
||||
return nil, ErrNeedToHaveNamespaceReadAccess{NamespaceID: tn.NamespaceID, UserID: user.ID}
|
||||
return nil, errs.ErrNeedToHaveNamespaceReadAccess{NamespaceID: tn.NamespaceID, UserID: user.ID}
|
||||
}
|
||||
|
||||
// Get the teams
|
37
pkg/sharing/team_namespace_rights.go
Normal file
37
pkg/sharing/team_namespace_rights.go
Normal file
|
@ -0,0 +1,37 @@
|
|||
package sharing
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/log"
|
||||
"code.vikunja.io/api/pkg/namespace"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
)
|
||||
|
||||
// CanCreate checks if one can create a new team <-> namespace relation
|
||||
func (tn *TeamNamespace) CanCreate(user *user.User) bool {
|
||||
n, err := namespace.GetNamespaceByID(tn.NamespaceID)
|
||||
if err != nil {
|
||||
log.Log.Error("Error occurred during CanCreate for TeamNamespace: %s", err)
|
||||
return false
|
||||
}
|
||||
return n.IsAdmin(user)
|
||||
}
|
||||
|
||||
// CanDelete checks if a user can remove a team from a namespace. Only namespace admins can do that.
|
||||
func (tn *TeamNamespace) CanDelete(user *user.User) bool {
|
||||
n, err := namespace.GetNamespaceByID(tn.NamespaceID)
|
||||
if err != nil {
|
||||
log.Log.Error("Error occurred during CanDelete for TeamNamespace: %s", err)
|
||||
return false
|
||||
}
|
||||
return n.IsAdmin(user)
|
||||
}
|
||||
|
||||
// CanUpdate checks if a user can update a team from a namespace. Only namespace admins can do that.
|
||||
func (tn *TeamNamespace) CanUpdate(user *user.User) bool {
|
||||
n, err := namespace.GetNamespaceByID(tn.NamespaceID)
|
||||
if err != nil {
|
||||
log.Log.Error("Error occurred during CanUpdate for TeamNamespace: %s", err)
|
||||
return false
|
||||
}
|
||||
return n.IsAdmin(user)
|
||||
}
|
|
@ -1,6 +1,9 @@
|
|||
package models
|
||||
package sharing
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/errs"
|
||||
"code.vikunja.io/api/pkg/models"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
@ -11,10 +14,10 @@ func TestTeamNamespace(t *testing.T) {
|
|||
tn := TeamNamespace{
|
||||
TeamID: 1,
|
||||
NamespaceID: 1,
|
||||
Right: TeamRightAdmin,
|
||||
Right: models.TeamRightAdmin,
|
||||
}
|
||||
|
||||
dummyuser, err := GetUserByID(1)
|
||||
dummyuser, err := user.GetUserByID(1)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Test normal creation
|
||||
|
@ -25,28 +28,28 @@ func TestTeamNamespace(t *testing.T) {
|
|||
// Test again (should fail)
|
||||
err = tn.Create(&dummyuser)
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrTeamAlreadyHasAccess(err))
|
||||
assert.True(t, errs.IsErrTeamAlreadyHasAccess(err))
|
||||
|
||||
// Test with invalid team right
|
||||
tn2 := tn
|
||||
tn2.Right = TeamRightUnknown
|
||||
tn2.Right = models.TeamRightUnknown
|
||||
err = tn2.Create(&dummyuser)
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrInvalidTeamRight(err))
|
||||
assert.True(t, errs.IsErrInvalidTeamRight(err))
|
||||
|
||||
// Check with inexistant team
|
||||
tn3 := tn
|
||||
tn3.TeamID = 324
|
||||
err = tn3.Create(&dummyuser)
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrTeamDoesNotExist(err))
|
||||
assert.True(t, errs.IsErrTeamDoesNotExist(err))
|
||||
|
||||
// Check with a namespace which does not exist
|
||||
tn4 := tn
|
||||
tn4.NamespaceID = 423
|
||||
err = tn4.Create(&dummyuser)
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrNamespaceDoesNotExist(err))
|
||||
assert.True(t, errs.IsErrNamespaceDoesNotExist(err))
|
||||
|
||||
// Check readall
|
||||
teams, err := tn.ReadAll(&dummyuser)
|
||||
|
@ -58,13 +61,13 @@ func TestTeamNamespace(t *testing.T) {
|
|||
// Check readall for a nonexistant namespace
|
||||
_, err = tn4.ReadAll(&dummyuser)
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrNamespaceDoesNotExist(err))
|
||||
assert.True(t, errs.IsErrNamespaceDoesNotExist(err))
|
||||
|
||||
// Check with no right to read the namespace
|
||||
nouser := &User{ID: 393}
|
||||
nouser := &user.User{ID: 393}
|
||||
_, err = tn.ReadAll(nouser)
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrNeedToHaveNamespaceReadAccess(err))
|
||||
assert.True(t, errs.IsErrNeedToHaveNamespaceReadAccess(err))
|
||||
|
||||
// Delete it
|
||||
assert.True(t, tn.CanDelete(&dummyuser))
|
||||
|
@ -74,11 +77,11 @@ func TestTeamNamespace(t *testing.T) {
|
|||
// Try deleting with a nonexisting team
|
||||
err = tn3.Delete()
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrTeamDoesNotExist(err))
|
||||
assert.True(t, errs.IsErrTeamDoesNotExist(err))
|
||||
|
||||
// Try deleting with a nonexistant namespace
|
||||
err = tn4.Delete()
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrTeamDoesNotHaveAccessToNamespace(err))
|
||||
assert.True(t, errs.IsErrTeamDoesNotHaveAccessToNamespace(err))
|
||||
|
||||
}
|
|
@ -1,10 +1,10 @@
|
|||
package models
|
||||
package sharing
|
||||
|
||||
// Update updates a team <-> namespace relation
|
||||
func (tl *TeamNamespace) Update() (err error) {
|
||||
|
||||
// Check if the right is valid
|
||||
if err := tl.Right.isValid(); err != nil {
|
||||
if err := tl.Right.IsValid(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user