diff --git a/pkg/api/api_account.go b/pkg/api/api_account.go index bccd8b4c647..734463c3d50 100644 --- a/pkg/api/api_account.go +++ b/pkg/api/api_account.go @@ -21,14 +21,14 @@ func GetAccount(c *middleware.Context) { } func AddCollaborator(c *middleware.Context) { - var model dtos.AddCollaboratorCommand + var cmd m.AddCollaboratorCommand - if !c.JsonBody(&model) { + if !c.JsonBody(&cmd) { c.JsonApiErr(400, "Invalid request", nil) return } - accountToAdd, err := m.GetAccountByLogin(model.Email) + accountToAdd, err := m.GetAccountByLogin(cmd.Email) if err != nil { c.JsonApiErr(404, "Collaborator not found", nil) return @@ -39,15 +39,17 @@ func AddCollaborator(c *middleware.Context) { return } - var collaborator = m.NewCollaborator(accountToAdd.Id, c.UserAccount.Id, m.ROLE_READ_WRITE) + cmd.AccountId = accountToAdd.Id + cmd.ForAccountId = c.UserAccount.Id + cmd.Role = m.ROLE_READ_WRITE - err = m.AddCollaborator(collaborator) + err = bus.Dispatch(&cmd) if err != nil { c.JsonApiErr(500, "Could not add collaborator", err) return } - c.Status(204) + c.JsonOK("Collaborator added") } func GetOtherAccounts(c *middleware.Context) { diff --git a/pkg/models/account.go b/pkg/models/account.go index 879686a2115..11c26954690 100644 --- a/pkg/models/account.go +++ b/pkg/models/account.go @@ -6,12 +6,10 @@ import ( ) var ( - SaveAccount func(account *Account) error - GetAccountByLogin func(emailOrName string) (*Account, error) - GetAccount func(accountId int64) (*Account, error) - GetOtherAccountsFor func(accountId int64) ([]*OtherAccount, error) - GetCollaboratorsForAccount func(accountId int64) ([]*CollaboratorInfo, error) - AddCollaborator func(collaborator *Collaborator) error + SaveAccount func(account *Account) error + GetAccountByLogin func(emailOrName string) (*Account, error) + GetAccount func(accountId int64) (*Account, error) + GetOtherAccountsFor func(accountId int64) ([]*OtherAccount, error) ) // Typed errors @@ -30,7 +28,7 @@ type Account struct { Id int64 Login string `xorm:"UNIQUE NOT NULL"` Email string `xorm:"UNIQUE NOT NULL"` - Name string `xorm:"UNIQUE NOT NULL"` + Name string FullName string Password string IsAdmin bool diff --git a/pkg/models/collaborator.go b/pkg/models/collaborator.go index c02dd0f8b17..39ffaeefa15 100644 --- a/pkg/models/collaborator.go +++ b/pkg/models/collaborator.go @@ -5,8 +5,8 @@ import ( ) const ( - ROLE_READ_WRITE = "ReadWrite" - ROLE_READ = "Read" + ROLE_READ_WRITE RoleType = "ReadWrite" + ROLE_READ = "Read" ) type RoleType string @@ -16,15 +16,16 @@ type Collaborator struct { AccountId int64 `xorm:"not null unique(uix_account_id_for_account_id)"` // The account that can use another account Role RoleType `xorm:"not null"` // Permission type ForAccountId int64 `xorm:"not null unique(uix_account_id_for_account_id)"` // The account being given access to - Created time.Time - Updated time.Time + + Created time.Time + Updated time.Time } -// read only projection -type CollaboratorInfo struct { - AccountId int64 - Role string - Email string +type AddCollaboratorCommand struct { + Email string `json:"email" binding:"required"` + AccountId int64 `json:"-"` + ForAccountId int64 `json:"-"` + Role RoleType `json:"-"` } func NewCollaborator(accountId int64, forAccountId int64, role RoleType) *Collaborator { diff --git a/pkg/stores/sqlstore/accounts.go b/pkg/stores/sqlstore/accounts.go index 1ac4206cdde..909d36e4e6c 100644 --- a/pkg/stores/sqlstore/accounts.go +++ b/pkg/stores/sqlstore/accounts.go @@ -1,12 +1,17 @@ package sqlstore import ( + "time" + + "github.com/go-xorm/xorm" + "github.com/torkelo/grafana-pro/pkg/bus" m "github.com/torkelo/grafana-pro/pkg/models" ) func init() { bus.AddHandler("sql", GetAccountInfo) + bus.AddHandler("sql", AddCollaborator) } func GetAccountInfo(query *m.GetAccountInfoQuery) error { @@ -33,6 +38,22 @@ func GetAccountInfo(query *m.GetAccountInfoQuery) error { return err } +func AddCollaborator(cmd *m.AddCollaboratorCommand) error { + return inTransaction(func(sess *xorm.Session) error { + + entity := m.Collaborator{ + AccountId: cmd.AccountId, + ForAccountId: cmd.ForAccountId, + Role: cmd.Role, + Created: time.Now(), + Updated: time.Now(), + } + + _, err := sess.Insert(&entity) + return err + }) +} + func SaveAccount(account *m.Account) error { var err error @@ -93,37 +114,6 @@ func GetAccountByLogin(emailOrLogin string) (*m.Account, error) { return account, nil } -func GetCollaboratorsForAccount(accountId int64) ([]*m.CollaboratorInfo, error) { - collaborators := make([]*m.CollaboratorInfo, 0) - - sess := x.Table("collaborator") - sess.Join("INNER", "account", "account.id=collaborator.account_Id") - sess.Where("collaborator.for_account_id=?", accountId) - err := sess.Find(&collaborators) - - return collaborators, err -} - -func AddCollaborator(collaborator *m.Collaborator) error { - var err error - - sess := x.NewSession() - defer sess.Close() - - if err = sess.Begin(); err != nil { - return err - } - - if _, err = sess.Insert(collaborator); err != nil { - sess.Rollback() - return err - } else if err = sess.Commit(); err != nil { - return err - } - - return nil -} - func GetOtherAccountsFor(accountId int64) ([]*m.OtherAccount, error) { collaborators := make([]*m.OtherAccount, 0) sess := x.Table("collaborator") diff --git a/pkg/stores/sqlstore/accounts_test.go b/pkg/stores/sqlstore/accounts_test.go index beff005b3a0..ce830f568bd 100644 --- a/pkg/stores/sqlstore/accounts_test.go +++ b/pkg/stores/sqlstore/accounts_test.go @@ -13,20 +13,52 @@ func TestAccountDataAccess(t *testing.T) { Convey("Testing Account DB Access", t, func() { InitTestDB(t) - Convey("Can save account", func() { - account := m.Account{ - Login: "login", - Email: "login@test.com", - Name: "name", + Convey("Given two saved accounts", func() { + ac1 := m.Account{ + Login: "ac1", + Email: "ac1@test.com", + Name: "ac1_name", + } + ac2 := m.Account{ + Login: "ac2", + Email: "ac2@test.com", + Name: "ac2_name", } - err := SaveAccount(&account) - - query := m.GetAccountInfoQuery{Id: account.Id} - err = GetAccountInfo(&query) - + err := SaveAccount(&ac1) + err = SaveAccount(&ac2) So(err, ShouldBeNil) - So(query.Result.Name, ShouldEqual, "name") + + Convey("Should be able to read account info projection", func() { + query := m.GetAccountInfoQuery{Id: ac1.Id} + err = GetAccountInfo(&query) + + So(err, ShouldBeNil) + So(query.Result.Name, ShouldEqual, "ac1_name") + }) + + Convey("Can add collaborator", func() { + cmd := m.AddCollaboratorCommand{ + AccountId: ac2.Id, + ForAccountId: ac1.Id, + Role: m.ROLE_READ_WRITE, + } + + err := AddCollaborator(&cmd) + Convey("Saved without error", func() { + So(err, ShouldBeNil) + }) + + Convey("Collaborator should be included in account info projection", func() { + query := m.GetAccountInfoQuery{Id: ac1.Id} + err = GetAccountInfo(&query) + + So(err, ShouldBeNil) + So(query.Result.Collaborators[0].AccountId, ShouldEqual, ac2.Id) + So(query.Result.Collaborators[0].Role, ShouldEqual, m.ROLE_READ_WRITE) + So(query.Result.Collaborators[0].Email, ShouldEqual, "ac2@test.com") + }) + }) }) }) } diff --git a/pkg/stores/sqlstore/sqlstore.go b/pkg/stores/sqlstore/sqlstore.go index c1a552e9295..95a05e0f178 100644 --- a/pkg/stores/sqlstore/sqlstore.go +++ b/pkg/stores/sqlstore/sqlstore.go @@ -43,8 +43,6 @@ func Init() { m.SaveDashboard = SaveDashboard m.SearchQuery = SearchQuery m.DeleteDashboard = DeleteDashboard - m.GetCollaboratorsForAccount = GetCollaboratorsForAccount - m.AddCollaborator = AddCollaborator } func NewEngine() (err error) {