diff --git a/main.go b/main.go index 6e86020915..f01d677a04 100644 --- a/main.go +++ b/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,19 +20,19 @@ 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()) + log.Log.Error(err.Error()) os.Exit(1) } // Set Engine err = models.SetEngine() if err != nil { - models.Log.Error(err.Error()) + log.Log.Error(err.Error()) os.Exit(1) } @@ -38,7 +40,7 @@ func main() { mail.StartMailDaemon() // Version notification - models.Log.Infof("Vikunja version %s", Version) + log.Log.Infof("Vikunja version %s", Version) // Start the webserver e := routes.NewEcho() @@ -57,7 +59,7 @@ func main() { <-quit ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() - models.Log.Infof("Sutting down...") + log.Log.Infof("Shutting down...") if err := e.Shutdown(ctx); err != nil { e.Logger.Fatal(err) } diff --git a/models/teams_rights.go b/models/teams_rights.go deleted file mode 100644 index 5a1fbe405e..0000000000 --- a/models/teams_rights.go +++ /dev/null @@ -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 -} diff --git a/models/config.go b/pkg/config/config.go similarity index 99% rename from models/config.go rename to pkg/config/config.go index a097df832a..bd3162b7bf 100644 --- a/models/config.go +++ b/pkg/config/config.go @@ -1,4 +1,4 @@ -package models +package config import ( "crypto/rand" diff --git a/models/logging.go b/pkg/log/logging.go similarity index 97% rename from models/logging.go rename to pkg/log/logging.go index 6fbbf5b6f2..cc15e66218 100644 --- a/models/logging.go +++ b/pkg/log/logging.go @@ -1,4 +1,4 @@ -package models +package log import ( "github.com/op/go-logging" diff --git a/models/mail/mail.go b/pkg/mail/mail.go similarity index 68% rename from models/mail/mail.go rename to pkg/mail/mail.go index c674948f0a..a8d99a1d0f 100644 --- a/models/mail/mail.go +++ b/pkg/mail/mail.go @@ -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 } } diff --git a/models/mail/send_mail.go b/pkg/mail/send_mail.go similarity index 98% rename from models/mail/send_mail.go rename to pkg/mail/send_mail.go index 2138a780b0..4c467d12dd 100644 --- a/models/mail/send_mail.go +++ b/pkg/mail/send_mail.go @@ -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" diff --git a/models/crudable.go b/pkg/models/crudable.go similarity index 100% rename from models/crudable.go rename to pkg/models/crudable.go diff --git a/models/error.go b/pkg/models/error.go similarity index 100% rename from models/error.go rename to pkg/models/error.go diff --git a/models/fixtures/list.yml b/pkg/models/fixtures/list.yml similarity index 100% rename from models/fixtures/list.yml rename to pkg/models/fixtures/list.yml diff --git a/models/fixtures/namespaces.yml b/pkg/models/fixtures/namespaces.yml similarity index 100% rename from models/fixtures/namespaces.yml rename to pkg/models/fixtures/namespaces.yml diff --git a/models/fixtures/team_members.yml b/pkg/models/fixtures/team_members.yml similarity index 100% rename from models/fixtures/team_members.yml rename to pkg/models/fixtures/team_members.yml diff --git a/models/fixtures/teams.yml b/pkg/models/fixtures/teams.yml similarity index 100% rename from models/fixtures/teams.yml rename to pkg/models/fixtures/teams.yml diff --git a/models/fixtures/users.yml b/pkg/models/fixtures/users.yml similarity index 100% rename from models/fixtures/users.yml rename to pkg/models/fixtures/users.yml diff --git a/models/list.go b/pkg/models/list.go similarity index 91% rename from models/list.go rename to pkg/models/list.go index caf6700884..d353e34d24 100644 --- a/models/list.go +++ b/pkg/models/list.go @@ -25,9 +25,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) (interface{}, error) { lists := []*List{} - fullUser, err := GetUserByID(user.ID) + fullUser, err := GetUserByID(u.ID) if err != nil { return lists, err } @@ -53,7 +53,7 @@ func (l *List) ReadAll(user *User) (interface{}, error) { Find(&lists) // Add more list details - addListDetails(lists) + AddListDetails(lists) return lists, err } @@ -98,8 +98,8 @@ func (l *List) GetSimpleByID() (err error) { return } -// Adds owner user objects and list tasks to all lists in the slice -func addListDetails(lists []*List) (err error) { +// AddListDetails adds owner user objects and list tasks to all lists in the slice +func AddListDetails(lists []*List) (err error) { var listIDs []int64 var ownerIDs []int64 for _, l := range lists { @@ -108,8 +108,8 @@ 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 } @@ -132,7 +132,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) } diff --git a/models/list_create_test.go b/pkg/models/list_create_test.go similarity index 100% rename from models/list_create_test.go rename to pkg/models/list_create_test.go diff --git a/models/list_create_update.go b/pkg/models/list_create_update.go similarity index 92% rename from models/list_create_update.go rename to pkg/models/list_create_update.go index 5e04573b15..56c0bbdf89 100644 --- a/models/list_create_update.go +++ b/pkg/models/list_create_update.go @@ -44,13 +44,13 @@ func (l *List) Update() (err error) { // Create implements the create method of CRUDable func (l *List) Create(doer *User) (err error) { // Check rights - user, err := GetUserByID(doer.ID) + u, err := 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) diff --git a/models/list_delete.go b/pkg/models/list_delete.go similarity index 100% rename from models/list_delete.go rename to pkg/models/list_delete.go diff --git a/models/lists_get_test.go b/pkg/models/list_read_test.go similarity index 91% rename from models/lists_get_test.go rename to pkg/models/list_read_test.go index 9593f41b72..8d01efe5cb 100644 --- a/models/lists_get_test.go +++ b/pkg/models/list_read_test.go @@ -16,11 +16,11 @@ 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 := 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) diff --git a/models/list_rights.go b/pkg/models/list_rights.go similarity index 84% rename from models/list_rights.go rename to pkg/models/list_rights.go index ba13308cbb..0dc3b4be4b 100644 --- a/models/list_rights.go +++ b/pkg/models/list_rights.go @@ -1,18 +1,22 @@ package models +import ( + "code.vikunja.io/api/pkg/log" +) + // 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) 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, UserRightAdmin) { return true } - return l.checkListTeamRight(user, TeamRightAdmin) + return l.checkListTeamRight(u, TeamRightAdmin) } // CanWrite return whether the user can write on that list or not @@ -48,7 +52,7 @@ func (l *List) CanRead(user *User) bool { // CanDelete checks if the user can delete a list func (l *List) CanDelete(doer *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) @@ -57,7 +61,7 @@ func (l *List) CanDelete(doer *User) bool { // CanUpdate checks if the user can update a list func (l *List) CanUpdate(doer *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) @@ -82,7 +86,7 @@ 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 } @@ -103,7 +107,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 } diff --git a/models/list_items.go b/pkg/models/list_tasks.go similarity index 92% rename from models/list_items.go rename to pkg/models/list_tasks.go index 0ff856d343..12e5fd7db9 100644 --- a/models/list_items.go +++ b/pkg/models/list_tasks.go @@ -59,9 +59,9 @@ func GetTasksByListID(listID int64) (tasks []*ListTask, err error) { } 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 } } @@ -88,11 +88,11 @@ func GetListTaskByID(listTaskID int64) (listTask ListTask, err error) { return ListTask{}, ErrListTaskDoesNotExist{listTaskID} } - user, err := GetUserByID(listTask.CreatedByID) + u, err := GetUserByID(listTask.CreatedByID) if err != nil { return } - listTask.CreatedBy = user + listTask.CreatedBy = u return } diff --git a/models/list_items_create_update.go b/pkg/models/list_tasks_create_update.go similarity index 88% rename from models/list_items_create_update.go rename to pkg/models/list_tasks_create_update.go index 03494da21b..e06e635702 100644 --- a/models/list_items_create_update.go +++ b/pkg/models/list_tasks_create_update.go @@ -19,13 +19,13 @@ func (i *ListTask) Create(doer *User) (err error) { return } - user, err := GetUserByID(doer.ID) + u, err := 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 } @@ -39,8 +39,8 @@ func (i *ListTask) Update() (err error) { } // For whatever reason, xorm dont detect if done is updated, so we need to update this every time by hand - // Which is why we merge the actual task struct with the one we got from the user. - // The user struct ovverrides values in the actual one. + // Which is why we merge the actual task struct with the one we got from the + // The user struct overrides values in the actual one. if err := mergo.Merge(&ot, i, mergo.WithOverride); err != nil { return err } diff --git a/models/list_items_delete.go b/pkg/models/list_tasks_delete.go similarity index 100% rename from models/list_items_delete.go rename to pkg/models/list_tasks_delete.go diff --git a/models/list_items_rights.go b/pkg/models/list_tasks_rights.go similarity index 65% rename from models/list_items_rights.go rename to pkg/models/list_tasks_rights.go index 5380745f70..93cb027c0f 100644 --- a/models/list_items_rights.go +++ b/pkg/models/list_tasks_rights.go @@ -1,18 +1,22 @@ package models +import ( + "code.vikunja.io/api/pkg/log" +) + // 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) + 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 - list := &List{ID: lI.ListID} - list.ReadOne() - return list.CanWrite(doer) + l := &List{ID: lI.ListID} + l.ReadOne() + return l.CanWrite(doer) } // CanUpdate determines if a user has the right to update a list task @@ -20,20 +24,20 @@ 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) + 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 - list := &List{ID: lI.ListID} - list.ReadOne() - return list.CanWrite(doer) + 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) 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) + l := &List{ID: i.ListID} + l.ReadOne() + return l.CanWrite(doer) } diff --git a/models/list_items_test.go b/pkg/models/list_tasks_test.go similarity index 100% rename from models/list_items_test.go rename to pkg/models/list_tasks_test.go diff --git a/models/list_users.go b/pkg/models/list_users.go similarity index 100% rename from models/list_users.go rename to pkg/models/list_users.go diff --git a/models/list_users_create.go b/pkg/models/list_users_create.go similarity index 94% rename from models/list_users_create.go rename to pkg/models/list_users_create.go index d95a9773fb..df1d4c4756 100644 --- a/models/list_users_create.go +++ b/pkg/models/list_users_create.go @@ -1,7 +1,7 @@ package models // Create creates a new list <-> user relation -func (ul *ListUser) Create(user *User) (err error) { +func (ul *ListUser) Create(u *User) (err error) { // Check if the right is valid if err := ul.Right.isValid(); err != nil { diff --git a/models/list_users_delete.go b/pkg/models/list_users_delete.go similarity index 100% rename from models/list_users_delete.go rename to pkg/models/list_users_delete.go diff --git a/models/list_users_readall.go b/pkg/models/list_users_readall.go similarity index 83% rename from models/list_users_readall.go rename to pkg/models/list_users_readall.go index e316d21365..fe1a978e73 100644 --- a/models/list_users_readall.go +++ b/pkg/models/list_users_readall.go @@ -1,13 +1,13 @@ package models // ReadAll gets all users who have access to a list -func (ul *ListUser) ReadAll(user *User) (interface{}, error) { +func (ul *ListUser) ReadAll(u *User) (interface{}, error) { // Check if the user has access to the list l := &List{ID: ul.ListID} if err := l.GetSimpleByID(); err != nil { return nil, err } - if !l.CanRead(user) { + if !l.CanRead(u) { return nil, ErrNeedToHaveListReadAccess{} } diff --git a/models/list_users_rights.go b/pkg/models/list_users_rights.go similarity index 53% rename from models/list_users_rights.go rename to pkg/models/list_users_rights.go index f882740fed..a996660f26 100644 --- a/models/list_users_rights.go +++ b/pkg/models/list_users_rights.go @@ -1,37 +1,15 @@ package models -// UserRight defines the rights users can have for lists/namespaces -type UserRight int - -// define unknown user right -const ( - UserRightUnknown = -1 +import ( + "code.vikunja.io/api/pkg/log" ) -// 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) + log.Log.Error("Error occurred during CanCreate for ListUser: %s", err) return false } return l.CanWrite(doer) @@ -42,7 +20,7 @@ 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) + log.Log.Error("Error occurred during CanDelete for ListUser: %s", err) return false } return l.CanWrite(doer) @@ -53,7 +31,7 @@ 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) + log.Log.Error("Error occurred during CanUpdate for ListUser: %s", err) return false } return l.CanWrite(doer) diff --git a/models/list_users_update.go b/pkg/models/list_users_update.go similarity index 100% rename from models/list_users_update.go rename to pkg/models/list_users_update.go diff --git a/models/main_test.go b/pkg/models/main_test.go similarity index 100% rename from models/main_test.go rename to pkg/models/main_test.go diff --git a/models/message.go b/pkg/models/message.go similarity index 100% rename from models/message.go rename to pkg/models/message.go diff --git a/models/models.go b/pkg/models/models.go similarity index 100% rename from models/models.go rename to pkg/models/models.go diff --git a/models/models_test.go b/pkg/models/models_test.go similarity index 100% rename from models/models_test.go rename to pkg/models/models_test.go diff --git a/models/namespaces.go b/pkg/models/namespace.go similarity index 99% rename from models/namespaces.go rename to pkg/models/namespace.go index b1d898f9b2..b72fd0a8a7 100644 --- a/models/namespaces.go +++ b/pkg/models/namespace.go @@ -109,7 +109,7 @@ func (n *Namespace) ReadAll(doer *User) (interface{}, error) { } // More details for the lists - addListDetails(lists) + AddListDetails(lists) // Put objects in our namespace list for i, n := range all { diff --git a/models/namespace_create.go b/pkg/models/namespace_create.go similarity index 100% rename from models/namespace_create.go rename to pkg/models/namespace_create.go diff --git a/models/namespace_delete.go b/pkg/models/namespace_delete.go similarity index 91% rename from models/namespace_delete.go rename to pkg/models/namespace_delete.go index 21d933e488..a580b5a135 100644 --- a/models/namespace_delete.go +++ b/pkg/models/namespace_delete.go @@ -21,8 +21,8 @@ func (n *Namespace) Delete() (err error) { // 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 diff --git a/models/namespace_rights.go b/pkg/models/namespace_rights.go similarity index 60% rename from models/namespace_rights.go rename to pkg/models/namespace_rights.go index 5840c38bbe..1c56e5db5b 100644 --- a/models/namespace_rights.go +++ b/pkg/models/namespace_rights.go @@ -1,106 +1,110 @@ package models +import ( + "code.vikunja.io/api/pkg/log" +) + // 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) 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, 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, 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) 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, 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, 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) 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, 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, TeamRightRead) } // CanUpdate checks if the user can update the namespace -func (n *Namespace) CanUpdate(user *User) bool { +func (n *Namespace) CanUpdate(u *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) 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) 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, r 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, r 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 } diff --git a/models/namespace_test.go b/pkg/models/namespace_test.go similarity index 100% rename from models/namespace_test.go rename to pkg/models/namespace_test.go diff --git a/models/namespace_update.go b/pkg/models/namespace_update.go similarity index 100% rename from models/namespace_update.go rename to pkg/models/namespace_update.go diff --git a/models/namespace_users.go b/pkg/models/namespace_users.go similarity index 100% rename from models/namespace_users.go rename to pkg/models/namespace_users.go diff --git a/models/namespace_users_create.go b/pkg/models/namespace_users_create.go similarity index 94% rename from models/namespace_users_create.go rename to pkg/models/namespace_users_create.go index fca5bbadad..dc2e865326 100644 --- a/models/namespace_users_create.go +++ b/pkg/models/namespace_users_create.go @@ -1,7 +1,7 @@ package models // Create creates a new namespace <-> user relation -func (un *NamespaceUser) Create(user *User) (err error) { +func (un *NamespaceUser) Create(u *User) (err error) { // Reset the id un.ID = 0 diff --git a/models/namespace_users_delete.go b/pkg/models/namespace_users_delete.go similarity index 100% rename from models/namespace_users_delete.go rename to pkg/models/namespace_users_delete.go diff --git a/models/namespace_users_readall.go b/pkg/models/namespace_users_readall.go similarity index 83% rename from models/namespace_users_readall.go rename to pkg/models/namespace_users_readall.go index 6b0664d805..d31080e028 100644 --- a/models/namespace_users_readall.go +++ b/pkg/models/namespace_users_readall.go @@ -1,13 +1,13 @@ package models // ReadAll gets all users who have access to a namespace -func (un *NamespaceUser) ReadAll(user *User) (interface{}, error) { +func (un *NamespaceUser) ReadAll(u *User) (interface{}, error) { // Check if the user has access to the namespace l, err := GetNamespaceByID(un.NamespaceID) if err != nil { return nil, err } - if !l.CanRead(user) { + if !l.CanRead(u) { return nil, ErrNeedToHaveNamespaceReadAccess{} } diff --git a/models/namespace_users_rights.go b/pkg/models/namespace_users_rights.go similarity index 76% rename from models/namespace_users_rights.go rename to pkg/models/namespace_users_rights.go index 80cd1771b6..a26dd98de9 100644 --- a/models/namespace_users_rights.go +++ b/pkg/models/namespace_users_rights.go @@ -1,11 +1,15 @@ package models +import ( + "code.vikunja.io/api/pkg/log" +) + // 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) + log.Log.Error("Error occurred during CanCreate for NamespaceUser: %s", err) return false } return n.CanWrite(doer) @@ -16,7 +20,7 @@ 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) + log.Log.Error("Error occurred during CanDelete for NamespaceUser: %s", err) return false } return n.CanWrite(doer) @@ -27,7 +31,7 @@ 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) + log.Log.Error("Error occurred during CanUpdate for NamespaceUser: %s", err) return false } return n.CanWrite(doer) diff --git a/models/namespace_users_update.go b/pkg/models/namespace_users_update.go similarity index 100% rename from models/namespace_users_update.go rename to pkg/models/namespace_users_update.go diff --git a/models/rights.go b/pkg/models/rights.go similarity index 100% rename from models/rights.go rename to pkg/models/rights.go diff --git a/models/team_list.go b/pkg/models/team_list.go similarity index 100% rename from models/team_list.go rename to pkg/models/team_list.go diff --git a/models/team_list_create.go b/pkg/models/team_list_create.go similarity index 100% rename from models/team_list_create.go rename to pkg/models/team_list_create.go diff --git a/models/team_list_delete.go b/pkg/models/team_list_delete.go similarity index 100% rename from models/team_list_delete.go rename to pkg/models/team_list_delete.go diff --git a/models/team_list_readall.go b/pkg/models/team_list_readall.go similarity index 82% rename from models/team_list_readall.go rename to pkg/models/team_list_readall.go index 849232003d..09572496db 100644 --- a/models/team_list_readall.go +++ b/pkg/models/team_list_readall.go @@ -1,14 +1,14 @@ package models // 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) (interface{}, error) { // Check if the user can read the namespace l := &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, ErrNeedToHaveListReadAccess{ListID: tl.ListID, UserID: u.ID} } // Get the teams diff --git a/models/team_list_rights.go b/pkg/models/team_list_rights.go similarity index 65% rename from models/team_list_rights.go rename to pkg/models/team_list_rights.go index faf69ecd53..2d87ced1da 100644 --- a/models/team_list_rights.go +++ b/pkg/models/team_list_rights.go @@ -1,20 +1,24 @@ package models +import ( + "code.vikunja.io/api/pkg/log" +) + // CanCreate checks if the user can create a team <-> list relation -func (tl *TeamList) CanCreate(user *User) bool { +func (tl *TeamList) CanCreate(u *User) bool { l := List{ID: tl.ListID} if err := l.GetSimpleByID(); err != nil { - Log.Error("Error occurred during CanCreate for TeamList: %s", err) + log.Log.Error("Error occurred during CanCreate for TeamList: %s", err) return false } - return l.IsAdmin(user) + return l.IsAdmin(u) } // 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) + log.Log.Error("Error occurred during CanDelete for TeamList: %s", err) return false } return l.IsAdmin(user) @@ -24,7 +28,7 @@ func (tl *TeamList) CanDelete(user *User) bool { 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) + log.Log.Error("Error occurred during CanUpdate for TeamList: %s", err) return false } return l.IsAdmin(user) diff --git a/models/team_list_test.go b/pkg/models/team_list_test.go similarity index 82% rename from models/team_list_test.go rename to pkg/models/team_list_test.go index 37effb454d..926bff325b 100644 --- a/models/team_list_test.go +++ b/pkg/models/team_list_test.go @@ -15,67 +15,67 @@ func TestTeamList(t *testing.T) { } // Dummyuser - user, err := GetUserByID(1) + u, err := 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)) // Check with wrong rights tl2 := tl tl2.Right = TeamRightUnknown - err = tl2.Create(&user) + err = tl2.Create(&u) assert.Error(t, err) assert.True(t, 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)) // 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)) // 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)) // 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)) // Delete - assert.True(t, tl.CanDelete(&user)) + assert.True(t, tl.CanDelete(&u)) err = tl.Delete() assert.NoError(t, err) diff --git a/models/team_list_update.go b/pkg/models/team_list_update.go similarity index 100% rename from models/team_list_update.go rename to pkg/models/team_list_update.go diff --git a/models/team_members_create.go b/pkg/models/team_members_create.go similarity index 100% rename from models/team_members_create.go rename to pkg/models/team_members_create.go diff --git a/models/team_members_delete.go b/pkg/models/team_members_delete.go similarity index 100% rename from models/team_members_delete.go rename to pkg/models/team_members_delete.go diff --git a/models/team_members_rights.go b/pkg/models/team_members_rights.go similarity index 53% rename from models/team_members_rights.go rename to pkg/models/team_members_rights.go index a97548bbfd..a487492ac7 100644 --- a/models/team_members_rights.go +++ b/pkg/models/team_members_rights.go @@ -1,22 +1,26 @@ package models +import ( + "code.vikunja.io/api/pkg/log" +) + // CanCreate checks if the user can add a new tem member -func (tm *TeamMember) CanCreate(user *User) bool { - return tm.IsAdmin(user) +func (tm *TeamMember) CanCreate(u *User) bool { + return tm.IsAdmin(u) } // CanDelete checks if the user can delete a new team member -func (tm *TeamMember) CanDelete(user *User) bool { - return tm.IsAdmin(user) +func (tm *TeamMember) CanDelete(u *User) bool { + return tm.IsAdmin(u) } // IsAdmin checks if the user is team admin -func (tm *TeamMember) IsAdmin(user *User) bool { +func (tm *TeamMember) IsAdmin(u *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). + exists, err := x.Where("user_id = ? AND team_id = ? AND admin = ?", u.ID, tm.TeamID, true). Get(&TeamMember{}) if err != nil { - Log.Error("Error occurred during IsAdmin for TeamMember: %s", err) + log.Log.Error("Error occurred during IsAdmin for TeamMember: %s", err) return false } return exists diff --git a/models/team_members_test.go b/pkg/models/team_members_test.go similarity index 100% rename from models/team_members_test.go rename to pkg/models/team_members_test.go diff --git a/models/team_namespace.go b/pkg/models/team_namespace.go similarity index 100% rename from models/team_namespace.go rename to pkg/models/team_namespace.go diff --git a/models/team_namespace_create.go b/pkg/models/team_namespace_create.go similarity index 100% rename from models/team_namespace_create.go rename to pkg/models/team_namespace_create.go diff --git a/models/team_namespace_delete.go b/pkg/models/team_namespace_delete.go similarity index 100% rename from models/team_namespace_delete.go rename to pkg/models/team_namespace_delete.go diff --git a/models/team_namespace_readall.go b/pkg/models/team_namespace_readall.go similarity index 100% rename from models/team_namespace_readall.go rename to pkg/models/team_namespace_readall.go diff --git a/models/team_namespace_rights.go b/pkg/models/team_namespace_rights.go similarity index 64% rename from models/team_namespace_rights.go rename to pkg/models/team_namespace_rights.go index ba1f3b053b..4707c4a984 100644 --- a/models/team_namespace_rights.go +++ b/pkg/models/team_namespace_rights.go @@ -1,10 +1,14 @@ package models +import ( + "code.vikunja.io/api/pkg/log" +) + // 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) + log.Log.Error("Error occurred during CanCreate for TeamNamespace: %s", err) return false } return n.IsAdmin(user) @@ -14,17 +18,17 @@ func (tn *TeamNamespace) CanCreate(user *User) bool { 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) + 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. +// CanUpdate checks if a user can update a team from a 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) + log.Log.Error("Error occurred during CanUpdate for TeamNamespace: %s", err) return false } return n.IsAdmin(user) diff --git a/models/team_namespace_test.go b/pkg/models/team_namespace_test.go similarity index 100% rename from models/team_namespace_test.go rename to pkg/models/team_namespace_test.go diff --git a/models/team_namespace_update.go b/pkg/models/team_namespace_update.go similarity index 100% rename from models/team_namespace_update.go rename to pkg/models/team_namespace_update.go diff --git a/pkg/models/team_right.go b/pkg/models/team_right.go new file mode 100644 index 0000000000..3bf47b4616 --- /dev/null +++ b/pkg/models/team_right.go @@ -0,0 +1,27 @@ +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 +} diff --git a/models/teams.go b/pkg/models/teams.go similarity index 100% rename from models/teams.go rename to pkg/models/teams.go diff --git a/models/teams_create.go b/pkg/models/teams_create.go similarity index 100% rename from models/teams_create.go rename to pkg/models/teams_create.go diff --git a/models/teams_delete.go b/pkg/models/teams_delete.go similarity index 100% rename from models/teams_delete.go rename to pkg/models/teams_delete.go diff --git a/pkg/models/teams_rights.go b/pkg/models/teams_rights.go new file mode 100644 index 0000000000..da875b4add --- /dev/null +++ b/pkg/models/teams_rights.go @@ -0,0 +1,58 @@ +package models + +import ( + "code.vikunja.io/api/pkg/log" +) + +// CanCreate checks if the user can create a new team +func (t *Team) CanCreate(u *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(u *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 = ?", u.ID). + And("admin = ?", true). + Get(&TeamMember{}) + if err != nil { + log.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(u *User) bool { + return t.IsAdmin(u) +} + +// IsAdmin returns true when the user is admin of a team +func (t *Team) IsAdmin(u *User) bool { + exists, err := x.Where("team_id = ?", t.ID). + And("user_id = ?", u.ID). + And("admin = ?", true). + Get(&TeamMember{}) + if err != nil { + log.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.Log.Error("Error occurred during CanUpdate for Team: %s", err) + return false + } + return exists +} diff --git a/models/teams_test.go b/pkg/models/teams_test.go similarity index 100% rename from models/teams_test.go rename to pkg/models/teams_test.go diff --git a/models/teams_update.go b/pkg/models/teams_update.go similarity index 100% rename from models/teams_update.go rename to pkg/models/teams_update.go diff --git a/models/test_fixtures.go b/pkg/models/test_fixtures.go similarity index 100% rename from models/test_fixtures.go rename to pkg/models/test_fixtures.go diff --git a/models/unit_tests.go b/pkg/models/unit_tests.go similarity index 97% rename from models/unit_tests.go rename to pkg/models/unit_tests.go index 9b31d5111d..c627e46411 100644 --- a/models/unit_tests.go +++ b/pkg/models/unit_tests.go @@ -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" diff --git a/models/user.go b/pkg/models/user.go similarity index 100% rename from models/user.go rename to pkg/models/user.go diff --git a/models/user_add_update.go b/pkg/models/user_add_update.go similarity index 97% rename from models/user_add_update.go rename to pkg/models/user_add_update.go index d77610f9b2..6f71fd4748 100644 --- a/models/user_add_update.go +++ b/pkg/models/user_add_update.go @@ -1,8 +1,8 @@ package models import ( - "code.vikunja.io/api/models/mail" - "code.vikunja.io/api/models/utils" + "code.vikunja.io/api/pkg/mail" + "code.vikunja.io/api/pkg/utils" "golang.org/x/crypto/bcrypt" ) diff --git a/models/user_delete.go b/pkg/models/user_delete.go similarity index 100% rename from models/user_delete.go rename to pkg/models/user_delete.go diff --git a/models/user_email_confirm.go b/pkg/models/user_email_confirm.go similarity index 100% rename from models/user_email_confirm.go rename to pkg/models/user_email_confirm.go diff --git a/models/user_password_reset.go b/pkg/models/user_password_reset.go similarity index 96% rename from models/user_password_reset.go rename to pkg/models/user_password_reset.go index 3137164847..eb10ab6e93 100644 --- a/models/user_password_reset.go +++ b/pkg/models/user_password_reset.go @@ -1,8 +1,8 @@ package models import ( - "code.vikunja.io/api/models/mail" - "code.vikunja.io/api/models/utils" + "code.vikunja.io/api/pkg/mail" + "code.vikunja.io/api/pkg/utils" ) // PasswordReset holds the data to reset a password diff --git a/pkg/models/user_right.go b/pkg/models/user_right.go new file mode 100644 index 0000000000..d53b26b7ba --- /dev/null +++ b/pkg/models/user_right.go @@ -0,0 +1,27 @@ +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 +} diff --git a/models/user_test.go b/pkg/models/user_test.go similarity index 99% rename from models/user_test.go rename to pkg/models/user_test.go index c03a968bc0..d99bf488b9 100644 --- a/models/user_test.go +++ b/pkg/models/user_test.go @@ -1,7 +1,7 @@ package models import ( - "code.vikunja.io/api/models/utils" + "code.vikunja.io/api/pkg/utils" "github.com/stretchr/testify/assert" "testing" ) diff --git a/models/users_list.go b/pkg/models/users_list.go similarity index 100% rename from models/users_list.go rename to pkg/models/users_list.go diff --git a/routes/api/v1/list_by_namespace.go b/pkg/routes/api/v1/list_by_namespace.go similarity index 98% rename from routes/api/v1/list_by_namespace.go rename to pkg/routes/api/v1/list_by_namespace.go index 8585b7ba8f..bcfa50542b 100644 --- a/routes/api/v1/list_by_namespace.go +++ b/pkg/routes/api/v1/list_by_namespace.go @@ -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" diff --git a/routes/api/v1/login.go b/pkg/routes/api/v1/login.go similarity index 97% rename from routes/api/v1/login.go rename to pkg/routes/api/v1/login.go index 15d67238cf..b88e5e6455 100644 --- a/routes/api/v1/login.go +++ b/pkg/routes/api/v1/login.go @@ -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" diff --git a/routes/api/v1/swagger/options.go b/pkg/routes/api/v1/swagger/options.go similarity index 94% rename from routes/api/v1/swagger/options.go rename to pkg/routes/api/v1/swagger/options.go index 845734808a..ac3aa282c4 100644 --- a/routes/api/v1/swagger/options.go +++ b/pkg/routes/api/v1/swagger/options.go @@ -1,6 +1,8 @@ package swagger -import "code.vikunja.io/api/models" +import ( + "code.vikunja.io/api/pkg/models" +) // not actually a response, just a hack to get go-swagger to include definitions // of the various XYZOption structs diff --git a/routes/api/v1/swagger/responses.go b/pkg/routes/api/v1/swagger/responses.go similarity index 97% rename from routes/api/v1/swagger/responses.go rename to pkg/routes/api/v1/swagger/responses.go index b65a2ed649..5a15abb461 100644 --- a/routes/api/v1/swagger/responses.go +++ b/pkg/routes/api/v1/swagger/responses.go @@ -1,6 +1,8 @@ package swagger -import "code.vikunja.io/api/models" +import ( + "code.vikunja.io/api/pkg/models" +) // Message // swagger:response Message diff --git a/routes/api/v1/swaggerdocs.go b/pkg/routes/api/v1/swaggerdocs.go similarity index 100% rename from routes/api/v1/swaggerdocs.go rename to pkg/routes/api/v1/swaggerdocs.go diff --git a/routes/api/v1/token_check.go b/pkg/routes/api/v1/token_check.go similarity index 91% rename from routes/api/v1/token_check.go rename to pkg/routes/api/v1/token_check.go index f35aab90e0..76bef03ded 100644 --- a/routes/api/v1/token_check.go +++ b/pkg/routes/api/v1/token_check.go @@ -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" diff --git a/routes/api/v1/user_add_update.go b/pkg/routes/api/v1/user_add_update.go similarity index 96% rename from routes/api/v1/user_add_update.go rename to pkg/routes/api/v1/user_add_update.go index 8fb339664c..b5e8e16e64 100644 --- a/routes/api/v1/user_add_update.go +++ b/pkg/routes/api/v1/user_add_update.go @@ -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" diff --git a/routes/api/v1/user_confirm_email.go b/pkg/routes/api/v1/user_confirm_email.go similarity index 93% rename from routes/api/v1/user_confirm_email.go rename to pkg/routes/api/v1/user_confirm_email.go index 03d9108af8..d59ff63dcc 100644 --- a/routes/api/v1/user_confirm_email.go +++ b/pkg/routes/api/v1/user_confirm_email.go @@ -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" ) diff --git a/routes/api/v1/user_delete.go b/pkg/routes/api/v1/user_delete.go similarity index 92% rename from routes/api/v1/user_delete.go rename to pkg/routes/api/v1/user_delete.go index f3d2656822..a7726117f8 100644 --- a/routes/api/v1/user_delete.go +++ b/pkg/routes/api/v1/user_delete.go @@ -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" diff --git a/routes/api/v1/user_list.go b/pkg/routes/api/v1/user_list.go similarity index 91% rename from routes/api/v1/user_list.go rename to pkg/routes/api/v1/user_list.go index e86080e044..8a16838490 100644 --- a/routes/api/v1/user_list.go +++ b/pkg/routes/api/v1/user_list.go @@ -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" ) diff --git a/routes/api/v1/user_password_reset.go b/pkg/routes/api/v1/user_password_reset.go similarity index 96% rename from routes/api/v1/user_password_reset.go rename to pkg/routes/api/v1/user_password_reset.go index 1e26eaf864..5fbd14da09 100644 --- a/routes/api/v1/user_password_reset.go +++ b/pkg/routes/api/v1/user_password_reset.go @@ -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" ) diff --git a/routes/api/v1/user_show.go b/pkg/routes/api/v1/user_show.go similarity index 91% rename from routes/api/v1/user_show.go rename to pkg/routes/api/v1/user_show.go index 4c591ab646..0ddb734ee3 100644 --- a/routes/api/v1/user_show.go +++ b/pkg/routes/api/v1/user_show.go @@ -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" ) diff --git a/routes/api/v1/user_update_password.go b/pkg/routes/api/v1/user_update_password.go similarity index 95% rename from routes/api/v1/user_update_password.go rename to pkg/routes/api/v1/user_update_password.go index 9c0b23ac14..b588abb579 100644 --- a/routes/api/v1/user_update_password.go +++ b/pkg/routes/api/v1/user_update_password.go @@ -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" ) diff --git a/routes/crud/create.go b/pkg/routes/crud/create.go similarity index 82% rename from routes/crud/create.go rename to pkg/routes/crud/create.go index a1090cdb49..33aed5751b 100644 --- a/routes/crud/create.go +++ b/pkg/routes/crud/create.go @@ -1,7 +1,8 @@ package crud import ( - "code.vikunja.io/api/models" + "code.vikunja.io/api/pkg/log" + "code.vikunja.io/api/pkg/models" "github.com/labstack/echo" "net/http" ) @@ -24,7 +25,7 @@ func (c *WebHandler) CreateWeb(ctx echo.Context) error { // 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) } diff --git a/routes/crud/delete.go b/pkg/routes/crud/delete.go similarity index 72% rename from routes/crud/delete.go rename to pkg/routes/crud/delete.go index bd05144478..d3f5c7ac41 100644 --- a/routes/crud/delete.go +++ b/pkg/routes/crud/delete.go @@ -1,7 +1,8 @@ package crud import ( - "code.vikunja.io/api/models" + "code.vikunja.io/api/pkg/log" + "code.vikunja.io/api/pkg/models" "github.com/labstack/echo" "net/http" ) @@ -18,12 +19,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 := models.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) } diff --git a/routes/crud/helper.go b/pkg/routes/crud/helper.go similarity index 87% rename from routes/crud/helper.go rename to pkg/routes/crud/helper.go index 5f742de9dd..bdb981d0dd 100644 --- a/routes/crud/helper.go +++ b/pkg/routes/crud/helper.go @@ -1,7 +1,8 @@ package crud import ( - "code.vikunja.io/api/models" + "code.vikunja.io/api/pkg/log" + "code.vikunja.io/api/pkg/models" "github.com/labstack/echo" "net/http" ) @@ -24,6 +25,6 @@ func HandleHTTPError(err error) *echo.HTTPError { errDetails := a.HTTPError() return echo.NewHTTPError(errDetails.HTTPCode, errDetails) } - models.Log.Error(err.Error()) + log.Log.Error(err.Error()) return echo.NewHTTPError(http.StatusInternalServerError) } diff --git a/routes/crud/paramBinder.go b/pkg/routes/crud/paramBinder.go similarity index 100% rename from routes/crud/paramBinder.go rename to pkg/routes/crud/paramBinder.go diff --git a/routes/crud/read_all.go b/pkg/routes/crud/read_all.go similarity index 95% rename from routes/crud/read_all.go rename to pkg/routes/crud/read_all.go index 45c39fbe1f..b6e53c2c8a 100644 --- a/routes/crud/read_all.go +++ b/pkg/routes/crud/read_all.go @@ -1,7 +1,7 @@ package crud import ( - "code.vikunja.io/api/models" + "code.vikunja.io/api/pkg/models" "github.com/labstack/echo" "net/http" ) diff --git a/routes/crud/read_one.go b/pkg/routes/crud/read_one.go similarity index 84% rename from routes/crud/read_one.go rename to pkg/routes/crud/read_one.go index a5461a733e..6e920978f5 100644 --- a/routes/crud/read_one.go +++ b/pkg/routes/crud/read_one.go @@ -1,7 +1,8 @@ package crud import ( - "code.vikunja.io/api/models" + "code.vikunja.io/api/pkg/log" + "code.vikunja.io/api/pkg/models" "github.com/labstack/echo" "net/http" ) @@ -29,7 +30,7 @@ func (c *WebHandler) ReadOneWeb(ctx echo.Context) error { 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") } diff --git a/routes/crud/update.go b/pkg/routes/crud/update.go similarity index 82% rename from routes/crud/update.go rename to pkg/routes/crud/update.go index b5e5002d0f..496a2c4ef8 100644 --- a/routes/crud/update.go +++ b/pkg/routes/crud/update.go @@ -1,7 +1,8 @@ package crud import ( - "code.vikunja.io/api/models" + "code.vikunja.io/api/pkg/log" + "code.vikunja.io/api/pkg/models" "github.com/labstack/echo" "net/http" ) @@ -23,7 +24,7 @@ func (c *WebHandler) UpdateWeb(ctx echo.Context) error { 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) } diff --git a/routes/routes.go b/pkg/routes/routes.go similarity index 96% rename from routes/routes.go rename to pkg/routes/routes.go index 9731a2fa30..27e3e46bff 100644 --- a/routes/routes.go +++ b/pkg/routes/routes.go @@ -27,13 +27,13 @@ package routes import ( + "code.vikunja.io/api/pkg/models" "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" ) diff --git a/models/utils/random_string.go b/pkg/utils/random_string.go similarity index 100% rename from models/utils/random_string.go rename to pkg/utils/random_string.go