1
0

Use the username instead of a user when adding a user to a team or giving it rights (#76)

This commit is contained in:
konrad
2019-05-25 09:47:16 +00:00
committed by Gitea
parent 3fffcbd986
commit 50d1f29125
19 changed files with 121 additions and 85 deletions

View File

@ -22,8 +22,10 @@ import "code.vikunja.io/web"
type ListUser struct {
// The unique, numeric id of this list <-> user relation.
ID int64 `xorm:"int(11) autoincr not null unique pk" json:"id" param:"namespace"`
// The user id.
UserID int64 `xorm:"int(11) not null INDEX" json:"userID" param:"user"`
// The username.
Username string `xorm:"-" json:"username" param:"user"`
// Used internally to reference the user
UserID int64 `xorm:"int(11) not null INDEX" json:"-"`
// The list id.
ListID int64 `xorm:"int(11) not null INDEX" json:"-" param:"list"`
// The right this user has. 0 = Read only, 1 = Read & Write, 2 = Admin. See the docs for more details.

View File

@ -47,9 +47,11 @@ func (lu *ListUser) Create(a web.Auth) (err error) {
}
// Check if the user exists
if _, err = GetUserByID(lu.UserID); err != nil {
user, err := GetUserByUsername(lu.Username)
if err != nil {
return err
}
lu.UserID = user.ID
// Check if the user already has access or is owner of that list
// We explicitly DONT check for teams here

View File

@ -34,10 +34,11 @@ import _ "code.vikunja.io/web" // For swaggerdocs generation
func (lu *ListUser) Delete() (err error) {
// Check if the user exists
_, err = GetUserByID(lu.UserID)
user, err := GetUserByUsername(lu.Username)
if err != nil {
return
}
lu.UserID = user.ID
// Check if the user has access to the list
has, err := x.Where("user_id = ? AND list_id = ?", lu.UserID, lu.ListID).

View File

@ -29,6 +29,7 @@ func TestListUser_Create(t *testing.T) {
type fields struct {
ID int64
UserID int64
Username string
ListID int64
Right Right
Created int64
@ -49,15 +50,15 @@ func TestListUser_Create(t *testing.T) {
{
name: "ListUsers Create normally",
fields: fields{
UserID: 1,
ListID: 2,
Username: "user1",
ListID: 2,
},
},
{
name: "ListUsers Create for duplicate",
fields: fields{
UserID: 1,
ListID: 2,
Username: "user1",
ListID: 2,
},
wantErr: true,
errType: IsErrUserAlreadyHasAccess,
@ -65,9 +66,9 @@ func TestListUser_Create(t *testing.T) {
{
name: "ListUsers Create with invalid right",
fields: fields{
UserID: 1,
ListID: 2,
Right: 500,
Username: "user1",
ListID: 2,
Right: 500,
},
wantErr: true,
errType: IsErrInvalidRight,
@ -75,8 +76,8 @@ func TestListUser_Create(t *testing.T) {
{
name: "ListUsers Create with inexisting list",
fields: fields{
UserID: 1,
ListID: 2000,
Username: "user1",
ListID: 2000,
},
wantErr: true,
errType: IsErrListDoesNotExist,
@ -84,8 +85,8 @@ func TestListUser_Create(t *testing.T) {
{
name: "ListUsers Create with inexisting user",
fields: fields{
UserID: 500,
ListID: 2,
Username: "user500",
ListID: 2,
},
wantErr: true,
errType: IsErrUserDoesNotExist,
@ -93,8 +94,8 @@ func TestListUser_Create(t *testing.T) {
{
name: "ListUsers Create with the owner as shared user",
fields: fields{
UserID: 1,
ListID: 1,
Username: "user1",
ListID: 1,
},
wantErr: true,
errType: IsErrUserAlreadyHasAccess,
@ -105,6 +106,7 @@ func TestListUser_Create(t *testing.T) {
ul := &ListUser{
ID: tt.fields.ID,
UserID: tt.fields.UserID,
Username: tt.fields.Username,
ListID: tt.fields.ListID,
Right: tt.fields.Right,
Created: tt.fields.Created,
@ -291,7 +293,7 @@ func TestListUser_Update(t *testing.T) {
func TestListUser_Delete(t *testing.T) {
type fields struct {
ID int64
UserID int64
Username string
ListID int64
Right Right
Created int64
@ -308,8 +310,8 @@ func TestListUser_Delete(t *testing.T) {
{
name: "Try deleting some unexistant user",
fields: fields{
UserID: 1000,
ListID: 2,
Username: "user1000",
ListID: 2,
},
wantErr: true,
errType: IsErrUserDoesNotExist,
@ -317,8 +319,8 @@ func TestListUser_Delete(t *testing.T) {
{
name: "Try deleting a user which does not has access but exists",
fields: fields{
UserID: 1,
ListID: 4,
Username: "user1",
ListID: 4,
},
wantErr: true,
errType: IsErrUserDoesNotHaveAccessToList,
@ -326,8 +328,8 @@ func TestListUser_Delete(t *testing.T) {
{
name: "Try deleting normally",
fields: fields{
UserID: 1,
ListID: 3,
Username: "user1",
ListID: 3,
},
},
}
@ -335,7 +337,7 @@ func TestListUser_Delete(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
lu := &ListUser{
ID: tt.fields.ID,
UserID: tt.fields.UserID,
Username: tt.fields.Username,
ListID: tt.fields.ListID,
Right: tt.fields.Right,
Created: tt.fields.Created,

View File

@ -22,8 +22,9 @@ import "code.vikunja.io/web"
type NamespaceUser struct {
// The unique, numeric id of this namespace <-> user relation.
ID int64 `xorm:"int(11) autoincr not null unique pk" json:"id" param:"namespace"`
// The user id.
UserID int64 `xorm:"int(11) not null INDEX" json:"userID" param:"user"`
// The username.
Username string `xorm:"-" json:"userID" param:"user"`
UserID int64 `xorm:"int(11) not null INDEX" json:"-"`
// The namespace id
NamespaceID int64 `xorm:"int(11) not null INDEX" json:"-" param:"namespace"`
// The right this user has. 0 = Read only, 1 = Read & Write, 2 = Admin. See the docs for more details.

View File

@ -49,9 +49,11 @@ func (nu *NamespaceUser) Create(a web.Auth) (err error) {
}
// Check if the user exists
if _, err = GetUserByID(nu.UserID); err != nil {
user, err := GetUserByUsername(nu.Username)
if err != nil {
return err
}
nu.UserID = user.ID
// Check if the user already has access or is owner of that namespace
// We explicitly DO NOT check for teams here

View File

@ -34,10 +34,11 @@ import _ "code.vikunja.io/web" // For swaggerdocs generation
func (nu *NamespaceUser) Delete() (err error) {
// Check if the user exists
_, err = GetUserByID(nu.UserID)
user, err := GetUserByUsername(nu.Username)
if err != nil {
return
}
nu.UserID = user.ID
// Check if the user has access to the namespace
has, err := x.Where("user_id = ? AND namespace_id = ?", nu.UserID, nu.NamespaceID).

View File

@ -29,7 +29,7 @@ import (
func TestNamespaceUser_Create(t *testing.T) {
type fields struct {
ID int64
UserID int64
Username string
NamespaceID int64
Right Right
Created int64
@ -50,14 +50,14 @@ func TestNamespaceUser_Create(t *testing.T) {
{
name: "NamespaceUsers Create normally",
fields: fields{
UserID: 1,
Username: "user1",
NamespaceID: 2,
},
},
{
name: "NamespaceUsers Create for duplicate",
fields: fields{
UserID: 1,
Username: "user1",
NamespaceID: 2,
},
wantErr: true,
@ -66,7 +66,7 @@ func TestNamespaceUser_Create(t *testing.T) {
{
name: "NamespaceUsers Create with invalid right",
fields: fields{
UserID: 1,
Username: "user1",
NamespaceID: 2,
Right: 500,
},
@ -76,7 +76,7 @@ func TestNamespaceUser_Create(t *testing.T) {
{
name: "NamespaceUsers Create with inexisting list",
fields: fields{
UserID: 1,
Username: "user1",
NamespaceID: 2000,
},
wantErr: true,
@ -85,7 +85,7 @@ func TestNamespaceUser_Create(t *testing.T) {
{
name: "NamespaceUsers Create with inexisting user",
fields: fields{
UserID: 500,
Username: "user500",
NamespaceID: 2,
},
wantErr: true,
@ -94,7 +94,7 @@ func TestNamespaceUser_Create(t *testing.T) {
{
name: "NamespaceUsers Create with the owner as shared user",
fields: fields{
UserID: 1,
Username: "user1",
NamespaceID: 1,
},
wantErr: true,
@ -105,7 +105,7 @@ func TestNamespaceUser_Create(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
un := &NamespaceUser{
ID: tt.fields.ID,
UserID: tt.fields.UserID,
Username: tt.fields.Username,
NamespaceID: tt.fields.NamespaceID,
Right: tt.fields.Right,
Created: tt.fields.Created,
@ -293,7 +293,7 @@ func TestNamespaceUser_Update(t *testing.T) {
func TestNamespaceUser_Delete(t *testing.T) {
type fields struct {
ID int64
UserID int64
Username string
NamespaceID int64
Right Right
Created int64
@ -310,7 +310,7 @@ func TestNamespaceUser_Delete(t *testing.T) {
{
name: "Try deleting some unexistant user",
fields: fields{
UserID: 1000,
Username: "user1000",
NamespaceID: 2,
},
wantErr: true,
@ -319,7 +319,7 @@ func TestNamespaceUser_Delete(t *testing.T) {
{
name: "Try deleting a user which does not has access but exists",
fields: fields{
UserID: 1,
Username: "user1",
NamespaceID: 4,
},
wantErr: true,
@ -328,7 +328,7 @@ func TestNamespaceUser_Delete(t *testing.T) {
{
name: "Try deleting normally",
fields: fields{
UserID: 1,
Username: "user1",
NamespaceID: 3,
},
},
@ -337,7 +337,7 @@ func TestNamespaceUser_Delete(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
nu := &NamespaceUser{
ID: tt.fields.ID,
UserID: tt.fields.UserID,
Username: tt.fields.Username,
NamespaceID: tt.fields.NamespaceID,
Right: tt.fields.Right,
Created: tt.fields.Created,

View File

@ -41,10 +41,11 @@ func (tm *TeamMember) Create(a web.Auth) (err error) {
}
// Check if the user exists
_, err = GetUserByID(tm.UserID)
user, err := GetUserByUsername(tm.Username)
if err != nil {
return
}
tm.UserID = user.ID
// Check if that user is already part of the team
exists, err := x.Where("team_id = ? AND user_id = ?", tm.TeamID, tm.UserID).

View File

@ -37,6 +37,13 @@ func (tm *TeamMember) Delete() (err error) {
return ErrCannotDeleteLastTeamMember{tm.TeamID, tm.UserID}
}
// Find the numeric user id
user, err := GetUserByUsername(tm.Username)
if err != nil {
return
}
tm.UserID = user.ID
_, err = x.Where("team_id = ? AND user_id = ?", tm.TeamID, tm.UserID).Delete(&TeamMember{})
return
}

View File

@ -25,8 +25,8 @@ func TestTeamMember_Create(t *testing.T) {
// Dummy team member
dummyteammember := TeamMember{
TeamID: 1,
UserID: 3,
TeamID: 1,
Username: "user3",
}
// Doer
@ -57,24 +57,24 @@ func TestTeamMember_Create(t *testing.T) {
assert.NoError(t, err)
// Delete the other one
tm := TeamMember{TeamID: 1, UserID: 2}
tm := TeamMember{TeamID: 1, Username: "user2"}
err = tm.Delete()
assert.NoError(t, err)
// Try deleting the last one
tm = TeamMember{TeamID: 1, UserID: 1}
tm = TeamMember{TeamID: 1, Username: "user1"}
err = tm.Delete()
assert.Error(t, err)
assert.True(t, IsErrCannotDeleteLastTeamMember(err))
// Try inserting a user which does not exist
dummyteammember.UserID = 9484
dummyteammember.Username = "user9484"
err = dummyteammember.Create(&doer)
assert.Error(t, err)
assert.True(t, IsErrUserDoesNotExist(err))
// Try adding a user to a team which does not exist
tm = TeamMember{TeamID: 94824, UserID: 1}
tm = TeamMember{TeamID: 94824, Username: "user1"}
err = tm.Create(&doer)
assert.Error(t, err)
assert.True(t, IsErrTeamDoesNotExist(err))

View File

@ -66,8 +66,10 @@ type TeamMember struct {
ID int64 `xorm:"int(11) autoincr not null unique pk" json:"id"`
// The team id.
TeamID int64 `xorm:"int(11) not null INDEX" json:"-" param:"team"`
// The id of the member.
UserID int64 `xorm:"int(11) not null INDEX" json:"userID" param:"user"`
// The username of the member. We use this to prevent automated user id entering.
Username string `xorm:"-" json:"username" param:"user"`
// Used under the hood to manage team members
UserID int64 `xorm:"int(11) not null INDEX" json:"-"`
// Whether or not the member is an admin of the team. See the docs for more about what a team admin can do
Admin bool `xorm:"tinyint(1) INDEX null" json:"admin"`

View File

@ -53,7 +53,7 @@ func (t *Team) Create(a web.Auth) (err error) {
}
// Insert the current user as member and admin
tm := TeamMember{TeamID: t.ID, UserID: doer.ID, Admin: true}
tm := TeamMember{TeamID: t.ID, Username: doer.Username, Admin: true}
if err = tm.Create(doer); err != nil {
return err
}

View File

@ -119,6 +119,15 @@ func GetUserByID(id int64) (user User, err error) {
return GetUser(User{ID: id})
}
// GetUserByUsername gets a user from its user name. This is an extra function to be able to add an extra error check.
func GetUserByUsername(username string) (user User, err error) {
if username == "" {
return User{}, ErrUserDoesNotExist{}
}
return GetUser(User{Username: username})
}
// GetUser gets a user object
func GetUser(user User) (userOut User, err error) {
userOut = user
@ -139,7 +148,7 @@ func CheckUserCredentials(u *UserLogin) (User, error) {
}
// Check if the user exists
user, err := GetUser(User{Username: u.Username})
user, err := GetUserByUsername(u.Username)
if err != nil {
// hashing the password takes a long time, so we hash something to not make it clear if the username was wrong
bcrypt.GenerateFromPassword([]byte(u.Username), 14)

View File

@ -36,7 +36,7 @@ func CreateUser(user User) (newUser User, err error) {
// Check if the user already existst with that username
exists := true
existingUser, err := GetUser(User{Username: newUser.Username})
existingUser, err := GetUserByUsername(newUser.Username)
if err != nil {
if IsErrUserDoesNotExist(err) {
exists = false