From 32fde286dbccda50227efd014941c47ebac615b7 Mon Sep 17 00:00:00 2001 From: konrad Date: Thu, 12 Jul 2018 21:07:59 +0200 Subject: [PATCH] Optimized right checking + list.ReadAll now really gets all lists --- models/{lists.go => list.go} | 64 ++++++--------------------- models/list_rights.go | 81 +++++++++++++++++++++++++++++++++++ models/models.go | 4 +- models/namespaces.go | 76 --------------------------------- models/namespaces_rights.go | 83 ++++++++++++++++++++++++++++++++++++ 5 files changed, 179 insertions(+), 129 deletions(-) rename models/{lists.go => list.go} (59%) create mode 100644 models/list_rights.go create mode 100644 models/namespaces_rights.go diff --git a/models/lists.go b/models/list.go similarity index 59% rename from models/lists.go rename to models/list.go index 19ca6dda5b..b01dfa7486 100644 --- a/models/lists.go +++ b/models/list.go @@ -59,12 +59,19 @@ func (l *List) ReadAll(user *User) (interface{}, error) { return lists, err } - // TODO: namespaces... - err = x.Select("list.*"). - Join("LEFT", "team_list", "list.id = team_list.list_id"). - Join("LEFT", "team_members", "team_members.team_id = team_list.team_id"). - Where("team_members.user_id = ?", fullUser.ID). - Or("list.owner_id = ?", fullUser.ID). + // Gets all Lists where the user is either owner or in a team which has access to the list + // Or in a team which has namespace read access + err = x.Select("l.*"). + Table("list"). + Alias("l"). + Join("INNER", []string{"namespaces", "n"}, "l.namespace_id = n.id"). + Join("LEFT", []string{"team_namespaces", "tn"}, "tn.namespace_id = n.id"). + Join("LEFT", []string{"team_members", "tm"}, "tm.team_id = tn.team_id"). + Join("LEFT", []string{"team_list", "tl"}, "l.id = tl.list_id"). + Join("LEFT", []string{"team_members", "tm2"}, "tm2.team_id = tl.team_id"). + Where("tm.user_id = ?", fullUser.ID). + Or("tm2.user_id = ?", fullUser.ID). + Or("l.owner_id = ?", fullUser.ID). Find(&lists) return lists, err @@ -75,48 +82,3 @@ func (l *List) ReadOne(id int64) (err error) { *l, err = GetListByID(id) return } - -// IsAdmin returns whether the user has admin rights on the list or not -func (l *List) IsAdmin(user *User) bool { - // Owners are always admins - if l.Owner.ID == user.ID { - return true - } - - // Check Team rights - // aka "is the user in a team which has admin rights?" - // TODO - - // Check Namespace rights - // TODO - - // Check individual rights - // TODO - - return false -} - -// CanWrite return whether the user can write on that list or not -func (l *List) CanWrite(user *User) bool { - // Admins always have write access - if l.IsAdmin(user) { - return true - } - - // Owners always have write access - if l.Owner.ID == user.ID { - return true - } - - // Check Namespace rights - // TODO - // TODO find a way to prioritize: what happens if a user has namespace write access but is not in that list? - - // Check Team rights - // TODO - - // Check individual rights - // TODO - - return false -} diff --git a/models/list_rights.go b/models/list_rights.go new file mode 100644 index 0000000000..b09960f7b9 --- /dev/null +++ b/models/list_rights.go @@ -0,0 +1,81 @@ +package models + +// IsAdmin returns whether the user has admin rights on the list or not +func (l *List) IsAdmin(user *User) bool { + // Owners are always admins + if l.Owner.ID == user.ID { + return true + } + + // Check Team rights + // aka "is the user in a team which has admin rights?" + // TODO + + // Check Namespace rights + // TODO + + // Check individual rights + // TODO + + return false +} + +// CanWrite return whether the user can write on that list or not +func (l *List) CanWrite(user *User) bool { + // Owners always have write access + if l.Owner.ID == user.ID { + return true + } + + // Admins always have write access + if l.IsAdmin(user) { + return true + } + + // Check Namespace rights + // TODO + // TODO find a way to prioritize: what happens if a user has namespace write access but is not in that list? + + // Check Team rights + // TODO + + // Check individual rights + // TODO + + return false +} + +// CanRead checks if a user has read access to a list +func (l *List) CanRead(user *User) bool { + // Owners always have read access + if l.Owner.ID == user.ID { + return true + } + + // Admins always have read access + if l.IsAdmin(user) { + return true + } + + // Check Namespace rights + exists, _ := x.Select("list.*"). + Table("namespaces"). + Join("INNER", "list", "list.namespace_id = namespaces.id"). + Join("INNER", "team_namespaces", "team_namespaces.namespace_id = namespaces.id"). + Join("INNER", "team_members", "team_members.team_id = team_namespaces.team_id"). + Where("team_members.user_id = ?", user.ID). + And("list.id = ?", l.ID). + Get(&List{}) + + if exists { + return true + } + + // Check Team rights + // TODO + + // Check individual rights + // TODO + + return false +} diff --git a/models/models.go b/models/models.go index 6fc958a521..a01bd5f2d7 100644 --- a/models/models.go +++ b/models/models.go @@ -51,8 +51,8 @@ func SetEngine() (err error) { } // Cache - cacher := xorm.NewLRUCacher(xorm.NewMemoryStore(), 1000) - x.SetDefaultCacher(cacher) + //cacher := xorm.NewLRUCacher(xorm.NewMemoryStore(), 1000) + //x.SetDefaultCacher(cacher) x.SetMapper(core.GonicMapper{}) diff --git a/models/namespaces.go b/models/namespaces.go index 03db3a0695..60b3edfa26 100644 --- a/models/namespaces.go +++ b/models/namespaces.go @@ -26,60 +26,6 @@ func (n *Namespace) AfterLoad() { n.Owner, _, _ = GetUserByID(n.OwnerID) } -// NamespaceRight defines the rights teams can have for namespaces -type NamespaceRight int - -// define unknown namespace right -const ( - NamespaceRightUnknown = -1 -) - -// Enumerate all the namespace rights -const ( - // Can read lists in a namespace - NamespaceRightRead NamespaceRight = iota - // Cat write items in a namespace like lists and todo items - NamespaceRightWrite - // Can manage a namespace, can do everything - NamespaceRightAdmin -) - -// IsNamespaceAdmin returns whether the usre has admin rights in a namespace -func (user *User) IsNamespaceAdmin(namespace *Namespace) (err error) { - // Owners always have admin rights - if user.ID == namespace.Owner.ID { - return nil - } - - // Check if that user is in a team which has admin rights to that namespace - - return ErrUserNeedsToBeNamespaceAdmin{UserID: user.ID, NamespaceID: namespace.ID} -} - -// IsAdmin returns true or false if the user is admin on that namespace or not -func (n *Namespace) IsAdmin(user *User) bool { - - // Owners always have admin rights - if user.ID == n.Owner.ID { - return true - } - - // Check if that user is in a team which has admin rights to that namespace - // TODO - - return false -} - -// CanWrite checks if a user has write access to a namespace -func (n *Namespace) CanWrite(user *User) bool { - // Owners always have access - if user.ID == n.Owner.ID { - return true - } - - return true -} - // GetNamespaceByID returns a namespace object by its ID func GetNamespaceByID(id int64) (namespace Namespace, err error) { namespace.ID = id @@ -165,25 +111,3 @@ func (n *Namespace) ReadAll(doer *User) (interface{}, error) { return all, nil } - -func (n *Namespace) CanRead(user *User) bool { - // Owners always have access - if user.ID == n.Owner.ID { - return true - } - - // Check if the user is in a team which has access to the namespace - all := Namespace{} - // TODO respect individual rights - exists, _ := x.Select("namespaces.*"). - Table("namespaces"). - Join("LEFT", "team_namespaces", "namespaces.id = team_namespaces.namespace_id"). - Join("LEFT", "team_members", "team_members.team_id = team_namespaces.team_id"). - Where("team_members.user_id = ?", user.ID). - Or("namespaces.owner_id = ?", user.ID). - And("namespaces.id = ?", n.ID). - GroupBy("namespaces.id"). - Get(&all) - - return exists -} diff --git a/models/namespaces_rights.go b/models/namespaces_rights.go new file mode 100644 index 0000000000..a9ac14ed9f --- /dev/null +++ b/models/namespaces_rights.go @@ -0,0 +1,83 @@ +package models + +// NamespaceRight defines the rights teams can have for namespaces +type NamespaceRight int + +// define unknown namespace right +const ( + NamespaceRightUnknown = -1 +) + +// Enumerate all the namespace rights +const ( + // Can read lists in a namespace + NamespaceRightRead NamespaceRight = iota + // Cat write items in a namespace like lists and todo items + NamespaceRightWrite + // Can manage a namespace, can do everything + NamespaceRightAdmin +) + +// IsNamespaceAdmin returns whether the usre has admin rights in a namespace +func (user *User) IsNamespaceAdmin(namespace *Namespace) (err error) { + // Owners always have admin rights + if user.ID == namespace.Owner.ID { + return nil + } + + // Check if that user is in a team which has admin rights to that namespace + + return ErrUserNeedsToBeNamespaceAdmin{UserID: user.ID, NamespaceID: namespace.ID} +} + +// IsAdmin returns true or false if the user is admin on that namespace or not +func (n *Namespace) IsAdmin(user *User) bool { + + // Owners always have admin rights + if user.ID == n.Owner.ID { + return true + } + + // Check if that user is in a team which has admin rights to that namespace + // TODO + + return false +} + +// CanWrite checks if a user has write access to a namespace +func (n *Namespace) CanWrite(user *User) bool { + // Owners always have access + if user.ID == n.Owner.ID { + return true + } + + return true +} + +// CanRead checks if a user has read access to that namespace +func (n *Namespace) CanRead(user *User) bool { + // Owners always have access + if user.ID == n.Owner.ID { + return true + } + + // Admins always have read access + if n.IsAdmin(user) { + return true + } + + // Check if the user is in a team which has access to the namespace + all := Namespace{} + // TODO respect individual rights + exists, _ := x.Select("namespaces.*"). + Table("namespaces"). + Join("LEFT", "team_namespaces", "namespaces.id = team_namespaces.namespace_id"). + Join("LEFT", "team_members", "team_members.team_id = team_namespaces.team_id"). + Where("team_members.user_id = ?", user.ID). + Or("namespaces.owner_id = ?", user.ID). + And("namespaces.id = ?", n.ID). + GroupBy("namespaces.id"). + Get(&all) + + return exists +}