Merge branch 'refactor-user-group-to-team' of https://github.com/alexanderzobnin/grafana into user-group-to-team

This commit is contained in:
Torkel Ödegaard
2017-12-12 17:07:00 +01:00
52 changed files with 922 additions and 920 deletions
+13 -13
View File
@@ -24,7 +24,7 @@ func UpdateDashboardAcl(cmd *m.UpdateDashboardAclCommand) error {
}
for _, item := range cmd.Items {
if item.UserId == 0 && item.UserGroupId == 0 && !item.Role.IsValid() {
if item.UserId == 0 && item.TeamId == 0 && !item.Role.IsValid() {
return m.ErrDashboardAclInfoMissing
}
@@ -32,7 +32,7 @@ func UpdateDashboardAcl(cmd *m.UpdateDashboardAclCommand) error {
return m.ErrDashboardPermissionDashboardEmpty
}
sess.Nullable("user_id", "user_group_id")
sess.Nullable("user_id", "team_id")
if _, err := sess.Insert(item); err != nil {
return err
}
@@ -49,7 +49,7 @@ func UpdateDashboardAcl(cmd *m.UpdateDashboardAclCommand) error {
func SetDashboardAcl(cmd *m.SetDashboardAclCommand) error {
return inTransaction(func(sess *DBSession) error {
if cmd.UserId == 0 && cmd.UserGroupId == 0 {
if cmd.UserId == 0 && cmd.TeamId == 0 {
return m.ErrDashboardAclInfoMissing
}
@@ -57,7 +57,7 @@ func SetDashboardAcl(cmd *m.SetDashboardAclCommand) error {
return m.ErrDashboardPermissionDashboardEmpty
}
if res, err := sess.Query("SELECT 1 from "+dialect.Quote("dashboard_acl")+" WHERE dashboard_id =? and (user_group_id=? or user_id=?)", cmd.DashboardId, cmd.UserGroupId, cmd.UserId); err != nil {
if res, err := sess.Query("SELECT 1 from "+dialect.Quote("dashboard_acl")+" WHERE dashboard_id =? and (team_id=? or user_id=?)", cmd.DashboardId, cmd.TeamId, cmd.UserId); err != nil {
return err
} else if len(res) == 1 {
@@ -66,7 +66,7 @@ func SetDashboardAcl(cmd *m.SetDashboardAclCommand) error {
Updated: time.Now(),
}
if _, err := sess.Cols("updated", "permission").Where("dashboard_id =? and (user_group_id=? or user_id=?)", cmd.DashboardId, cmd.UserGroupId, cmd.UserId).Update(&entity); err != nil {
if _, err := sess.Cols("updated", "permission").Where("dashboard_id =? and (team_id=? or user_id=?)", cmd.DashboardId, cmd.TeamId, cmd.UserId).Update(&entity); err != nil {
return err
}
@@ -75,7 +75,7 @@ func SetDashboardAcl(cmd *m.SetDashboardAclCommand) error {
entity := m.DashboardAcl{
OrgId: cmd.OrgId,
UserGroupId: cmd.UserGroupId,
TeamId: cmd.TeamId,
UserId: cmd.UserId,
Created: time.Now(),
Updated: time.Now(),
@@ -89,8 +89,8 @@ func SetDashboardAcl(cmd *m.SetDashboardAclCommand) error {
cols = append(cols, "user_id")
}
if cmd.UserGroupId != 0 {
cols = append(cols, "user_group_id")
if cmd.TeamId != 0 {
cols = append(cols, "team_id")
}
_, err := sess.Cols(cols...).Insert(&entity)
@@ -138,17 +138,17 @@ func GetDashboardAclInfoList(query *m.GetDashboardAclInfoListQuery) error {
da.org_id,
da.dashboard_id,
da.user_id,
da.user_group_id,
da.team_id,
da.permission,
da.role,
da.created,
da.updated,
u.login AS user_login,
u.email AS user_email,
ug.name AS user_group
ug.name AS team
FROM` + dialect.Quote("dashboard_acl") + ` as da
LEFT OUTER JOIN ` + dialect.Quote("user") + ` AS u ON u.id = da.user_id
LEFT OUTER JOIN user_group ug on ug.id = da.user_group_id
LEFT OUTER JOIN team ug on ug.id = da.team_id
WHERE dashboard_id ` + dashboardFilter + ` AND da.org_id = ?
-- Also include default permission if has_acl = 0
@@ -159,14 +159,14 @@ func GetDashboardAclInfoList(query *m.GetDashboardAclInfoListQuery) error {
da.org_id,
da.dashboard_id,
da.user_id,
da.user_group_id,
da.team_id,
da.permission,
da.role,
da.created,
da.updated,
'' as user_login,
'' as user_email,
'' as user_group
'' as team
FROM dashboard_acl as da,
dashboard as dash
LEFT JOIN dashboard folder on dash.folder_id = folder.id
+11 -11
View File
@@ -16,7 +16,7 @@ func TestDashboardAclDataAccess(t *testing.T) {
savedFolder := insertTestDashboard("1 test dash folder", 1, 0, true, "prod", "webapp")
childDash := insertTestDashboard("2 test dash", 1, savedFolder.Id, false, "prod", "webapp")
Convey("When adding dashboard permission with userId and userGroupId set to 0", func() {
Convey("When adding dashboard permission with userId and teamId set to 0", func() {
err := SetDashboardAcl(&m.SetDashboardAclCommand{
OrgId: 1,
DashboardId: savedFolder.Id,
@@ -175,15 +175,15 @@ func TestDashboardAclDataAccess(t *testing.T) {
})
})
Convey("Given a user group", func() {
group1 := m.CreateUserGroupCommand{Name: "group1 name", OrgId: 1}
err := CreateUserGroup(&group1)
Convey("Given a team", func() {
group1 := m.CreateTeamCommand{Name: "group1 name", OrgId: 1}
err := CreateTeam(&group1)
So(err, ShouldBeNil)
Convey("Should be able to add a user permission for a user group", func() {
Convey("Should be able to add a user permission for a team", func() {
setDashAclCmd := m.SetDashboardAclCommand{
OrgId: 1,
UserGroupId: group1.Result.Id,
TeamId: group1.Result.Id,
DashboardId: savedFolder.Id,
Permission: m.PERMISSION_EDIT,
}
@@ -196,9 +196,9 @@ func TestDashboardAclDataAccess(t *testing.T) {
So(err, ShouldBeNil)
So(q1.Result[0].DashboardId, ShouldEqual, savedFolder.Id)
So(q1.Result[0].Permission, ShouldEqual, m.PERMISSION_EDIT)
So(q1.Result[0].UserGroupId, ShouldEqual, group1.Result.Id)
So(q1.Result[0].TeamId, ShouldEqual, group1.Result.Id)
Convey("Should be able to delete an existing permission for a user group", func() {
Convey("Should be able to delete an existing permission for a team", func() {
err := RemoveDashboardAcl(&m.RemoveDashboardAclCommand{
OrgId: 1,
AclId: setDashAclCmd.Result.Id,
@@ -212,10 +212,10 @@ func TestDashboardAclDataAccess(t *testing.T) {
})
})
Convey("Should be able to update an existing permission for a user group", func() {
Convey("Should be able to update an existing permission for a team", func() {
err := SetDashboardAcl(&m.SetDashboardAclCommand{
OrgId: 1,
UserGroupId: group1.Result.Id,
TeamId: group1.Result.Id,
DashboardId: savedFolder.Id,
Permission: m.PERMISSION_ADMIN,
})
@@ -227,7 +227,7 @@ func TestDashboardAclDataAccess(t *testing.T) {
So(len(q3.Result), ShouldEqual, 1)
So(q3.Result[0].DashboardId, ShouldEqual, savedFolder.Id)
So(q3.Result[0].Permission, ShouldEqual, m.PERMISSION_ADMIN)
So(q3.Result[0].UserGroupId, ShouldEqual, group1.Result.Id)
So(q3.Result[0].TeamId, ShouldEqual, group1.Result.Id)
})
})
@@ -10,7 +10,7 @@ func addDashboardAclMigrations(mg *Migrator) {
{Name: "org_id", Type: DB_BigInt},
{Name: "dashboard_id", Type: DB_BigInt},
{Name: "user_id", Type: DB_BigInt, Nullable: true},
{Name: "user_group_id", Type: DB_BigInt, Nullable: true},
{Name: "team_id", Type: DB_BigInt, Nullable: true},
{Name: "permission", Type: DB_SmallInt, Default: "4"},
{Name: "role", Type: DB_Varchar, Length: 20, Nullable: true},
{Name: "created", Type: DB_DateTime, Nullable: false},
@@ -19,7 +19,7 @@ func addDashboardAclMigrations(mg *Migrator) {
Indices: []*Index{
{Cols: []string{"dashboard_id"}},
{Cols: []string{"dashboard_id", "user_id"}, Type: UniqueIndex},
{Cols: []string{"dashboard_id", "user_group_id"}, Type: UniqueIndex},
{Cols: []string{"dashboard_id", "team_id"}, Type: UniqueIndex},
},
}
@@ -26,7 +26,7 @@ func AddMigrations(mg *Migrator) {
addAnnotationMig(mg)
addTestDataMigrations(mg)
addDashboardVersionMigration(mg)
addUserGroupMigrations(mg)
addTeamMigrations(mg)
addDashboardAclMigrations(mg)
addTagMigration(mg)
}
@@ -2,9 +2,9 @@ package migrations
import . "github.com/grafana/grafana/pkg/services/sqlstore/migrator"
func addUserGroupMigrations(mg *Migrator) {
userGroupV1 := Table{
Name: "user_group",
func addTeamMigrations(mg *Migrator) {
teamV1 := Table{
Name: "team",
Columns: []*Column{
{Name: "id", Type: DB_BigInt, IsPrimaryKey: true, IsAutoIncrement: true},
{Name: "name", Type: DB_NVarchar, Length: 255, Nullable: false},
@@ -18,31 +18,31 @@ func addUserGroupMigrations(mg *Migrator) {
},
}
mg.AddMigration("create user group table", NewAddTableMigration(userGroupV1))
mg.AddMigration("create team table", NewAddTableMigration(teamV1))
//------- indexes ------------------
mg.AddMigration("add index user_group.org_id", NewAddIndexMigration(userGroupV1, userGroupV1.Indices[0]))
mg.AddMigration("add unique index user_group_org_id_name", NewAddIndexMigration(userGroupV1, userGroupV1.Indices[1]))
mg.AddMigration("add index team.org_id", NewAddIndexMigration(teamV1, teamV1.Indices[0]))
mg.AddMigration("add unique index team_org_id_name", NewAddIndexMigration(teamV1, teamV1.Indices[1]))
userGroupMemberV1 := Table{
Name: "user_group_member",
teamMemberV1 := Table{
Name: "team_member",
Columns: []*Column{
{Name: "id", Type: DB_BigInt, IsPrimaryKey: true, IsAutoIncrement: true},
{Name: "org_id", Type: DB_BigInt},
{Name: "user_group_id", Type: DB_BigInt},
{Name: "team_id", Type: DB_BigInt},
{Name: "user_id", Type: DB_BigInt},
{Name: "created", Type: DB_DateTime, Nullable: false},
{Name: "updated", Type: DB_DateTime, Nullable: false},
},
Indices: []*Index{
{Cols: []string{"org_id"}},
{Cols: []string{"org_id", "user_group_id", "user_id"}, Type: UniqueIndex},
{Cols: []string{"org_id", "team_id", "user_id"}, Type: UniqueIndex},
},
}
mg.AddMigration("create user group member table", NewAddTableMigration(userGroupMemberV1))
mg.AddMigration("create team member table", NewAddTableMigration(teamMemberV1))
//------- indexes ------------------
mg.AddMigration("add index user_group_member.org_id", NewAddIndexMigration(userGroupMemberV1, userGroupMemberV1.Indices[0]))
mg.AddMigration("add unique index user_group_member_org_id_user_group_id_user_id", NewAddIndexMigration(userGroupMemberV1, userGroupMemberV1.Indices[1]))
mg.AddMigration("add index team_member.org_id", NewAddIndexMigration(teamMemberV1, teamMemberV1.Indices[0]))
mg.AddMigration("add unique index team_member_org_id_team_id_user_id", NewAddIndexMigration(teamMemberV1, teamMemberV1.Indices[1]))
}
+1 -1
View File
@@ -91,7 +91,7 @@ func RemoveOrgUser(cmd *m.RemoveOrgUserCommand) error {
deletes := []string{
"DELETE FROM org_user WHERE org_id=? and user_id=?",
"DELETE FROM dashboard_acl WHERE org_id=? and user_id = ?",
"DELETE FROM user_group_member WHERE org_id=? and user_id = ?",
"DELETE FROM team_member WHERE org_id=? and user_id = ?",
}
for _, sql := range deletes {
+1 -1
View File
@@ -179,7 +179,7 @@ func (sb *SearchBuilder) buildSearchWhereClause() {
SELECT distinct d.id AS DashboardId
FROM dashboard AS d
LEFT JOIN dashboard_acl as da on d.folder_id = da.dashboard_id or d.id = da.dashboard_id
LEFT JOIN user_group_member as ugm on ugm.user_group_id = da.user_group_id
LEFT JOIN team_member as ugm on ugm.team_id = da.team_id
LEFT JOIN org_user ou on ou.role = da.role
WHERE
d.has_acl = 1 and
+233
View File
@@ -0,0 +1,233 @@
package sqlstore
import (
"fmt"
"time"
"github.com/grafana/grafana/pkg/bus"
m "github.com/grafana/grafana/pkg/models"
)
func init() {
bus.AddHandler("sql", CreateTeam)
bus.AddHandler("sql", UpdateTeam)
bus.AddHandler("sql", DeleteTeam)
bus.AddHandler("sql", SearchTeams)
bus.AddHandler("sql", GetTeamById)
bus.AddHandler("sql", GetTeamsByUser)
bus.AddHandler("sql", AddTeamMember)
bus.AddHandler("sql", RemoveTeamMember)
bus.AddHandler("sql", GetTeamMembers)
}
func CreateTeam(cmd *m.CreateTeamCommand) error {
return inTransaction(func(sess *DBSession) error {
if isNameTaken, err := isTeamNameTaken(cmd.Name, 0, sess); err != nil {
return err
} else if isNameTaken {
return m.ErrTeamNameTaken
}
team := m.Team{
Name: cmd.Name,
OrgId: cmd.OrgId,
Created: time.Now(),
Updated: time.Now(),
}
_, err := sess.Insert(&team)
cmd.Result = team
return err
})
}
func UpdateTeam(cmd *m.UpdateTeamCommand) error {
return inTransaction(func(sess *DBSession) error {
if isNameTaken, err := isTeamNameTaken(cmd.Name, cmd.Id, sess); err != nil {
return err
} else if isNameTaken {
return m.ErrTeamNameTaken
}
team := m.Team{
Name: cmd.Name,
Updated: time.Now(),
}
affectedRows, err := sess.Id(cmd.Id).Update(&team)
if err != nil {
return err
}
if affectedRows == 0 {
return m.ErrTeamNotFound
}
return nil
})
}
func DeleteTeam(cmd *m.DeleteTeamCommand) error {
return inTransaction(func(sess *DBSession) error {
if res, err := sess.Query("SELECT 1 from team WHERE id=?", cmd.Id); err != nil {
return err
} else if len(res) != 1 {
return m.ErrTeamNotFound
}
deletes := []string{
"DELETE FROM team_member WHERE team_id = ?",
"DELETE FROM team WHERE id = ?",
"DELETE FROM dashboard_acl WHERE team_id = ?",
}
for _, sql := range deletes {
_, err := sess.Exec(sql, cmd.Id)
if err != nil {
return err
}
}
return nil
})
}
func isTeamNameTaken(name string, existingId int64, sess *DBSession) (bool, error) {
var team m.Team
exists, err := sess.Where("name=?", name).Get(&team)
if err != nil {
return false, nil
}
if exists && existingId != team.Id {
return true, nil
}
return false, nil
}
func SearchTeams(query *m.SearchTeamsQuery) error {
query.Result = m.SearchTeamQueryResult{
Teams: make([]*m.Team, 0),
}
queryWithWildcards := "%" + query.Query + "%"
sess := x.Table("team")
sess.Where("org_id=?", query.OrgId)
if query.Query != "" {
sess.Where("name LIKE ?", queryWithWildcards)
}
if query.Name != "" {
sess.Where("name=?", query.Name)
}
sess.Asc("name")
offset := query.Limit * (query.Page - 1)
sess.Limit(query.Limit, offset)
sess.Cols("id", "name")
if err := sess.Find(&query.Result.Teams); err != nil {
return err
}
team := m.Team{}
countSess := x.Table("team")
if query.Query != "" {
countSess.Where("name LIKE ?", queryWithWildcards)
}
if query.Name != "" {
countSess.Where("name=?", query.Name)
}
count, err := countSess.Count(&team)
query.Result.TotalCount = count
return err
}
func GetTeamById(query *m.GetTeamByIdQuery) error {
var team m.Team
exists, err := x.Id(query.Id).Get(&team)
if err != nil {
return err
}
if !exists {
return m.ErrTeamNotFound
}
query.Result = &team
return nil
}
func GetTeamsByUser(query *m.GetTeamsByUserQuery) error {
query.Result = make([]*m.Team, 0)
sess := x.Table("team")
sess.Join("INNER", "team_member", "team.id=team_member.team_id")
sess.Where("team_member.user_id=?", query.UserId)
err := sess.Find(&query.Result)
if err != nil {
return err
}
return nil
}
func AddTeamMember(cmd *m.AddTeamMemberCommand) error {
return inTransaction(func(sess *DBSession) error {
if res, err := sess.Query("SELECT 1 from team_member WHERE team_id=? and user_id=?", cmd.TeamId, cmd.UserId); err != nil {
return err
} else if len(res) == 1 {
return m.ErrTeamMemberAlreadyAdded
}
if res, err := sess.Query("SELECT 1 from team WHERE id=?", cmd.TeamId); err != nil {
return err
} else if len(res) != 1 {
return m.ErrTeamNotFound
}
entity := m.TeamMember{
OrgId: cmd.OrgId,
TeamId: cmd.TeamId,
UserId: cmd.UserId,
Created: time.Now(),
Updated: time.Now(),
}
_, err := sess.Insert(&entity)
return err
})
}
func RemoveTeamMember(cmd *m.RemoveTeamMemberCommand) error {
return inTransaction(func(sess *DBSession) error {
var rawSql = "DELETE FROM team_member WHERE team_id=? and user_id=?"
_, err := sess.Exec(rawSql, cmd.TeamId, cmd.UserId)
if err != nil {
return err
}
return err
})
}
func GetTeamMembers(query *m.GetTeamMembersQuery) error {
query.Result = make([]*m.TeamMemberDTO, 0)
sess := x.Table("team_member")
sess.Join("INNER", "user", fmt.Sprintf("team_member.user_id=%s.id", x.Dialect().Quote("user")))
sess.Where("team_member.team_id=?", query.TeamId)
sess.Cols("user.org_id", "team_member.team_id", "team_member.user_id", "user.email", "user.login")
sess.Asc("user.login", "user.email")
err := sess.Find(&query.Result)
return err
}
+114
View File
@@ -0,0 +1,114 @@
package sqlstore
import (
"fmt"
"testing"
. "github.com/smartystreets/goconvey/convey"
m "github.com/grafana/grafana/pkg/models"
)
func TestTeamCommandsAndQueries(t *testing.T) {
Convey("Testing Team commands & queries", t, func() {
InitTestDB(t)
Convey("Given saved users and two teams", func() {
var userIds []int64
for i := 0; i < 5; i++ {
userCmd := &m.CreateUserCommand{
Email: fmt.Sprint("user", i, "@test.com"),
Name: fmt.Sprint("user", i),
Login: fmt.Sprint("loginuser", i),
}
err := CreateUser(userCmd)
So(err, ShouldBeNil)
userIds = append(userIds, userCmd.Result.Id)
}
group1 := m.CreateTeamCommand{Name: "group1 name"}
group2 := m.CreateTeamCommand{Name: "group2 name"}
err := CreateTeam(&group1)
So(err, ShouldBeNil)
err = CreateTeam(&group2)
So(err, ShouldBeNil)
Convey("Should be able to create teams and add users", func() {
query := &m.SearchTeamsQuery{Name: "group1 name", Page: 1, Limit: 10}
err = SearchTeams(query)
So(err, ShouldBeNil)
So(query.Page, ShouldEqual, 1)
team1 := query.Result.Teams[0]
So(team1.Name, ShouldEqual, "group1 name")
err = AddTeamMember(&m.AddTeamMemberCommand{OrgId: 1, TeamId: team1.Id, UserId: userIds[0]})
So(err, ShouldBeNil)
q1 := &m.GetTeamMembersQuery{TeamId: team1.Id}
err = GetTeamMembers(q1)
So(err, ShouldBeNil)
So(q1.Result[0].TeamId, ShouldEqual, team1.Id)
So(q1.Result[0].Login, ShouldEqual, "loginuser0")
})
Convey("Should be able to search for teams", func() {
query := &m.SearchTeamsQuery{Query: "group", Page: 1}
err = SearchTeams(query)
So(err, ShouldBeNil)
So(len(query.Result.Teams), ShouldEqual, 2)
So(query.Result.TotalCount, ShouldEqual, 2)
query2 := &m.SearchTeamsQuery{Query: ""}
err = SearchTeams(query2)
So(err, ShouldBeNil)
So(len(query2.Result.Teams), ShouldEqual, 2)
})
Convey("Should be able to return all teams a user is member of", func() {
groupId := group2.Result.Id
err := AddTeamMember(&m.AddTeamMemberCommand{OrgId: 1, TeamId: groupId, UserId: userIds[0]})
query := &m.GetTeamsByUserQuery{UserId: userIds[0]}
err = GetTeamsByUser(query)
So(err, ShouldBeNil)
So(len(query.Result), ShouldEqual, 1)
So(query.Result[0].Name, ShouldEqual, "group2 name")
})
Convey("Should be able to remove users from a group", func() {
err = RemoveTeamMember(&m.RemoveTeamMemberCommand{TeamId: group1.Result.Id, UserId: userIds[0]})
So(err, ShouldBeNil)
q1 := &m.GetTeamMembersQuery{TeamId: group1.Result.Id}
err = GetTeamMembers(q1)
So(err, ShouldBeNil)
So(len(q1.Result), ShouldEqual, 0)
})
Convey("Should be able to remove a group with users and permissions", func() {
groupId := group2.Result.Id
err := AddTeamMember(&m.AddTeamMemberCommand{OrgId: 1, TeamId: groupId, UserId: userIds[1]})
So(err, ShouldBeNil)
err = AddTeamMember(&m.AddTeamMemberCommand{OrgId: 1, TeamId: groupId, UserId: userIds[2]})
So(err, ShouldBeNil)
err = SetDashboardAcl(&m.SetDashboardAclCommand{DashboardId: 1, OrgId: 1, Permission: m.PERMISSION_EDIT, TeamId: groupId})
err = DeleteTeam(&m.DeleteTeamCommand{Id: groupId})
So(err, ShouldBeNil)
query := &m.GetTeamByIdQuery{Id: groupId}
err = GetTeamById(query)
So(err, ShouldEqual, m.ErrTeamNotFound)
permQuery := &m.GetDashboardAclInfoListQuery{DashboardId: 1, OrgId: 1}
err = GetDashboardAclInfoList(permQuery)
So(err, ShouldBeNil)
So(len(permQuery.Result), ShouldEqual, 0)
})
})
})
}
+1 -1
View File
@@ -442,7 +442,7 @@ func DeleteUser(cmd *m.DeleteUserCommand) error {
"DELETE FROM org_user WHERE user_id = ?",
"DELETE FROM dashboard_acl WHERE user_id = ?",
"DELETE FROM preferences WHERE user_id = ?",
"DELETE FROM user_group_member WHERE user_id = ?",
"DELETE FROM team_member WHERE user_id = ?",
}
for _, sql := range deletes {
-233
View File
@@ -1,233 +0,0 @@
package sqlstore
import (
"fmt"
"time"
"github.com/grafana/grafana/pkg/bus"
m "github.com/grafana/grafana/pkg/models"
)
func init() {
bus.AddHandler("sql", CreateUserGroup)
bus.AddHandler("sql", UpdateUserGroup)
bus.AddHandler("sql", DeleteUserGroup)
bus.AddHandler("sql", SearchUserGroups)
bus.AddHandler("sql", GetUserGroupById)
bus.AddHandler("sql", GetUserGroupsByUser)
bus.AddHandler("sql", AddUserGroupMember)
bus.AddHandler("sql", RemoveUserGroupMember)
bus.AddHandler("sql", GetUserGroupMembers)
}
func CreateUserGroup(cmd *m.CreateUserGroupCommand) error {
return inTransaction(func(sess *DBSession) error {
if isNameTaken, err := isUserGroupNameTaken(cmd.Name, 0, sess); err != nil {
return err
} else if isNameTaken {
return m.ErrUserGroupNameTaken
}
userGroup := m.UserGroup{
Name: cmd.Name,
OrgId: cmd.OrgId,
Created: time.Now(),
Updated: time.Now(),
}
_, err := sess.Insert(&userGroup)
cmd.Result = userGroup
return err
})
}
func UpdateUserGroup(cmd *m.UpdateUserGroupCommand) error {
return inTransaction(func(sess *DBSession) error {
if isNameTaken, err := isUserGroupNameTaken(cmd.Name, cmd.Id, sess); err != nil {
return err
} else if isNameTaken {
return m.ErrUserGroupNameTaken
}
userGroup := m.UserGroup{
Name: cmd.Name,
Updated: time.Now(),
}
affectedRows, err := sess.Id(cmd.Id).Update(&userGroup)
if err != nil {
return err
}
if affectedRows == 0 {
return m.ErrUserGroupNotFound
}
return nil
})
}
func DeleteUserGroup(cmd *m.DeleteUserGroupCommand) error {
return inTransaction(func(sess *DBSession) error {
if res, err := sess.Query("SELECT 1 from user_group WHERE id=?", cmd.Id); err != nil {
return err
} else if len(res) != 1 {
return m.ErrUserGroupNotFound
}
deletes := []string{
"DELETE FROM user_group_member WHERE user_group_id = ?",
"DELETE FROM user_group WHERE id = ?",
"DELETE FROM dashboard_acl WHERE user_group_id = ?",
}
for _, sql := range deletes {
_, err := sess.Exec(sql, cmd.Id)
if err != nil {
return err
}
}
return nil
})
}
func isUserGroupNameTaken(name string, existingId int64, sess *DBSession) (bool, error) {
var userGroup m.UserGroup
exists, err := sess.Where("name=?", name).Get(&userGroup)
if err != nil {
return false, nil
}
if exists && existingId != userGroup.Id {
return true, nil
}
return false, nil
}
func SearchUserGroups(query *m.SearchUserGroupsQuery) error {
query.Result = m.SearchUserGroupQueryResult{
UserGroups: make([]*m.UserGroup, 0),
}
queryWithWildcards := "%" + query.Query + "%"
sess := x.Table("user_group")
sess.Where("org_id=?", query.OrgId)
if query.Query != "" {
sess.Where("name LIKE ?", queryWithWildcards)
}
if query.Name != "" {
sess.Where("name=?", query.Name)
}
sess.Asc("name")
offset := query.Limit * (query.Page - 1)
sess.Limit(query.Limit, offset)
sess.Cols("id", "name")
if err := sess.Find(&query.Result.UserGroups); err != nil {
return err
}
userGroup := m.UserGroup{}
countSess := x.Table("user_group")
if query.Query != "" {
countSess.Where("name LIKE ?", queryWithWildcards)
}
if query.Name != "" {
countSess.Where("name=?", query.Name)
}
count, err := countSess.Count(&userGroup)
query.Result.TotalCount = count
return err
}
func GetUserGroupById(query *m.GetUserGroupByIdQuery) error {
var userGroup m.UserGroup
exists, err := x.Id(query.Id).Get(&userGroup)
if err != nil {
return err
}
if !exists {
return m.ErrUserGroupNotFound
}
query.Result = &userGroup
return nil
}
func GetUserGroupsByUser(query *m.GetUserGroupsByUserQuery) error {
query.Result = make([]*m.UserGroup, 0)
sess := x.Table("user_group")
sess.Join("INNER", "user_group_member", "user_group.id=user_group_member.user_group_id")
sess.Where("user_group_member.user_id=?", query.UserId)
err := sess.Find(&query.Result)
if err != nil {
return err
}
return nil
}
func AddUserGroupMember(cmd *m.AddUserGroupMemberCommand) error {
return inTransaction(func(sess *DBSession) error {
if res, err := sess.Query("SELECT 1 from user_group_member WHERE user_group_id=? and user_id=?", cmd.UserGroupId, cmd.UserId); err != nil {
return err
} else if len(res) == 1 {
return m.ErrUserGroupMemberAlreadyAdded
}
if res, err := sess.Query("SELECT 1 from user_group WHERE id=?", cmd.UserGroupId); err != nil {
return err
} else if len(res) != 1 {
return m.ErrUserGroupNotFound
}
entity := m.UserGroupMember{
OrgId: cmd.OrgId,
UserGroupId: cmd.UserGroupId,
UserId: cmd.UserId,
Created: time.Now(),
Updated: time.Now(),
}
_, err := sess.Insert(&entity)
return err
})
}
func RemoveUserGroupMember(cmd *m.RemoveUserGroupMemberCommand) error {
return inTransaction(func(sess *DBSession) error {
var rawSql = "DELETE FROM user_group_member WHERE user_group_id=? and user_id=?"
_, err := sess.Exec(rawSql, cmd.UserGroupId, cmd.UserId)
if err != nil {
return err
}
return err
})
}
func GetUserGroupMembers(query *m.GetUserGroupMembersQuery) error {
query.Result = make([]*m.UserGroupMemberDTO, 0)
sess := x.Table("user_group_member")
sess.Join("INNER", "user", fmt.Sprintf("user_group_member.user_id=%s.id", x.Dialect().Quote("user")))
sess.Where("user_group_member.user_group_id=?", query.UserGroupId)
sess.Cols("user.org_id", "user_group_member.user_group_id", "user_group_member.user_id", "user.email", "user.login")
sess.Asc("user.login", "user.email")
err := sess.Find(&query.Result)
return err
}
-114
View File
@@ -1,114 +0,0 @@
package sqlstore
import (
"fmt"
"testing"
. "github.com/smartystreets/goconvey/convey"
m "github.com/grafana/grafana/pkg/models"
)
func TestUserGroupCommandsAndQueries(t *testing.T) {
Convey("Testing User Group commands & queries", t, func() {
InitTestDB(t)
Convey("Given saved users and two user groups", func() {
var userIds []int64
for i := 0; i < 5; i++ {
userCmd := &m.CreateUserCommand{
Email: fmt.Sprint("user", i, "@test.com"),
Name: fmt.Sprint("user", i),
Login: fmt.Sprint("loginuser", i),
}
err := CreateUser(userCmd)
So(err, ShouldBeNil)
userIds = append(userIds, userCmd.Result.Id)
}
group1 := m.CreateUserGroupCommand{Name: "group1 name"}
group2 := m.CreateUserGroupCommand{Name: "group2 name"}
err := CreateUserGroup(&group1)
So(err, ShouldBeNil)
err = CreateUserGroup(&group2)
So(err, ShouldBeNil)
Convey("Should be able to create user groups and add users", func() {
query := &m.SearchUserGroupsQuery{Name: "group1 name", Page: 1, Limit: 10}
err = SearchUserGroups(query)
So(err, ShouldBeNil)
So(query.Page, ShouldEqual, 1)
userGroup1 := query.Result.UserGroups[0]
So(userGroup1.Name, ShouldEqual, "group1 name")
err = AddUserGroupMember(&m.AddUserGroupMemberCommand{OrgId: 1, UserGroupId: userGroup1.Id, UserId: userIds[0]})
So(err, ShouldBeNil)
q1 := &m.GetUserGroupMembersQuery{UserGroupId: userGroup1.Id}
err = GetUserGroupMembers(q1)
So(err, ShouldBeNil)
So(q1.Result[0].UserGroupId, ShouldEqual, userGroup1.Id)
So(q1.Result[0].Login, ShouldEqual, "loginuser0")
})
Convey("Should be able to search for user groups", func() {
query := &m.SearchUserGroupsQuery{Query: "group", Page: 1}
err = SearchUserGroups(query)
So(err, ShouldBeNil)
So(len(query.Result.UserGroups), ShouldEqual, 2)
So(query.Result.TotalCount, ShouldEqual, 2)
query2 := &m.SearchUserGroupsQuery{Query: ""}
err = SearchUserGroups(query2)
So(err, ShouldBeNil)
So(len(query2.Result.UserGroups), ShouldEqual, 2)
})
Convey("Should be able to return all user groups a user is member of", func() {
groupId := group2.Result.Id
err := AddUserGroupMember(&m.AddUserGroupMemberCommand{OrgId: 1, UserGroupId: groupId, UserId: userIds[0]})
query := &m.GetUserGroupsByUserQuery{UserId: userIds[0]}
err = GetUserGroupsByUser(query)
So(err, ShouldBeNil)
So(len(query.Result), ShouldEqual, 1)
So(query.Result[0].Name, ShouldEqual, "group2 name")
})
Convey("Should be able to remove users from a group", func() {
err = RemoveUserGroupMember(&m.RemoveUserGroupMemberCommand{UserGroupId: group1.Result.Id, UserId: userIds[0]})
So(err, ShouldBeNil)
q1 := &m.GetUserGroupMembersQuery{UserGroupId: group1.Result.Id}
err = GetUserGroupMembers(q1)
So(err, ShouldBeNil)
So(len(q1.Result), ShouldEqual, 0)
})
Convey("Should be able to remove a group with users and permissions", func() {
groupId := group2.Result.Id
err := AddUserGroupMember(&m.AddUserGroupMemberCommand{OrgId: 1, UserGroupId: groupId, UserId: userIds[1]})
So(err, ShouldBeNil)
err = AddUserGroupMember(&m.AddUserGroupMemberCommand{OrgId: 1, UserGroupId: groupId, UserId: userIds[2]})
So(err, ShouldBeNil)
err = SetDashboardAcl(&m.SetDashboardAclCommand{DashboardId: 1, OrgId: 1, Permission: m.PERMISSION_EDIT, UserGroupId: groupId})
err = DeleteUserGroup(&m.DeleteUserGroupCommand{Id: groupId})
So(err, ShouldBeNil)
query := &m.GetUserGroupByIdQuery{Id: groupId}
err = GetUserGroupById(query)
So(err, ShouldEqual, m.ErrUserGroupNotFound)
permQuery := &m.GetDashboardAclInfoListQuery{DashboardId: 1, OrgId: 1}
err = GetDashboardAclInfoList(permQuery)
So(err, ShouldBeNil)
So(len(permQuery.Result), ShouldEqual, 0)
})
})
})
}