瀏覽代碼

WIP: add usergroup commands and queries

Daniel Lee 8 年之前
父節點
當前提交
af67aea2a9
共有 4 個文件被更改,包括 347 次插入1 次删除
  1. 38 1
      pkg/models/user_group.go
  2. 55 0
      pkg/models/user_group_member.go
  3. 164 0
      pkg/services/sqlstore/user_group.go
  4. 90 0
      pkg/services/sqlstore/user_group_test.go

+ 38 - 1
pkg/models/user_group.go

@@ -1,6 +1,15 @@
 package models
 
-import "time"
+import (
+	"errors"
+	"time"
+)
+
+// Typed errors
+var (
+	ErrUserGroupNotFound  = errors.New("User Group not found")
+	ErrUserGroupNameTaken = errors.New("User Group name is taken")
+)
 
 // UserGroup model
 type UserGroup struct {
@@ -11,3 +20,31 @@ type UserGroup struct {
 	Created time.Time
 	Updated time.Time
 }
+
+// ---------------------
+// COMMANDS
+
+type CreateUserGroupCommand struct {
+	Name  string `json:"name" binding:"Required"`
+	OrgId int64  `json:"orgId" binding:"Required"`
+
+	Result UserGroup `json:"-"`
+}
+
+type DeleteUserGroupCommand struct {
+	Id int64
+}
+
+type GetUserGroupByIdQuery struct {
+	Id     int64
+	Result *UserGroup
+}
+
+type SearchUserGroupsQuery struct {
+	Query string
+	Name  string
+	Limit int
+	Page  int
+
+	Result []*UserGroup
+}

+ 55 - 0
pkg/models/user_group_member.go

@@ -0,0 +1,55 @@
+package models
+
+import (
+	"errors"
+	"time"
+)
+
+// Typed errors
+var (
+	ErrUserGroupMemberAlreadyAdded = errors.New("User is already added to this user group")
+)
+
+// UserGroupMember model
+type UserGroupMember struct {
+	Id          int64
+	OrgId       int64
+	UserGroupId int64
+	UserId      int64
+
+	Created time.Time
+	Updated time.Time
+}
+
+// ---------------------
+// COMMANDS
+
+type AddUserGroupMemberCommand struct {
+	OrgId       int64 `json:"-"`
+	UserGroupId int64 `json:"-"`
+	UserId      int64 `json:"-"`
+}
+
+type RemoveUserGroupMemberCommand struct {
+	UserId      int64
+	UserGroupId int64
+}
+
+// ----------------------
+// QUERIES
+
+type GetUserGroupMembersQuery struct {
+	UserGroupId int64
+	Result      []*UserGroupMemberDTO
+}
+
+// ----------------------
+// Projections and DTOs
+
+type UserGroupMemberDTO struct {
+	OrgId       int64  `json:"orgId"`
+	UserGroupId int64  `json:"orgId"`
+	UserId      int64  `json:"userId"`
+	Email       string `json:"email"`
+	Login       string `json:"login"`
+}

+ 164 - 0
pkg/services/sqlstore/user_group.go

@@ -0,0 +1,164 @@
+package sqlstore
+
+import (
+	"fmt"
+	"time"
+
+	"github.com/go-xorm/xorm"
+
+	"github.com/grafana/grafana/pkg/bus"
+	m "github.com/grafana/grafana/pkg/models"
+)
+
+func init() {
+	bus.AddHandler("sql", CreateUserGroup)
+	bus.AddHandler("sql", DeleteUserGroup)
+	bus.AddHandler("sql", SearchUserGroups)
+	bus.AddHandler("sql", GetUserGroupById)
+
+	bus.AddHandler("sql", AddUserGroupMember)
+	bus.AddHandler("sql", RemoveUserGroupMember)
+	bus.AddHandler("sql", GetUserGroupMembers)
+}
+
+func CreateUserGroup(cmd *m.CreateUserGroupCommand) error {
+	return inTransaction2(func(sess *session) 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,
+			Created: time.Now(),
+			Updated: time.Now(),
+		}
+
+		_, err := sess.Insert(&userGroup)
+
+		cmd.Result = userGroup
+
+		return err
+	})
+}
+
+func DeleteUserGroup(cmd *m.DeleteUserGroupCommand) error {
+	return inTransaction2(func(sess *session) 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 = ?",
+		}
+
+		for _, sql := range deletes {
+			_, err := sess.Exec(sql, cmd.Id)
+			if err != nil {
+				return err
+			}
+		}
+		return nil
+	})
+}
+
+func isUserGroupNameTaken(name string, existingId int64, sess *session) (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 = make([]*m.UserGroup, 0)
+	sess := x.Table("user_group")
+	if query.Query != "" {
+		sess.Where("name LIKE ?", query.Query+"%")
+	}
+	if query.Name != "" {
+		sess.Where("name=?", query.Name)
+	}
+	sess.Limit(query.Limit, query.Limit*query.Page)
+	sess.Cols("id", "name")
+	err := sess.Find(&query.Result)
+	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 AddUserGroupMember(cmd *m.AddUserGroupMemberCommand) error {
+	return inTransaction(func(sess *xorm.Session) 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 *xorm.Session) 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.email", "user.login")
+
+	err := sess.Find(&query.Result)
+	return err
+}

+ 90 - 0
pkg/services/sqlstore/user_group_test.go

@@ -0,0 +1,90 @@
+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"}
+				err = SearchUserGroups(query)
+				So(err, ShouldBeNil)
+				So(query.Page, ShouldEqual, 0)
+
+				userGroup1 := query.Result[0]
+				So(query.Result[0].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"}
+				err = SearchUserGroups(query)
+				So(err, ShouldBeNil)
+				So(len(query.Result), ShouldEqual, 2)
+			})
+
+			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", 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 = DeleteUserGroup(&m.DeleteUserGroupCommand{Id: groupId})
+				So(err, ShouldBeNil)
+
+				query := &m.GetUserGroupByIdQuery{Id: groupId}
+				err = GetUserGroupById(query)
+				So(err, ShouldEqual, m.ErrUserGroupNotFound)
+			})
+		})
+	})
+}