1
0

Move the crudhandler to own repo (#27)

This commit is contained in:
konrad
2018-11-30 23:26:56 +00:00
committed by Gitea
parent d9304f6996
commit ce2cae9430
228 changed files with 13281 additions and 3292 deletions

View File

@ -1,26 +0,0 @@
// Vikunja is a todo-list application to facilitate your life.
// Copyright 2018 Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
package models
// CRUDable defines the crud methods
type CRUDable interface {
Create(*User) error
ReadOne() error
ReadAll(string, *User, int) (interface{}, error)
Update() error
Delete() error
}

View File

@ -1,5 +1,5 @@
// Vikunja is a todo-list application to facilitate your life.
// Copyright 2018 Vikunja and contributors. All rights reserved.
// Copyright 2018 Vikunja and contributors. All web.Rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@ -17,22 +17,11 @@
package models
import (
"code.vikunja.io/web"
"fmt"
"net/http"
)
// HTTPErrorProcessor is executed when the defined error is thrown, it will make sure the user sees an appropriate error message and http status code
type HTTPErrorProcessor interface {
HTTPError() HTTPError
}
// HTTPError holds informations about an http error
type HTTPError struct {
HTTPCode int `json:"-"`
Code int `json:"code"`
Message string `json:"message"`
}
// =====================
// User Operation Errors
// =====================
@ -57,8 +46,8 @@ func (err ErrUsernameExists) Error() string {
const ErrorCodeUsernameExists = 1001
// HTTPError holds the http error description
func (err ErrUsernameExists) HTTPError() HTTPError {
return HTTPError{HTTPCode: http.StatusBadRequest, Code: ErrorCodeUsernameExists, Message: "A user with this username already exists."}
func (err ErrUsernameExists) HTTPError() web.HTTPError {
return web.HTTPError{HTTPCode: http.StatusBadRequest, Code: ErrorCodeUsernameExists, Message: "A user with this username already exists."}
}
// ErrUserEmailExists represents a "UserEmailExists" kind of error.
@ -81,8 +70,8 @@ func (err ErrUserEmailExists) Error() string {
const ErrorCodeUserEmailExists = 1002
// HTTPError holds the http error description
func (err ErrUserEmailExists) HTTPError() HTTPError {
return HTTPError{HTTPCode: http.StatusBadRequest, Code: ErrorCodeUserEmailExists, Message: "A user with this email address already exists."}
func (err ErrUserEmailExists) HTTPError() web.HTTPError {
return web.HTTPError{HTTPCode: http.StatusBadRequest, Code: ErrorCodeUserEmailExists, Message: "A user with this email address already exists."}
}
// ErrNoUsernamePassword represents a "NoUsernamePassword" kind of error.
@ -102,8 +91,8 @@ func (err ErrNoUsernamePassword) Error() string {
const ErrCodeNoUsernamePassword = 1004
// HTTPError holds the http error description
func (err ErrNoUsernamePassword) HTTPError() HTTPError {
return HTTPError{HTTPCode: http.StatusBadRequest, Code: ErrCodeNoUsernamePassword, Message: "Please specify a username and a password."}
func (err ErrNoUsernamePassword) HTTPError() web.HTTPError {
return web.HTTPError{HTTPCode: http.StatusBadRequest, Code: ErrCodeNoUsernamePassword, Message: "Please specify a username and a password."}
}
// ErrUserDoesNotExist represents a "UserDoesNotExist" kind of error.
@ -125,8 +114,8 @@ func (err ErrUserDoesNotExist) Error() string {
const ErrCodeUserDoesNotExist = 1005
// HTTPError holds the http error description
func (err ErrUserDoesNotExist) HTTPError() HTTPError {
return HTTPError{HTTPCode: http.StatusNotFound, Code: ErrCodeUserDoesNotExist, Message: "The user does not exist."}
func (err ErrUserDoesNotExist) HTTPError() web.HTTPError {
return web.HTTPError{HTTPCode: http.StatusNotFound, Code: ErrCodeUserDoesNotExist, Message: "The user does not exist."}
}
// ErrCouldNotGetUserID represents a "ErrCouldNotGetUserID" kind of error.
@ -146,8 +135,8 @@ func (err ErrCouldNotGetUserID) Error() string {
const ErrCodeCouldNotGetUserID = 1006
// HTTPError holds the http error description
func (err ErrCouldNotGetUserID) HTTPError() HTTPError {
return HTTPError{HTTPCode: http.StatusBadRequest, Code: ErrCodeCouldNotGetUserID, Message: "Could not get user id."}
func (err ErrCouldNotGetUserID) HTTPError() web.HTTPError {
return web.HTTPError{HTTPCode: http.StatusBadRequest, Code: ErrCodeCouldNotGetUserID, Message: "Could not get user id."}
}
// ErrNoPasswordResetToken represents an error where no password reset token exists for that user
@ -163,8 +152,8 @@ func (err ErrNoPasswordResetToken) Error() string {
const ErrCodeNoPasswordResetToken = 1008
// HTTPError holds the http error description
func (err ErrNoPasswordResetToken) HTTPError() HTTPError {
return HTTPError{HTTPCode: http.StatusPreconditionFailed, Code: ErrCodeNoPasswordResetToken, Message: "No token to reset a user's password provided."}
func (err ErrNoPasswordResetToken) HTTPError() web.HTTPError {
return web.HTTPError{HTTPCode: http.StatusPreconditionFailed, Code: ErrCodeNoPasswordResetToken, Message: "No token to reset a user's password provided."}
}
// ErrInvalidPasswordResetToken is an error where the password reset token is invalid
@ -180,8 +169,8 @@ func (err ErrInvalidPasswordResetToken) Error() string {
const ErrCodeInvalidPasswordResetToken = 1009
// HTTPError holds the http error description
func (err ErrInvalidPasswordResetToken) HTTPError() HTTPError {
return HTTPError{HTTPCode: http.StatusPreconditionFailed, Code: ErrCodeInvalidPasswordResetToken, Message: "Invalid token to reset a user's password."}
func (err ErrInvalidPasswordResetToken) HTTPError() web.HTTPError {
return web.HTTPError{HTTPCode: http.StatusPreconditionFailed, Code: ErrCodeInvalidPasswordResetToken, Message: "Invalid token to reset a user's password."}
}
// IsErrInvalidPasswordResetToken checks if an error is a ErrInvalidPasswordResetToken.
@ -203,8 +192,8 @@ func (err ErrInvalidEmailConfirmToken) Error() string {
const ErrCodeInvalidEmailConfirmToken = 1010
// HTTPError holds the http error description
func (err ErrInvalidEmailConfirmToken) HTTPError() HTTPError {
return HTTPError{HTTPCode: http.StatusPreconditionFailed, Code: ErrCodeInvalidEmailConfirmToken, Message: "Invalid email confirm token."}
func (err ErrInvalidEmailConfirmToken) HTTPError() web.HTTPError {
return web.HTTPError{HTTPCode: http.StatusPreconditionFailed, Code: ErrCodeInvalidEmailConfirmToken, Message: "Invalid email confirm token."}
}
// IsErrInvalidEmailConfirmToken checks if an error is a ErrInvalidEmailConfirmToken.
@ -225,8 +214,8 @@ func (err ErrWrongUsernameOrPassword) Error() string {
const ErrCodeWrongUsernameOrPassword = 1011
// HTTPError holds the http error description
func (err ErrWrongUsernameOrPassword) HTTPError() HTTPError {
return HTTPError{HTTPCode: http.StatusPreconditionFailed, Code: ErrCodeWrongUsernameOrPassword, Message: "Wrong username or password."}
func (err ErrWrongUsernameOrPassword) HTTPError() web.HTTPError {
return web.HTTPError{HTTPCode: http.StatusPreconditionFailed, Code: ErrCodeWrongUsernameOrPassword, Message: "Wrong username or password."}
}
// IsErrWrongUsernameOrPassword checks if an error is a IsErrEmailNotConfirmed.
@ -248,8 +237,8 @@ func (err ErrEmailNotConfirmed) Error() string {
const ErrCodeEmailNotConfirmed = 1012
// HTTPError holds the http error description
func (err ErrEmailNotConfirmed) HTTPError() HTTPError {
return HTTPError{HTTPCode: http.StatusPreconditionFailed, Code: ErrCodeEmailNotConfirmed, Message: "Please confirm your email address."}
func (err ErrEmailNotConfirmed) HTTPError() web.HTTPError {
return web.HTTPError{HTTPCode: http.StatusPreconditionFailed, Code: ErrCodeEmailNotConfirmed, Message: "Please confirm your email address."}
}
// IsErrEmailNotConfirmed checks if an error is a IsErrEmailNotConfirmed.
@ -279,8 +268,8 @@ func (err ErrIDCannotBeZero) Error() string {
const ErrCodeIDCannotBeZero = 2001
// HTTPError holds the http error description
func (err ErrIDCannotBeZero) HTTPError() HTTPError {
return HTTPError{HTTPCode: http.StatusBadRequest, Code: ErrCodeIDCannotBeZero, Message: "The ID cannot be empty or 0."}
func (err ErrIDCannotBeZero) HTTPError() web.HTTPError {
return web.HTTPError{HTTPCode: http.StatusBadRequest, Code: ErrCodeIDCannotBeZero, Message: "The ID cannot be empty or 0."}
}
// ErrInvalidData represents a "ErrInvalidData" kind of error. Used when a struct is invalid -> validation failed.
@ -302,13 +291,13 @@ func (err ErrInvalidData) Error() string {
const ErrCodeInvalidData = 2002
// HTTPError holds the http error description
func (err ErrInvalidData) HTTPError() HTTPError {
return HTTPError{HTTPCode: http.StatusBadRequest, Code: ErrCodeInvalidData, Message: err.Message}
func (err ErrInvalidData) HTTPError() web.HTTPError {
return web.HTTPError{HTTPCode: http.StatusBadRequest, Code: ErrCodeInvalidData, Message: err.Message}
}
// ValidationHTTPError is the http error when a validation fails
type ValidationHTTPError struct {
HTTPError
web.HTTPError
InvalidFields []string `json:"invalid_fields"`
}
@ -343,8 +332,8 @@ func (err ErrListDoesNotExist) Error() string {
const ErrCodeListDoesNotExist = 3001
// HTTPError holds the http error description
func (err ErrListDoesNotExist) HTTPError() HTTPError {
return HTTPError{HTTPCode: http.StatusNotFound, Code: ErrCodeListDoesNotExist, Message: "This list does not exist."}
func (err ErrListDoesNotExist) HTTPError() web.HTTPError {
return web.HTTPError{HTTPCode: http.StatusNotFound, Code: ErrCodeListDoesNotExist, Message: "This list does not exist."}
}
// ErrNeedToHaveListReadAccess represents an error, where the user dont has read access to that List
@ -367,8 +356,8 @@ func (err ErrNeedToHaveListReadAccess) Error() string {
const ErrCodeNeedToHaveListReadAccess = 3004
// HTTPError holds the http error description
func (err ErrNeedToHaveListReadAccess) HTTPError() HTTPError {
return HTTPError{HTTPCode: http.StatusForbidden, Code: ErrCodeNeedToHaveListReadAccess, Message: "You need to have read access to this list."}
func (err ErrNeedToHaveListReadAccess) HTTPError() web.HTTPError {
return web.HTTPError{HTTPCode: http.StatusForbidden, Code: ErrCodeNeedToHaveListReadAccess, Message: "You need to have read access to this list."}
}
// ErrListTitleCannotBeEmpty represents a "ErrListTitleCannotBeEmpty" kind of error. Used if the list does not exist.
@ -388,8 +377,8 @@ func (err ErrListTitleCannotBeEmpty) Error() string {
const ErrCodeListTitleCannotBeEmpty = 3005
// HTTPError holds the http error description
func (err ErrListTitleCannotBeEmpty) HTTPError() HTTPError {
return HTTPError{HTTPCode: http.StatusBadRequest, Code: ErrCodeListTitleCannotBeEmpty, Message: "You must provide at least a list title."}
func (err ErrListTitleCannotBeEmpty) HTTPError() web.HTTPError {
return web.HTTPError{HTTPCode: http.StatusBadRequest, Code: ErrCodeListTitleCannotBeEmpty, Message: "You must provide at least a list title."}
}
// ================
@ -413,8 +402,8 @@ func (err ErrListTaskCannotBeEmpty) Error() string {
const ErrCodeListTaskCannotBeEmpty = 4001
// HTTPError holds the http error description
func (err ErrListTaskCannotBeEmpty) HTTPError() HTTPError {
return HTTPError{HTTPCode: http.StatusBadRequest, Code: ErrCodeListTaskCannotBeEmpty, Message: "You must provide at least a list task text."}
func (err ErrListTaskCannotBeEmpty) HTTPError() web.HTTPError {
return web.HTTPError{HTTPCode: http.StatusBadRequest, Code: ErrCodeListTaskCannotBeEmpty, Message: "You must provide at least a list task text."}
}
// ErrListTaskDoesNotExist represents a "ErrListDoesNotExist" kind of error. Used if the list does not exist.
@ -436,8 +425,8 @@ func (err ErrListTaskDoesNotExist) Error() string {
const ErrCodeListTaskDoesNotExist = 4002
// HTTPError holds the http error description
func (err ErrListTaskDoesNotExist) HTTPError() HTTPError {
return HTTPError{HTTPCode: http.StatusNotFound, Code: ErrCodeListTaskDoesNotExist, Message: "This list task does not exist"}
func (err ErrListTaskDoesNotExist) HTTPError() web.HTTPError {
return web.HTTPError{HTTPCode: http.StatusNotFound, Code: ErrCodeListTaskDoesNotExist, Message: "This list task does not exist"}
}
// =================
@ -463,8 +452,8 @@ func (err ErrNamespaceDoesNotExist) Error() string {
const ErrCodeNamespaceDoesNotExist = 5001
// HTTPError holds the http error description
func (err ErrNamespaceDoesNotExist) HTTPError() HTTPError {
return HTTPError{HTTPCode: http.StatusNotFound, Code: ErrCodeNamespaceDoesNotExist, Message: "Namespace not found."}
func (err ErrNamespaceDoesNotExist) HTTPError() web.HTTPError {
return web.HTTPError{HTTPCode: http.StatusNotFound, Code: ErrCodeNamespaceDoesNotExist, Message: "Namespace not found."}
}
// ErrUserDoesNotHaveAccessToNamespace represents an error, where the user is not the owner of that namespace (used i.e. when deleting a namespace)
@ -487,8 +476,8 @@ func (err ErrUserDoesNotHaveAccessToNamespace) Error() string {
const ErrCodeUserDoesNotHaveAccessToNamespace = 5003
// HTTPError holds the http error description
func (err ErrUserDoesNotHaveAccessToNamespace) HTTPError() HTTPError {
return HTTPError{HTTPCode: http.StatusForbidden, Code: ErrCodeUserDoesNotHaveAccessToNamespace, Message: "This user does not have access to the namespace."}
func (err ErrUserDoesNotHaveAccessToNamespace) HTTPError() web.HTTPError {
return web.HTTPError{HTTPCode: http.StatusForbidden, Code: ErrCodeUserDoesNotHaveAccessToNamespace, Message: "This user does not have access to the namespace."}
}
// ErrNamespaceNameCannotBeEmpty represents an error, where a namespace name is empty.
@ -511,8 +500,8 @@ func (err ErrNamespaceNameCannotBeEmpty) Error() string {
const ErrCodeNamespaceNameCannotBeEmpty = 5006
// HTTPError holds the http error description
func (err ErrNamespaceNameCannotBeEmpty) HTTPError() HTTPError {
return HTTPError{HTTPCode: http.StatusBadRequest, Code: ErrCodeNamespaceNameCannotBeEmpty, Message: "The namespace name cannot be empty."}
func (err ErrNamespaceNameCannotBeEmpty) HTTPError() web.HTTPError {
return web.HTTPError{HTTPCode: http.StatusBadRequest, Code: ErrCodeNamespaceNameCannotBeEmpty, Message: "The namespace name cannot be empty."}
}
// ErrNeedToHaveNamespaceReadAccess represents an error, where the user is not the owner of that namespace (used i.e. when deleting a namespace)
@ -535,8 +524,8 @@ func (err ErrNeedToHaveNamespaceReadAccess) Error() string {
const ErrCodeNeedToHaveNamespaceReadAccess = 5009
// HTTPError holds the http error description
func (err ErrNeedToHaveNamespaceReadAccess) HTTPError() HTTPError {
return HTTPError{HTTPCode: http.StatusForbidden, Code: ErrCodeNeedToHaveNamespaceReadAccess, Message: "You need to have namespace read access to do this."}
func (err ErrNeedToHaveNamespaceReadAccess) HTTPError() web.HTTPError {
return web.HTTPError{HTTPCode: http.StatusForbidden, Code: ErrCodeNeedToHaveNamespaceReadAccess, Message: "You need to have namespace read access to do this."}
}
// ErrTeamDoesNotHaveAccessToNamespace represents an error, where the Team is not the owner of that namespace (used i.e. when deleting a namespace)
@ -559,8 +548,8 @@ func (err ErrTeamDoesNotHaveAccessToNamespace) Error() string {
const ErrCodeTeamDoesNotHaveAccessToNamespace = 5010
// HTTPError holds the http error description
func (err ErrTeamDoesNotHaveAccessToNamespace) HTTPError() HTTPError {
return HTTPError{HTTPCode: http.StatusForbidden, Code: ErrCodeTeamDoesNotHaveAccessToNamespace, Message: "You need to have access to this namespace to do this."}
func (err ErrTeamDoesNotHaveAccessToNamespace) HTTPError() web.HTTPError {
return web.HTTPError{HTTPCode: http.StatusForbidden, Code: ErrCodeTeamDoesNotHaveAccessToNamespace, Message: "You need to have access to this namespace to do this."}
}
// ErrUserAlreadyHasNamespaceAccess represents an error where a user already has access to a namespace
@ -583,8 +572,8 @@ func (err ErrUserAlreadyHasNamespaceAccess) Error() string {
const ErrCodeUserAlreadyHasNamespaceAccess = 5011
// HTTPError holds the http error description
func (err ErrUserAlreadyHasNamespaceAccess) HTTPError() HTTPError {
return HTTPError{HTTPCode: http.StatusConflict, Code: ErrCodeUserAlreadyHasNamespaceAccess, Message: "This user already has access to this namespace."}
func (err ErrUserAlreadyHasNamespaceAccess) HTTPError() web.HTTPError {
return web.HTTPError{HTTPCode: http.StatusConflict, Code: ErrCodeUserAlreadyHasNamespaceAccess, Message: "This user already has access to this namespace."}
}
// ============
@ -610,8 +599,8 @@ func (err ErrTeamNameCannotBeEmpty) Error() string {
const ErrCodeTeamNameCannotBeEmpty = 6001
// HTTPError holds the http error description
func (err ErrTeamNameCannotBeEmpty) HTTPError() HTTPError {
return HTTPError{HTTPCode: http.StatusBadRequest, Code: ErrCodeTeamNameCannotBeEmpty, Message: "The team name cannot be empty"}
func (err ErrTeamNameCannotBeEmpty) HTTPError() web.HTTPError {
return web.HTTPError{HTTPCode: http.StatusBadRequest, Code: ErrCodeTeamNameCannotBeEmpty, Message: "The team name cannot be empty"}
}
// ErrTeamDoesNotExist represents an error where a team does not exist
@ -633,8 +622,8 @@ func (err ErrTeamDoesNotExist) Error() string {
const ErrCodeTeamDoesNotExist = 6002
// HTTPError holds the http error description
func (err ErrTeamDoesNotExist) HTTPError() HTTPError {
return HTTPError{HTTPCode: http.StatusNotFound, Code: ErrCodeTeamDoesNotExist, Message: "This team does not exist."}
func (err ErrTeamDoesNotExist) HTTPError() web.HTTPError {
return web.HTTPError{HTTPCode: http.StatusNotFound, Code: ErrCodeTeamDoesNotExist, Message: "This team does not exist."}
}
// ErrInvalidTeamRight represents an error where a team right is invalid
@ -656,8 +645,8 @@ func (err ErrInvalidTeamRight) Error() string {
const ErrCodeInvalidTeamRight = 6003
// HTTPError holds the http error description
func (err ErrInvalidTeamRight) HTTPError() HTTPError {
return HTTPError{HTTPCode: http.StatusBadRequest, Code: ErrCodeInvalidTeamRight, Message: "The team right is invalid."}
func (err ErrInvalidTeamRight) HTTPError() web.HTTPError {
return web.HTTPError{HTTPCode: http.StatusBadRequest, Code: ErrCodeInvalidTeamRight, Message: "The team right is invalid."}
}
// ErrTeamAlreadyHasAccess represents an error where a team already has access to a list/namespace
@ -680,8 +669,8 @@ func (err ErrTeamAlreadyHasAccess) Error() string {
const ErrCodeTeamAlreadyHasAccess = 6004
// HTTPError holds the http error description
func (err ErrTeamAlreadyHasAccess) HTTPError() HTTPError {
return HTTPError{HTTPCode: http.StatusConflict, Code: ErrCodeTeamAlreadyHasAccess, Message: "This team already has access."}
func (err ErrTeamAlreadyHasAccess) HTTPError() web.HTTPError {
return web.HTTPError{HTTPCode: http.StatusConflict, Code: ErrCodeTeamAlreadyHasAccess, Message: "This team already has access."}
}
// ErrUserIsMemberOfTeam represents an error where a user is already member of a team.
@ -704,8 +693,8 @@ func (err ErrUserIsMemberOfTeam) Error() string {
const ErrCodeUserIsMemberOfTeam = 6005
// HTTPError holds the http error description
func (err ErrUserIsMemberOfTeam) HTTPError() HTTPError {
return HTTPError{HTTPCode: http.StatusConflict, Code: ErrCodeUserIsMemberOfTeam, Message: "This user is already a member of that team."}
func (err ErrUserIsMemberOfTeam) HTTPError() web.HTTPError {
return web.HTTPError{HTTPCode: http.StatusConflict, Code: ErrCodeUserIsMemberOfTeam, Message: "This user is already a member of that team."}
}
// ErrCannotDeleteLastTeamMember represents an error where a user wants to delete the last member of a team (probably himself)
@ -728,8 +717,8 @@ func (err ErrCannotDeleteLastTeamMember) Error() string {
const ErrCodeCannotDeleteLastTeamMember = 6006
// HTTPError holds the http error description
func (err ErrCannotDeleteLastTeamMember) HTTPError() HTTPError {
return HTTPError{HTTPCode: http.StatusBadRequest, Code: ErrCodeCannotDeleteLastTeamMember, Message: "You cannot delete the last member of a team."}
func (err ErrCannotDeleteLastTeamMember) HTTPError() web.HTTPError {
return web.HTTPError{HTTPCode: http.StatusBadRequest, Code: ErrCodeCannotDeleteLastTeamMember, Message: "You cannot delete the last member of a team."}
}
// ErrTeamDoesNotHaveAccessToList represents an error, where the Team is not the owner of that List (used i.e. when deleting a List)
@ -752,8 +741,8 @@ func (err ErrTeamDoesNotHaveAccessToList) Error() string {
const ErrCodeTeamDoesNotHaveAccessToList = 6007
// HTTPError holds the http error description
func (err ErrTeamDoesNotHaveAccessToList) HTTPError() HTTPError {
return HTTPError{HTTPCode: http.StatusForbidden, Code: ErrCodeTeamDoesNotHaveAccessToList, Message: "This team does not have access to the list."}
func (err ErrTeamDoesNotHaveAccessToList) HTTPError() web.HTTPError {
return web.HTTPError{HTTPCode: http.StatusForbidden, Code: ErrCodeTeamDoesNotHaveAccessToList, Message: "This team does not have access to the list."}
}
// ====================
@ -779,8 +768,8 @@ func (err ErrInvalidUserRight) Error() string {
const ErrCodeInvalidUserRight = 7001
// HTTPError holds the http error description
func (err ErrInvalidUserRight) HTTPError() HTTPError {
return HTTPError{HTTPCode: http.StatusBadRequest, Code: ErrCodeInvalidUserRight, Message: "The user right is invalid."}
func (err ErrInvalidUserRight) HTTPError() web.HTTPError {
return web.HTTPError{HTTPCode: http.StatusBadRequest, Code: ErrCodeInvalidUserRight, Message: "The user right is invalid."}
}
// ErrUserAlreadyHasAccess represents an error where a user already has access to a list/namespace
@ -803,8 +792,8 @@ func (err ErrUserAlreadyHasAccess) Error() string {
const ErrCodeUserAlreadyHasAccess = 7002
// HTTPError holds the http error description
func (err ErrUserAlreadyHasAccess) HTTPError() HTTPError {
return HTTPError{HTTPCode: http.StatusConflict, Code: ErrCodeUserAlreadyHasAccess, Message: "This user already has access to this list."}
func (err ErrUserAlreadyHasAccess) HTTPError() web.HTTPError {
return web.HTTPError{HTTPCode: http.StatusConflict, Code: ErrCodeUserAlreadyHasAccess, Message: "This user already has access to this list."}
}
// ErrUserDoesNotHaveAccessToList represents an error, where the user is not the owner of that List (used i.e. when deleting a List)
@ -827,6 +816,6 @@ func (err ErrUserDoesNotHaveAccessToList) Error() string {
const ErrCodeUserDoesNotHaveAccessToList = 7003
// HTTPError holds the http error description
func (err ErrUserDoesNotHaveAccessToList) HTTPError() HTTPError {
return HTTPError{HTTPCode: http.StatusForbidden, Code: ErrCodeUserDoesNotHaveAccessToList, Message: "This user does not have access to the list."}
func (err ErrUserDoesNotHaveAccessToList) HTTPError() web.HTTPError {
return web.HTTPError{HTTPCode: http.StatusForbidden, Code: ErrCodeUserDoesNotHaveAccessToList, Message: "This user does not have access to the list."}
}

View File

@ -16,7 +16,10 @@
package models
import "sort"
import (
"code.vikunja.io/web"
"sort"
)
// List represents a list of tasks
type List struct {
@ -32,8 +35,8 @@ type List struct {
Created int64 `xorm:"created" json:"created"`
Updated int64 `xorm:"updated" json:"updated"`
CRUDable `xorm:"-" json:"-"`
Rights `xorm:"-" json:"-"`
web.CRUDable `xorm:"-" json:"-"`
web.Rights `xorm:"-" json:"-"`
}
// GetListsByNamespaceID gets all lists in a namespace
@ -55,7 +58,12 @@ func GetListsByNamespaceID(nID int64) (lists []*List, err error) {
// @Failure 403 {object} models.HTTPError "The user does not have access to the list"
// @Failure 500 {object} models.Message "Internal error"
// @Router /lists [get]
func (l *List) ReadAll(search string, u *User, page int) (interface{}, error) {
func (l *List) ReadAll(search string, a web.Auth, page int) (interface{}, error) {
u, err := getUserWithError(a)
if err != nil {
return nil, err
}
lists, err := getRawListsForUser(search, u, page)
if err != nil {
return nil, err
@ -206,7 +214,12 @@ func AddListDetails(lists []*List) (err error) {
// @Success 200 {array} models.List "The tasks"
// @Failure 500 {object} models.Message "Internal error"
// @Router /tasks [get]
func (lt *ListTask) ReadAll(search string, u *User, page int) (interface{}, error) {
func (lt *ListTask) ReadAll(search string, a web.Auth, page int) (interface{}, error) {
u, err := getUserWithError(a)
if err != nil {
return nil, err
}
return GetTasksByUser(search, u, page)
}

View File

@ -16,6 +16,8 @@
package models
import "code.vikunja.io/web"
// CreateOrUpdateList updates a list or creates it if it doesn't exist
func CreateOrUpdateList(list *List) (err error) {
@ -84,7 +86,12 @@ func (l *List) Update() (err error) {
// @Failure 403 {object} models.HTTPError "The user does not have access to the list"
// @Failure 500 {object} models.Message "Internal error"
// @Router /namespaces/{namespaceID}/lists [put]
func (l *List) Create(doer *User) (err error) {
func (l *List) Create(a web.Auth) (err error) {
doer, err := getUserWithError(a)
if err != nil {
return err
}
// Check rights
u, err := GetUserByID(doer.ID)
if err != nil {

View File

@ -18,10 +18,13 @@ package models
import (
"code.vikunja.io/api/pkg/log"
"code.vikunja.io/web"
)
// IsAdmin returns whether the user has admin rights on the list or not
func (l *List) IsAdmin(u *User) bool {
func (l *List) IsAdmin(a web.Auth) bool {
u := getUserForRights(a)
// Owners are always admins
if l.Owner.ID == u.ID {
return true
@ -36,7 +39,9 @@ func (l *List) IsAdmin(u *User) bool {
}
// CanWrite return whether the user can write on that list or not
func (l *List) CanWrite(user *User) bool {
func (l *List) CanWrite(a web.Auth) bool {
user := getUserForRights(a)
// Admins always have write access
if l.IsAdmin(user) {
return true
@ -51,7 +56,9 @@ func (l *List) CanWrite(user *User) bool {
}
// CanRead checks if a user has read access to a list
func (l *List) CanRead(user *User) bool {
func (l *List) CanRead(a web.Auth) bool {
user := getUserForRights(a)
// Admins always have read access
if l.IsAdmin(user) {
return true
@ -66,7 +73,9 @@ func (l *List) CanRead(user *User) bool {
}
// CanDelete checks if the user can delete a list
func (l *List) CanDelete(doer *User) bool {
func (l *List) CanDelete(a web.Auth) bool {
doer := getUserForRights(a)
if err := l.GetSimpleByID(); err != nil {
log.Log.Error("Error occurred during CanDelete for List: %s", err)
return false
@ -75,7 +84,9 @@ func (l *List) CanDelete(doer *User) bool {
}
// CanUpdate checks if the user can update a list
func (l *List) CanUpdate(doer *User) bool {
func (l *List) CanUpdate(a web.Auth) bool {
doer := getUserForRights(a)
if err := l.GetSimpleByID(); err != nil {
log.Log.Error("Error occurred during CanUpdate for List: %s", err)
return false
@ -84,10 +95,10 @@ func (l *List) CanUpdate(doer *User) bool {
}
// CanCreate checks if the user can update a list
func (l *List) CanCreate(doer *User) bool {
func (l *List) CanCreate(a web.Auth) bool {
// A user can create a list if he has write access to the namespace
n, _ := GetNamespaceByID(l.NamespaceID)
return n.CanWrite(doer)
return n.CanWrite(a)
}
func (l *List) checkListTeamRight(user *User, r TeamRight) bool {

View File

@ -16,6 +16,8 @@
package models
import "code.vikunja.io/web"
// ListTask represents an task in a todolist
type ListTask struct {
ID int64 `xorm:"int(11) autoincr not null unique pk" json:"id" param:"listtask"`
@ -33,8 +35,8 @@ type ListTask struct {
CreatedBy User `xorm:"-" json:"createdBy" valid:"-"`
CRUDable `xorm:"-" json:"-"`
Rights `xorm:"-" json:"-"`
web.CRUDable `xorm:"-" json:"-"`
web.Rights `xorm:"-" json:"-"`
}
// TableName returns the table name for listtasks

View File

@ -17,6 +17,7 @@
package models
import (
"code.vikunja.io/web"
"github.com/imdario/mergo"
)
@ -34,7 +35,12 @@ import (
// @Failure 403 {object} models.HTTPError "The user does not have access to the list"
// @Failure 500 {object} models.Message "Internal error"
// @Router /lists/{id} [put]
func (i *ListTask) Create(doer *User) (err error) {
func (i *ListTask) Create(a web.Auth) (err error) {
doer, err := getUserWithError(a)
if err != nil {
return err
}
i.ID = 0
// Check if we have at least a text

View File

@ -18,10 +18,13 @@ package models
import (
"code.vikunja.io/api/pkg/log"
"code.vikunja.io/web"
)
// CanDelete checks if the user can delete an task
func (i *ListTask) CanDelete(doer *User) bool {
func (i *ListTask) CanDelete(a web.Auth) bool {
doer := getUserForRights(a)
// Get the task
lI, err := GetListTaskByID(i.ID)
if err != nil {
@ -36,7 +39,9 @@ func (i *ListTask) CanDelete(doer *User) bool {
}
// CanUpdate determines if a user has the right to update a list task
func (i *ListTask) CanUpdate(doer *User) bool {
func (i *ListTask) CanUpdate(a web.Auth) bool {
doer := getUserForRights(a)
// Get the task
lI, err := GetListTaskByID(i.ID)
if err != nil {
@ -51,7 +56,9 @@ func (i *ListTask) CanUpdate(doer *User) bool {
}
// CanCreate determines if a user has the right to create a list task
func (i *ListTask) CanCreate(doer *User) bool {
func (i *ListTask) CanCreate(a web.Auth) bool {
doer := getUserForRights(a)
// A user can create an task if he has write acces to its list
l := &List{ID: i.ListID}
l.ReadOne()

View File

@ -16,6 +16,8 @@
package models
import "code.vikunja.io/web"
// ListUser represents a list <-> user relation
type ListUser struct {
ID int64 `xorm:"int(11) autoincr not null unique pk" json:"id" param:"namespace"`
@ -26,8 +28,8 @@ type ListUser struct {
Created int64 `xorm:"created" json:"created"`
Updated int64 `xorm:"updated" json:"updated"`
CRUDable `xorm:"-" json:"-"`
Rights `xorm:"-" json:"-"`
web.CRUDable `xorm:"-" json:"-"`
web.Rights `xorm:"-" json:"-"`
}
// TableName is the table name for ListUser

View File

@ -16,6 +16,8 @@
package models
import "code.vikunja.io/web"
// Create creates a new list <-> user relation
// @Summary Add a user to a list
// @Description Gives a user access to a list.
@ -31,7 +33,7 @@ package models
// @Failure 403 {object} models.HTTPError "The user does not have access to the list"
// @Failure 500 {object} models.Message "Internal error"
// @Router /lists/{id}/users [put]
func (ul *ListUser) Create(u *User) (err error) {
func (ul *ListUser) Create(a web.Auth) (err error) {
// Check if the right is valid
if err := ul.Right.isValid(); err != nil {

View File

@ -16,6 +16,8 @@
package models
import "code.vikunja.io/web"
// ReadAll gets all users who have access to a list
// @Summary Get users on a list
// @Description Returns a list with all users which have access on a given list.
@ -30,7 +32,12 @@ package models
// @Failure 403 {object} models.HTTPError "No right to see the list."
// @Failure 500 {object} models.Message "Internal error"
// @Router /lists/{id}/users [get]
func (ul *ListUser) ReadAll(search string, u *User, page int) (interface{}, error) {
func (ul *ListUser) ReadAll(search string, a web.Auth, page int) (interface{}, error) {
u, err := getUserWithError(a)
if err != nil {
return nil, err
}
// Check if the user has access to the list
l := &List{ID: ul.ListID}
if err := l.GetSimpleByID(); err != nil {
@ -42,7 +49,7 @@ func (ul *ListUser) ReadAll(search string, u *User, page int) (interface{}, erro
// Get all users
all := []*UserWithRight{}
err := x.
err = x.
Join("INNER", "users_list", "user_id = users.id").
Where("users_list.list_id = ?", ul.ListID).
Limit(getLimitFromPageIndex(page)).

View File

@ -18,10 +18,13 @@ package models
import (
"code.vikunja.io/api/pkg/log"
"code.vikunja.io/web"
)
// CanCreate checks if the user can create a new user <-> list relation
func (lu *ListUser) CanCreate(doer *User) bool {
func (lu *ListUser) CanCreate(a web.Auth) bool {
doer := getUserForRights(a)
// Get the list and check if the user has write access on it
l := List{ID: lu.ListID}
if err := l.GetSimpleByID(); err != nil {
@ -32,7 +35,9 @@ func (lu *ListUser) CanCreate(doer *User) bool {
}
// CanDelete checks if the user can delete a user <-> list relation
func (lu *ListUser) CanDelete(doer *User) bool {
func (lu *ListUser) CanDelete(a web.Auth) bool {
doer := getUserForRights(a)
// Get the list and check if the user has write access on it
l := List{ID: lu.ListID}
if err := l.GetSimpleByID(); err != nil {
@ -43,7 +48,9 @@ func (lu *ListUser) CanDelete(doer *User) bool {
}
// CanUpdate checks if the user can update a user <-> list relation
func (lu *ListUser) CanUpdate(doer *User) bool {
func (lu *ListUser) CanUpdate(a web.Auth) bool {
doer := getUserForRights(a)
// Get the list and check if the user has write access on it
l := List{ID: lu.ListID}
if err := l.GetSimpleByID(); err != nil {

View File

@ -16,7 +16,10 @@
package models
import "time"
import (
"code.vikunja.io/web"
"time"
)
// Namespace holds informations about a namespace
type Namespace struct {
@ -30,8 +33,8 @@ type Namespace struct {
Created int64 `xorm:"created" json:"created"`
Updated int64 `xorm:"updated" json:"updated"`
CRUDable `xorm:"-" json:"-"`
Rights `xorm:"-" json:"-"`
web.CRUDable `xorm:"-" json:"-"`
web.Rights `xorm:"-" json:"-"`
}
// TableName makes beautiful table names
@ -99,7 +102,11 @@ type NamespaceWithLists struct {
// @Success 200 {array} models.NamespaceWithLists "The Namespaces."
// @Failure 500 {object} models.Message "Internal error"
// @Router /namespaces [get]
func (n *Namespace) ReadAll(search string, doer *User, page int) (interface{}, error) {
func (n *Namespace) ReadAll(search string, a web.Auth, page int) (interface{}, error) {
doer, err := getUserWithError(a)
if err != nil {
return nil, err
}
all := []*NamespaceWithLists{}
@ -117,7 +124,7 @@ func (n *Namespace) ReadAll(search string, doer *User, page int) (interface{}, e
[]*List{},
})
err := x.Select("namespaces.*").
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").

View File

@ -16,6 +16,8 @@
package models
import "code.vikunja.io/web"
// Create implements the creation method via the interface
// @Summary Creates a new namespace
// @Description Creates a new namespace.
@ -29,7 +31,12 @@ package models
// @Failure 403 {object} models.HTTPError "The user does not have access to the namespace"
// @Failure 500 {object} models.Message "Internal error"
// @Router /namespaces [put]
func (n *Namespace) Create(doer *User) (err error) {
func (n *Namespace) Create(a web.Auth) (err error) {
doer, err := getUserWithError(a)
if err != nil {
return err
}
// Check if we have at least a name
if n.Name == "" {
return ErrNamespaceNameCannotBeEmpty{NamespaceID: 0, UserID: doer.ID}

View File

@ -18,10 +18,13 @@ package models
import (
"code.vikunja.io/api/pkg/log"
"code.vikunja.io/web"
)
// IsAdmin returns true or false if the user is admin on that namespace or not
func (n *Namespace) IsAdmin(u *User) bool {
func (n *Namespace) IsAdmin(a web.Auth) bool {
u := getUserForRights(a)
// Owners always have admin rights
if u.ID == n.Owner.ID {
return true
@ -37,7 +40,9 @@ func (n *Namespace) IsAdmin(u *User) bool {
}
// CanWrite checks if a user has write access to a namespace
func (n *Namespace) CanWrite(u *User) bool {
func (n *Namespace) CanWrite(a web.Auth) bool {
u := getUserForRights(a)
// Admins always have write access
if n.IsAdmin(u) {
return true
@ -53,7 +58,9 @@ func (n *Namespace) CanWrite(u *User) bool {
}
// CanRead checks if a user has read access to that namespace
func (n *Namespace) CanRead(u *User) bool {
func (n *Namespace) CanRead(a web.Auth) bool {
u := getUserForRights(a)
// Admins always have read access
if n.IsAdmin(u) {
return true
@ -69,7 +76,9 @@ func (n *Namespace) CanRead(u *User) bool {
}
// CanUpdate checks if the user can update the namespace
func (n *Namespace) CanUpdate(u *User) bool {
func (n *Namespace) CanUpdate(a web.Auth) bool {
u := getUserForRights(a)
nn, err := GetNamespaceByID(n.ID)
if err != nil {
log.Log.Error("Error occurred during CanUpdate for Namespace: %s", err)
@ -79,7 +88,9 @@ func (n *Namespace) CanUpdate(u *User) bool {
}
// CanDelete checks if the user can delete a namespace
func (n *Namespace) CanDelete(u *User) bool {
func (n *Namespace) CanDelete(a web.Auth) bool {
u := getUserForRights(a)
nn, err := GetNamespaceByID(n.ID)
if err != nil {
log.Log.Error("Error occurred during CanDelete for Namespace: %s", err)
@ -89,7 +100,7 @@ func (n *Namespace) CanDelete(u *User) bool {
}
// CanCreate checks if the user can create a new namespace
func (n *Namespace) CanCreate(u *User) bool {
func (n *Namespace) CanCreate(a web.Auth) bool {
// This is currently a dummy function, later on we could imagine global limits etc.
return true
}
@ -99,9 +110,9 @@ func (n *Namespace) checkTeamRights(u *User, r TeamRight) bool {
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, u.ID, r, u.ID).
Where("namespaces.id = ? AND ("+
"(team_members.user_id = ? AND team_namespaces.right = ?) "+
"OR namespaces.owner_id = ?)", n.ID, u.ID, r, u.ID).
Get(&Namespace{})
if err != nil {
log.Log.Error("Error occurred during checkTeamRights for Namespace: %s, TeamRight: %d", err, r)
@ -116,8 +127,8 @@ func (n *Namespace) checkUserRights(u *User, r UserRight) bool {
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, u.ID, u.ID, r).
"(users_namespace.user_id = ? AND users_namespace.right = ?) "+
"OR namespaces.owner_id = ?)", n.ID, u.ID, r, u.ID).
Get(&Namespace{})
if err != nil {
log.Log.Error("Error occurred during checkUserRights for Namespace: %s, UserRight: %d", err, r)

View File

@ -16,6 +16,8 @@
package models
import "code.vikunja.io/web"
// NamespaceUser represents a namespace <-> user relation
type NamespaceUser struct {
ID int64 `xorm:"int(11) autoincr not null unique pk" json:"id" param:"namespace"`
@ -26,8 +28,8 @@ type NamespaceUser struct {
Created int64 `xorm:"created" json:"created"`
Updated int64 `xorm:"updated" json:"updated"`
CRUDable `xorm:"-" json:"-"`
Rights `xorm:"-" json:"-"`
web.CRUDable `xorm:"-" json:"-"`
web.Rights `xorm:"-" json:"-"`
}
// TableName is the table name for NamespaceUser

View File

@ -16,6 +16,8 @@
package models
import "code.vikunja.io/web"
// Create creates a new namespace <-> user relation
// @Summary Add a user to a namespace
// @Description Gives a user access to a namespace.
@ -31,8 +33,7 @@ package models
// @Failure 403 {object} models.HTTPError "The user does not have access to the namespace"
// @Failure 500 {object} models.Message "Internal error"
// @Router /namespaces/{id}/users [put]
func (un *NamespaceUser) Create(u *User) (err error) {
func (un *NamespaceUser) Create(a web.Auth) (err error) {
// Reset the id
un.ID = 0

View File

@ -16,6 +16,8 @@
package models
import "code.vikunja.io/web"
// ReadAll gets all users who have access to a namespace
// @Summary Get users on a namespace
// @Description Returns a namespace with all users which have access on a given namespace.
@ -30,7 +32,12 @@ package models
// @Failure 403 {object} models.HTTPError "No right to see the namespace."
// @Failure 500 {object} models.Message "Internal error"
// @Router /namespaces/{id}/users [get]
func (un *NamespaceUser) ReadAll(search string, u *User, page int) (interface{}, error) {
func (un *NamespaceUser) ReadAll(search string, a web.Auth, page int) (interface{}, error) {
u, err := getUserWithError(a)
if err != nil {
return nil, err
}
// Check if the user has access to the namespace
l, err := GetNamespaceByID(un.NamespaceID)
if err != nil {

View File

@ -18,10 +18,13 @@ package models
import (
"code.vikunja.io/api/pkg/log"
"code.vikunja.io/web"
)
// CanCreate checks if the user can create a new user <-> namespace relation
func (nu *NamespaceUser) CanCreate(doer *User) bool {
func (nu *NamespaceUser) CanCreate(a web.Auth) bool {
doer := getUserForRights(a)
// Get the namespace and check if the user has write access on it
n, err := GetNamespaceByID(nu.NamespaceID)
if err != nil {
@ -32,7 +35,9 @@ func (nu *NamespaceUser) CanCreate(doer *User) bool {
}
// CanDelete checks if the user can delete a user <-> namespace relation
func (nu *NamespaceUser) CanDelete(doer *User) bool {
func (nu *NamespaceUser) CanDelete(a web.Auth) bool {
doer := getUserForRights(a)
// Get the namespace and check if the user has write access on it
n, err := GetNamespaceByID(nu.NamespaceID)
if err != nil {
@ -43,7 +48,9 @@ func (nu *NamespaceUser) CanDelete(doer *User) bool {
}
// CanUpdate checks if the user can update a user <-> namespace relation
func (nu *NamespaceUser) CanUpdate(doer *User) bool {
func (nu *NamespaceUser) CanUpdate(a web.Auth) bool {
doer := getUserForRights(a)
// Get the namespace and check if the user has write access on it
n, err := GetNamespaceByID(nu.NamespaceID)
if err != nil {

View File

@ -1,27 +0,0 @@
// Vikunja is a todo-list application to facilitate your life.
// Copyright 2018 Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
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
}

View File

@ -16,6 +16,8 @@
package models
import "code.vikunja.io/web"
// 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"`
@ -26,8 +28,8 @@ type TeamList struct {
Created int64 `xorm:"created" json:"created"`
Updated int64 `xorm:"updated" json:"updated"`
CRUDable `xorm:"-" json:"-"`
Rights `xorm:"-" json:"-"`
web.CRUDable `xorm:"-" json:"-"`
web.Rights `xorm:"-" json:"-"`
}
// TableName makes beautiful table names

View File

@ -16,6 +16,8 @@
package models
import "code.vikunja.io/web"
// Create creates a new team <-> list relation
// @Summary Add a team to a list
// @Description Gives a team access to a list.
@ -31,7 +33,7 @@ package models
// @Failure 403 {object} models.HTTPError "The user does not have access to the list"
// @Failure 500 {object} models.Message "Internal error"
// @Router /lists/{id}/teams [put]
func (tl *TeamList) Create(doer *User) (err error) {
func (tl *TeamList) Create(a web.Auth) (err error) {
// Check if the rights are valid
if err = tl.Right.isValid(); err != nil {

View File

@ -16,6 +16,8 @@
package models
import "code.vikunja.io/web"
// ReadAll implements the method to read all teams of a list
// @Summary Get teams on a list
// @Description Returns a list with all teams which have access on a given list.
@ -30,7 +32,12 @@ package models
// @Failure 403 {object} models.HTTPError "No right to see the list."
// @Failure 500 {object} models.Message "Internal error"
// @Router /lists/{id}/teams [get]
func (tl *TeamList) ReadAll(search string, u *User, page int) (interface{}, error) {
func (tl *TeamList) ReadAll(search string, a web.Auth, page int) (interface{}, error) {
u, err := getUserWithError(a)
if err != nil {
return nil, err
}
// Check if the user can read the namespace
l := &List{ID: tl.ListID}
if err := l.GetSimpleByID(); err != nil {
@ -42,7 +49,7 @@ func (tl *TeamList) ReadAll(search string, u *User, page int) (interface{}, erro
// Get the teams
all := []*TeamWithRight{}
err := x.
err = x.
Table("teams").
Join("INNER", "team_list", "team_id = teams.id").
Where("team_list.list_id = ?", tl.ListID).

View File

@ -18,10 +18,13 @@ package models
import (
"code.vikunja.io/api/pkg/log"
"code.vikunja.io/web"
)
// CanCreate checks if the user can create a team <-> list relation
func (tl *TeamList) CanCreate(u *User) bool {
func (tl *TeamList) CanCreate(a web.Auth) bool {
u := getUserForRights(a)
l := List{ID: tl.ListID}
if err := l.GetSimpleByID(); err != nil {
log.Log.Error("Error occurred during CanCreate for TeamList: %s", err)
@ -31,7 +34,9 @@ func (tl *TeamList) CanCreate(u *User) bool {
}
// CanDelete checks if the user can delete a team <-> list relation
func (tl *TeamList) CanDelete(user *User) bool {
func (tl *TeamList) CanDelete(a web.Auth) bool {
user := getUserForRights(a)
l := List{ID: tl.ListID}
if err := l.GetSimpleByID(); err != nil {
log.Log.Error("Error occurred during CanDelete for TeamList: %s", err)
@ -41,7 +46,9 @@ func (tl *TeamList) CanDelete(user *User) bool {
}
// CanUpdate checks if the user can update a team <-> list relation
func (tl *TeamList) CanUpdate(user *User) bool {
func (tl *TeamList) CanUpdate(a web.Auth) bool {
user := getUserForRights(a)
l := List{ID: tl.ListID}
if err := l.GetSimpleByID(); err != nil {
log.Log.Error("Error occurred during CanUpdate for TeamList: %s", err)

View File

@ -16,6 +16,8 @@
package models
import "code.vikunja.io/web"
// Create implements the create method to assign a user to a team
// @Summary Add a user to a team
// @Description Add a user to a team.
@ -30,7 +32,8 @@ package models
// @Failure 403 {object} models.HTTPError "The user does not have access to the team"
// @Failure 500 {object} models.Message "Internal error"
// @Router /teams/{id}/members [put]
func (tm *TeamMember) Create(doer *User) (err error) {
func (tm *TeamMember) Create(a web.Auth) (err error) {
// Check if the team extst
_, err = GetTeamByID(tm.TeamID)
if err != nil {

View File

@ -18,20 +18,23 @@ package models
import (
"code.vikunja.io/api/pkg/log"
"code.vikunja.io/web"
)
// CanCreate checks if the user can add a new tem member
func (tm *TeamMember) CanCreate(u *User) bool {
return tm.IsAdmin(u)
func (tm *TeamMember) CanCreate(a web.Auth) bool {
return tm.IsAdmin(a)
}
// CanDelete checks if the user can delete a new team member
func (tm *TeamMember) CanDelete(u *User) bool {
return tm.IsAdmin(u)
func (tm *TeamMember) CanDelete(a web.Auth) bool {
return tm.IsAdmin(a)
}
// IsAdmin checks if the user is team admin
func (tm *TeamMember) IsAdmin(u *User) bool {
func (tm *TeamMember) IsAdmin(a web.Auth) bool {
u := getUserForRights(a)
// 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 = ?", u.ID, tm.TeamID, true).
Get(&TeamMember{})

View File

@ -16,6 +16,8 @@
package models
import "code.vikunja.io/web"
// 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"`
@ -26,8 +28,8 @@ type TeamNamespace struct {
Created int64 `xorm:"created" json:"created"`
Updated int64 `xorm:"updated" json:"updated"`
CRUDable `xorm:"-" json:"-"`
Rights `xorm:"-" json:"-"`
web.CRUDable `xorm:"-" json:"-"`
web.Rights `xorm:"-" json:"-"`
}
// TableName makes beautiful table names

View File

@ -16,6 +16,8 @@
package models
import "code.vikunja.io/web"
// Create creates a new team <-> namespace relation
// @Summary Add a team to a namespace
// @Description Gives a team access to a namespace.
@ -31,7 +33,7 @@ package models
// @Failure 403 {object} models.HTTPError "The team does not have access to the namespace"
// @Failure 500 {object} models.Message "Internal error"
// @Router /namespaces/{id}/teams [put]
func (tn *TeamNamespace) Create(doer *User) (err error) {
func (tn *TeamNamespace) Create(a web.Auth) (err error) {
// Check if the rights are valid
if err = tn.Right.isValid(); err != nil {

View File

@ -16,6 +16,8 @@
package models
import "code.vikunja.io/web"
// ReadAll implements the method to read all teams of a namespace
// @Summary Get teams on a namespace
// @Description Returns a namespace with all teams which have access on a given namespace.
@ -30,7 +32,12 @@ package models
// @Failure 403 {object} models.HTTPError "No right to see the namespace."
// @Failure 500 {object} models.Message "Internal error"
// @Router /namespaces/{id}/teams [get]
func (tn *TeamNamespace) ReadAll(search string, user *User, page int) (interface{}, error) {
func (tn *TeamNamespace) ReadAll(search string, a web.Auth, page int) (interface{}, error) {
user, err := getUserWithError(a)
if err != nil {
return nil, err
}
// Check if the user can read the namespace
n, err := GetNamespaceByID(tn.NamespaceID)
if err != nil {

View File

@ -18,10 +18,13 @@ package models
import (
"code.vikunja.io/api/pkg/log"
"code.vikunja.io/web"
)
// CanCreate checks if one can create a new team <-> namespace relation
func (tn *TeamNamespace) CanCreate(user *User) bool {
func (tn *TeamNamespace) CanCreate(a web.Auth) bool {
user := getUserForRights(a)
n, err := GetNamespaceByID(tn.NamespaceID)
if err != nil {
log.Log.Error("Error occurred during CanCreate for TeamNamespace: %s", err)
@ -31,7 +34,9 @@ func (tn *TeamNamespace) CanCreate(user *User) bool {
}
// 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 {
func (tn *TeamNamespace) CanDelete(a web.Auth) bool {
user := getUserForRights(a)
n, err := GetNamespaceByID(tn.NamespaceID)
if err != nil {
log.Log.Error("Error occurred during CanDelete for TeamNamespace: %s", err)
@ -41,7 +46,9 @@ func (tn *TeamNamespace) CanDelete(user *User) bool {
}
// CanUpdate checks if a user can update a team from a Only namespace admins can do that.
func (tn *TeamNamespace) CanUpdate(user *User) bool {
func (tn *TeamNamespace) CanUpdate(a web.Auth) bool {
user := getUserForRights(a)
n, err := GetNamespaceByID(tn.NamespaceID)
if err != nil {
log.Log.Error("Error occurred during CanUpdate for TeamNamespace: %s", err)

View File

@ -16,6 +16,8 @@
package models
import "code.vikunja.io/web"
// Team holds a team object
type Team struct {
ID int64 `xorm:"int(11) autoincr not null unique pk" json:"id" param:"team"`
@ -29,8 +31,8 @@ type Team struct {
Created int64 `xorm:"created" json:"created"`
Updated int64 `xorm:"updated" json:"updated"`
CRUDable `xorm:"-" json:"-"`
Rights `xorm:"-" json:"-"`
web.CRUDable `xorm:"-" json:"-"`
web.Rights `xorm:"-" json:"-"`
}
// TableName makes beautiful table names
@ -61,8 +63,8 @@ type TeamMember struct {
Created int64 `xorm:"created" json:"created"`
Updated int64 `xorm:"updated" json:"updated"`
CRUDable `xorm:"-" json:"-"`
Rights `xorm:"-" json:"-"`
web.CRUDable `xorm:"-" json:"-"`
web.Rights `xorm:"-" json:"-"`
}
// TableName makes beautiful table names
@ -122,7 +124,12 @@ func (t *Team) ReadOne() (err error) {
// @Success 200 {array} models.Team "The teams."
// @Failure 500 {object} models.Message "Internal error"
// @Router /teams [get]
func (t *Team) ReadAll(search string, user *User, page int) (teams interface{}, err error) {
func (t *Team) ReadAll(search string, a web.Auth, page int) (interface{}, error) {
user, err := getUserWithError(a)
if err != nil {
return nil, err
}
all := []*Team{}
err = x.Select("teams.*").
Table("teams").

View File

@ -16,6 +16,8 @@
package models
import "code.vikunja.io/web"
// Create is the handler to create a team
// @Summary Creates a new team
// @Description Creates a new team in a given namespace. The user needs write-access to the namespace.
@ -28,7 +30,12 @@ package models
// @Failure 400 {object} models.HTTPError "Invalid team object provided."
// @Failure 500 {object} models.Message "Internal error"
// @Router /teams [put]
func (t *Team) Create(doer *User) (err error) {
func (t *Team) Create(a web.Auth) (err error) {
doer, err := getUserWithError(a)
if err != nil {
return err
}
// Check if we have a name
if t.Name == "" {
return ErrTeamNameCannotBeEmpty{}

View File

@ -18,16 +18,18 @@ package models
import (
"code.vikunja.io/api/pkg/log"
"code.vikunja.io/web"
)
// CanCreate checks if the user can create a new team
func (t *Team) CanCreate(u *User) bool {
func (t *Team) CanCreate(a web.Auth) 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 {
func (t *Team) CanUpdate(a web.Auth) bool {
u := getUserForRights(a)
// Check if the current user is in the team and has admin rights in it
exists, err := x.Where("team_id = ?", t.ID).
@ -43,12 +45,14 @@ func (t *Team) CanUpdate(u *User) bool {
}
// CanDelete checks if a user can delete a team
func (t *Team) CanDelete(u *User) bool {
return t.IsAdmin(u)
func (t *Team) CanDelete(a web.Auth) bool {
return t.IsAdmin(a)
}
// IsAdmin returns true when the user is admin of a team
func (t *Team) IsAdmin(u *User) bool {
func (t *Team) IsAdmin(a web.Auth) bool {
u := getUserForRights(a)
exists, err := x.Where("team_id = ?", t.ID).
And("user_id = ?", u.ID).
And("admin = ?", true).
@ -61,7 +65,9 @@ func (t *Team) IsAdmin(u *User) bool {
}
// CanRead returns true if the user has read access to the team
func (t *Team) CanRead(user *User) bool {
func (t *Team) CanRead(a web.Auth) bool {
user := getUserForRights(a)
// Check if the user is in the team
exists, err := x.Where("team_id = ?", t.ID).
And("user_id = ?", user.ID).

View File

@ -17,9 +17,13 @@
package models
import (
"code.vikunja.io/api/pkg/log"
"code.vikunja.io/web"
"fmt"
"github.com/dgrijalva/jwt-go"
"github.com/labstack/echo"
"golang.org/x/crypto/bcrypt"
"reflect"
)
// UserLogin Object to recive user credentials in JSON format
@ -41,13 +45,34 @@ type User struct {
Created int64 `xorm:"created" json:"created"`
Updated int64 `xorm:"updated" json:"updated"`
web.Auth `xorm:"-" json:"-"`
}
// AuthDummy implements the auth of the crud handler
func (User) AuthDummy() {}
// TableName returns the table name for users
func (User) TableName() string {
return "users"
}
func getUserForRights(a web.Auth) *User {
u, err := getUserWithError(a)
if err != nil {
log.Log.Error(err.Error())
}
return u
}
func getUserWithError(a web.Auth) (*User, error) {
u, is := a.(*User)
if !is {
return &User{}, fmt.Errorf("user is not user element, is %s", reflect.TypeOf(a))
}
return u, nil
}
// APIUserPassword represents a user object without timestamps and a json password field.
type APIUserPassword struct {
ID int64 `json:"id"`
@ -119,14 +144,14 @@ func CheckUserCredentials(u *UserLogin) (User, error) {
}
// GetCurrentUser returns the current user based on its jwt token
func GetCurrentUser(c echo.Context) (user User, err error) {
func GetCurrentUser(c echo.Context) (user *User, err error) {
jwtinf := c.Get("user").(*jwt.Token)
claims := jwtinf.Claims.(jwt.MapClaims)
userID, ok := claims["id"].(float64)
if !ok {
return user, ErrCouldNotGetUserID{}
}
user = User{
user = &User{
ID: int64(userID),
Email: claims["email"].(string),
Username: claims["username"].(string),