Added http endpoint to list all users on a list (#87)
This commit is contained in:
@ -134,3 +134,21 @@
|
||||
namespace_id: 12
|
||||
updated: 0
|
||||
created: 0
|
||||
# This list is owned by user 7, and several other users have access to it via different methods.
|
||||
# It is used to test the listUsers method.
|
||||
-
|
||||
id: 18
|
||||
title: Test18
|
||||
description: Lorem Ipsum
|
||||
owner_id: 7
|
||||
namespace_id: 13
|
||||
updated: 0
|
||||
created: 0
|
||||
-
|
||||
id: 19
|
||||
title: Test19
|
||||
description: Lorem Ipsum
|
||||
owner_id: 7
|
||||
namespace_id: 14
|
||||
updated: 0
|
||||
created: 0
|
||||
|
@ -58,3 +58,15 @@
|
||||
owner_id: 6
|
||||
updated: 0
|
||||
created: 0
|
||||
- id: 13
|
||||
name: testnamespace13
|
||||
description: Lorem Ipsum
|
||||
owner_id: 7
|
||||
updated: 0
|
||||
created: 0
|
||||
- id: 14
|
||||
name: testnamespace14
|
||||
description: Lorem Ipsum
|
||||
owner_id: 7
|
||||
updated: 0
|
||||
created: 0
|
||||
|
@ -4,7 +4,6 @@
|
||||
right: 0
|
||||
updated: 0
|
||||
created: 0
|
||||
|
||||
# This team has read only access on list 6
|
||||
- id: 2
|
||||
team_id: 2
|
||||
@ -12,7 +11,6 @@
|
||||
right: 0
|
||||
updated: 0
|
||||
created: 0
|
||||
|
||||
# This team has write access on list 7
|
||||
- id: 3
|
||||
team_id: 3
|
||||
@ -20,11 +18,31 @@
|
||||
right: 1
|
||||
updated: 0
|
||||
created: 0
|
||||
|
||||
# This team has admin access on list 8
|
||||
- id: 4
|
||||
team_id: 4
|
||||
list_id: 8
|
||||
right: 2
|
||||
updated: 0
|
||||
created: 0
|
||||
# Readonly acces on list 19
|
||||
- id: 5
|
||||
team_id: 8
|
||||
list_id: 19
|
||||
right: 2
|
||||
updated: 0
|
||||
created: 0
|
||||
# Write acces on list 19
|
||||
- id: 6
|
||||
team_id: 9
|
||||
list_id: 19
|
||||
right: 1
|
||||
updated: 0
|
||||
created: 0
|
||||
# Admin acces on list 19
|
||||
- id: 7
|
||||
team_id: 10
|
||||
list_id: 19
|
||||
right: 2
|
||||
updated: 0
|
||||
created: 0
|
@ -31,3 +31,27 @@
|
||||
team_id: 7
|
||||
user_id: 1
|
||||
created: 0
|
||||
-
|
||||
team_id: 8
|
||||
user_id: 1
|
||||
created: 0
|
||||
-
|
||||
team_id: 9
|
||||
user_id: 2
|
||||
created: 0
|
||||
-
|
||||
team_id: 10
|
||||
user_id: 3
|
||||
created: 0
|
||||
-
|
||||
team_id: 11
|
||||
user_id: 8
|
||||
created: 0
|
||||
-
|
||||
team_id: 12
|
||||
user_id: 9
|
||||
created: 0
|
||||
-
|
||||
team_id: 13
|
||||
user_id: 10
|
||||
created: 0
|
||||
|
@ -32,3 +32,21 @@
|
||||
right: 2
|
||||
updated: 0
|
||||
created: 0
|
||||
- id: 6
|
||||
team_id: 11
|
||||
namespace_id: 14
|
||||
right: 0
|
||||
updated: 0
|
||||
created: 0
|
||||
- id: 7
|
||||
team_id: 12
|
||||
namespace_id: 14
|
||||
right: 1
|
||||
updated: 0
|
||||
created: 0
|
||||
- id: 8
|
||||
team_id: 13
|
||||
namespace_id: 14
|
||||
right: 2
|
||||
updated: 0
|
||||
created: 0
|
||||
|
@ -19,4 +19,22 @@
|
||||
created_by_id: 1
|
||||
- id: 7
|
||||
name: testteam4_admin_on_namespace9
|
||||
created_by_id: 1
|
||||
created_by_id: 1
|
||||
- id: 8
|
||||
name: testteam8
|
||||
created_by_id: 7
|
||||
- id: 9
|
||||
name: testteam9
|
||||
created_by_id: 7
|
||||
- id: 10
|
||||
name: testteam10
|
||||
created_by_id: 7
|
||||
- id: 11
|
||||
name: testteam11
|
||||
created_by_id: 7
|
||||
- id: 12
|
||||
name: testteam12
|
||||
created_by_id: 7
|
||||
- id: 13
|
||||
name: testteam13
|
||||
created_by_id: 7
|
@ -46,3 +46,52 @@
|
||||
is_active: true
|
||||
updated: 0
|
||||
created: 0
|
||||
- id: 7
|
||||
username: 'user7'
|
||||
password: '$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.' # 1234
|
||||
email: 'user7@example.com'
|
||||
is_active: true
|
||||
updated: 0
|
||||
created: 0
|
||||
- id: 8
|
||||
username: 'user8'
|
||||
password: '$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.' # 1234
|
||||
email: 'user8@example.com'
|
||||
is_active: true
|
||||
updated: 0
|
||||
created: 0
|
||||
- id: 9
|
||||
username: 'user9'
|
||||
password: '$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.' # 1234
|
||||
email: 'user9@example.com'
|
||||
is_active: true
|
||||
updated: 0
|
||||
created: 0
|
||||
- id: 10
|
||||
username: 'user10'
|
||||
password: '$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.' # 1234
|
||||
email: 'user10@example.com'
|
||||
is_active: true
|
||||
updated: 0
|
||||
created: 0
|
||||
- id: 11
|
||||
username: 'user11'
|
||||
password: '$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.' # 1234
|
||||
email: 'user11@example.com'
|
||||
is_active: true
|
||||
updated: 0
|
||||
created: 0
|
||||
- id: 12
|
||||
username: 'user12'
|
||||
password: '$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.' # 1234
|
||||
email: 'user12@example.com'
|
||||
is_active: true
|
||||
updated: 0
|
||||
created: 0
|
||||
- id: 13
|
||||
username: 'user13'
|
||||
password: '$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.' # 1234
|
||||
email: 'user14@example.com'
|
||||
is_active: true
|
||||
updated: 0
|
||||
created: 0
|
||||
|
@ -4,31 +4,45 @@
|
||||
right: 0
|
||||
updated: 0
|
||||
created: 0
|
||||
|
||||
- id: 2
|
||||
user_id: 2
|
||||
list_id: 3
|
||||
right: 0
|
||||
updated: 0
|
||||
created: 0
|
||||
|
||||
- id: 3
|
||||
user_id: 1
|
||||
list_id: 9
|
||||
right: 0
|
||||
updated: 0
|
||||
created: 0
|
||||
|
||||
- id: 4
|
||||
user_id: 1
|
||||
list_id: 10
|
||||
right: 1
|
||||
updated: 0
|
||||
created: 0
|
||||
|
||||
- id: 5
|
||||
user_id: 1
|
||||
list_id: 11
|
||||
right: 2
|
||||
updated: 0
|
||||
created: 0
|
||||
- id: 6
|
||||
user_id: 4
|
||||
list_id: 19
|
||||
right: 0
|
||||
updated: 0
|
||||
created: 0
|
||||
- id: 7
|
||||
user_id: 5
|
||||
list_id: 19
|
||||
right: 1
|
||||
updated: 0
|
||||
created: 0
|
||||
- id: 8
|
||||
user_id: 6
|
||||
list_id: 19
|
||||
right: 2
|
||||
updated: 0
|
||||
created: 0
|
||||
|
@ -32,3 +32,21 @@
|
||||
right: 2
|
||||
updated: 0
|
||||
created: 0
|
||||
- id: 6
|
||||
user_id: 11
|
||||
namespace_id: 14
|
||||
right: 0
|
||||
updated: 0
|
||||
created: 0
|
||||
- id: 7
|
||||
user_id: 12
|
||||
namespace_id: 14
|
||||
right: 1
|
||||
updated: 0
|
||||
created: 0
|
||||
- id: 8
|
||||
user_id: 13
|
||||
namespace_id: 14
|
||||
right: 2
|
||||
updated: 0
|
||||
created: 0
|
||||
|
@ -40,7 +40,7 @@ func TestList_ReadAll(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, reflect.TypeOf(lists3).Kind(), reflect.Slice)
|
||||
s := reflect.ValueOf(lists3)
|
||||
assert.Equal(t, 15, s.Len())
|
||||
assert.Equal(t, 16, s.Len())
|
||||
|
||||
// Try getting lists for a nonexistant user
|
||||
_, err = lists2.ReadAll("", &User{ID: 984234}, 1)
|
||||
|
@ -59,7 +59,7 @@ func TestTeam_Create(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, reflect.TypeOf(ts).Kind(), reflect.Slice)
|
||||
s := reflect.ValueOf(ts)
|
||||
assert.Equal(t, 8, s.Len())
|
||||
assert.Equal(t, 9, s.Len())
|
||||
|
||||
// Check inserting it with an empty name
|
||||
dummyteam.Name = ""
|
||||
|
@ -16,6 +16,8 @@
|
||||
|
||||
package models
|
||||
|
||||
import "github.com/go-xorm/builder"
|
||||
|
||||
// ListUsers returns a list with all users, filtered by an optional searchstring
|
||||
func ListUsers(searchterm string) (users []User, err error) {
|
||||
|
||||
@ -33,3 +35,89 @@ func ListUsers(searchterm string) (users []User, err error) {
|
||||
|
||||
return users, nil
|
||||
}
|
||||
|
||||
// ListUIDs hold all kinds of user IDs from accounts who have somehow access to a list
|
||||
type ListUIDs struct {
|
||||
ListOwnerID int64 `xorm:"listOwner"`
|
||||
NamespaceUserID int64 `xorm:"unID"`
|
||||
ListUserID int64 `xorm:"ulID"`
|
||||
NamespaceOwnerUserID int64 `xorm:"nOwner"`
|
||||
TeamNamespaceUserID int64 `xorm:"tnUID"`
|
||||
TeamListUserID int64 `xorm:"tlUID"`
|
||||
}
|
||||
|
||||
// ListUsersFromList returns a list with all users who have access to a list, regardless of the method which gave them access
|
||||
func ListUsersFromList(l *List, search string) (users []*User, err error) {
|
||||
|
||||
userids := []*ListUIDs{}
|
||||
|
||||
err = x.
|
||||
Select(`l.owner_id as listOwner,
|
||||
un.user_id as unID,
|
||||
ul.user_id as ulID,
|
||||
n.owner_id as nOwner,
|
||||
tm.user_id as tnUID,
|
||||
tm2.user_id as tlUID`).
|
||||
Table("list").
|
||||
Alias("l").
|
||||
// User stuff
|
||||
Join("LEFT", []string{"users_namespace", "un"}, "un.namespace_id = l.namespace_id").
|
||||
Join("LEFT", []string{"users_list", "ul"}, "ul.list_id = l.id").
|
||||
Join("LEFT", []string{"namespaces", "n"}, "n.id = l.namespace_id").
|
||||
// Team stuff
|
||||
Join("LEFT", []string{"team_namespaces", "tn"}, " l.namespace_id = tn.namespace_id").
|
||||
Join("LEFT", []string{"team_members", "tm"}, "tm.team_id = tn.team_id").
|
||||
Join("LEFT", []string{"team_list", "tl"}, "l.id = tl.list_id").
|
||||
Join("LEFT", []string{"team_members", "tm2"}, "tm2.team_id = tl.team_id").
|
||||
// The actual condition
|
||||
Where(
|
||||
builder.Or(
|
||||
builder.Or(builder.Eq{"ul.right": RightRead}),
|
||||
builder.Or(builder.Eq{"un.right": RightRead}),
|
||||
builder.Or(builder.Eq{"tl.right": RightRead}),
|
||||
builder.Or(builder.Eq{"tn.right": RightRead}),
|
||||
|
||||
builder.Or(builder.Eq{"ul.right": RightWrite}),
|
||||
builder.Or(builder.Eq{"un.right": RightWrite}),
|
||||
builder.Or(builder.Eq{"tl.right": RightWrite}),
|
||||
builder.Or(builder.Eq{"tn.right": RightWrite}),
|
||||
|
||||
builder.Or(builder.Eq{"ul.right": RightAdmin}),
|
||||
builder.Or(builder.Eq{"un.right": RightAdmin}),
|
||||
builder.Or(builder.Eq{"tl.right": RightAdmin}),
|
||||
builder.Or(builder.Eq{"tn.right": RightAdmin}),
|
||||
),
|
||||
builder.Eq{"l.id": l.ID},
|
||||
).
|
||||
Find(&userids)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Remove duplicates from the list of ids and make it a slice
|
||||
uidmap := make(map[int64]bool)
|
||||
uidmap[l.OwnerID] = true
|
||||
for _, u := range userids {
|
||||
uidmap[u.ListUserID] = true
|
||||
uidmap[u.NamespaceOwnerUserID] = true
|
||||
uidmap[u.NamespaceUserID] = true
|
||||
uidmap[u.TeamListUserID] = true
|
||||
uidmap[u.TeamNamespaceUserID] = true
|
||||
}
|
||||
|
||||
uids := make([]int64, len(uidmap))
|
||||
for id := range uidmap {
|
||||
uids = append(uids, id)
|
||||
}
|
||||
|
||||
// Get all users
|
||||
err = x.
|
||||
Table("users").
|
||||
Select("*").
|
||||
In("id", uids).
|
||||
And("username LIKE ?", "%"+search+"%").
|
||||
GroupBy("id").
|
||||
OrderBy("id").
|
||||
Find(&users)
|
||||
return
|
||||
}
|
||||
|
159
pkg/models/users_list_test.go
Normal file
159
pkg/models/users_list_test.go
Normal file
@ -0,0 +1,159 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"gopkg.in/d4l3k/messagediff.v1"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestListUsersFromList(t *testing.T) {
|
||||
|
||||
err := LoadFixtures()
|
||||
assert.NoError(t, err)
|
||||
|
||||
testuser1 := &User{
|
||||
ID: 1,
|
||||
Username: "user1",
|
||||
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
||||
IsActive: true,
|
||||
AvatarURL: "111d68d06e2d317b5a59c2c6c5bad808",
|
||||
}
|
||||
testuser2 := &User{
|
||||
ID: 2,
|
||||
Username: "user2",
|
||||
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
||||
AvatarURL: "ab53a2911ddf9b4817ac01ddcd3d975f",
|
||||
}
|
||||
testuser3 := &User{
|
||||
ID: 3,
|
||||
Username: "user3",
|
||||
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
||||
AvatarURL: "97d6d9441ff85fdc730e02a6068d267b",
|
||||
PasswordResetToken: "passwordresettesttoken",
|
||||
}
|
||||
testuser4 := &User{
|
||||
ID: 4,
|
||||
Username: "user4",
|
||||
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
||||
IsActive: false,
|
||||
AvatarURL: "7e65550957227bd38fe2d7fbc6fd2f7b",
|
||||
EmailConfirmToken: "tiepiQueed8ahc7zeeFe1eveiy4Ein8osooxegiephauph2Ael",
|
||||
}
|
||||
testuser5 := &User{
|
||||
ID: 5,
|
||||
Username: "user5",
|
||||
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
||||
IsActive: false,
|
||||
AvatarURL: "cfa35b8cd2ec278026357769582fa563",
|
||||
EmailConfirmToken: "tiepiQueed8ahc7zeeFe1eveiy4Ein8osooxegiephauph2Ael",
|
||||
}
|
||||
testuser6 := &User{
|
||||
ID: 6,
|
||||
Username: "user6",
|
||||
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
||||
IsActive: true,
|
||||
AvatarURL: "3efbe51f864c6666bc27caf4c6ff90ed",
|
||||
}
|
||||
testuser7 := &User{
|
||||
ID: 7,
|
||||
Username: "user7",
|
||||
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
||||
IsActive: true,
|
||||
AvatarURL: "e80a711d4de44c30054806ebbd488464",
|
||||
}
|
||||
testuser8 := &User{
|
||||
ID: 8,
|
||||
Username: "user8",
|
||||
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
||||
IsActive: true,
|
||||
AvatarURL: "2b9b320416cd31020bb6844c3fadefd1",
|
||||
}
|
||||
testuser9 := &User{
|
||||
ID: 9,
|
||||
Username: "user9",
|
||||
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
||||
IsActive: true,
|
||||
AvatarURL: "f784fdb21d26dd2c64f5135f35ec401f",
|
||||
}
|
||||
testuser10 := &User{
|
||||
ID: 10,
|
||||
Username: "user10",
|
||||
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
||||
IsActive: true,
|
||||
AvatarURL: "fce8ff4ff56d75ad587d1bbaa5ef0563",
|
||||
}
|
||||
testuser11 := &User{
|
||||
ID: 11,
|
||||
Username: "user11",
|
||||
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
||||
IsActive: true,
|
||||
AvatarURL: "ad6d67d0c4495e186010732a7d360028",
|
||||
}
|
||||
testuser12 := &User{
|
||||
ID: 12,
|
||||
Username: "user12",
|
||||
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
||||
IsActive: true,
|
||||
AvatarURL: "ef1debc1364806281c42eeedfdeb943b",
|
||||
}
|
||||
testuser13 := &User{
|
||||
ID: 13,
|
||||
Username: "user13",
|
||||
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
||||
IsActive: true,
|
||||
AvatarURL: "b9e3f76032af53c9ff2df52d51ada717",
|
||||
}
|
||||
|
||||
type args struct {
|
||||
l *List
|
||||
search string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
wantUsers []*User
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "Check owner only",
|
||||
args: args{l: &List{ID: 18, OwnerID: 7}},
|
||||
wantUsers: []*User{testuser7},
|
||||
},
|
||||
{
|
||||
// This list has another different user shared for each possible method
|
||||
name: "Check with owner and other users",
|
||||
args: args{l: &List{ID: 19, OwnerID: 7}},
|
||||
wantUsers: []*User{
|
||||
testuser1, // Shared Via Team readonly
|
||||
testuser2, // Shared Via Team write
|
||||
testuser3, // Shared Via Team admin
|
||||
|
||||
testuser4, // Shared Via User readonly
|
||||
testuser5, // Shared Via User write
|
||||
testuser6, // Shared Via User admin
|
||||
|
||||
testuser7, // Owner
|
||||
|
||||
testuser8, // Shared Via NamespaceTeam readonly
|
||||
testuser9, // Shared Via NamespaceTeam write
|
||||
testuser10, // Shared Via NamespaceTeam admin
|
||||
|
||||
testuser11, // Shared Via NamespaceUser readonly
|
||||
testuser12, // Shared Via NamespaceUser write
|
||||
testuser13, // Shared Via NamespaceUser admin
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
gotUsers, err := ListUsersFromList(tt.args.l, tt.args.search)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("ListUsersFromList() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if diff, equal := messagediff.PrettyDiff(tt.wantUsers, gotUsers); !equal {
|
||||
t.Errorf("Test %s, LabelTask.ReadAll() = %v, want %v, \ndiff: %v", tt.name, gotUsers, tt.wantUsers, diff)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user