Commit f04932aa by Torkel Ödegaard

More work on collaborators, and sql store

parent 4eefa734
...@@ -6,11 +6,13 @@ import ( ...@@ -6,11 +6,13 @@ import (
) )
var ( var (
CreateAccount func(acccount *Account) error CreateAccount func(acccount *Account) error
UpdateAccount func(acccount *Account) error UpdateAccount func(acccount *Account) error
GetAccountByLogin func(emailOrName string) (*Account, error) GetAccountByLogin func(emailOrName string) (*Account, error)
GetAccount func(accountId int64) (*Account, error) GetAccount func(accountId int64) (*Account, error)
GetOtherAccountsFor func(accountId int64) ([]*OtherAccount, error) GetOtherAccountsFor func(accountId int64) ([]*OtherAccount, error)
GetCollaboratorsForAccount func(accountId int64) ([]*CollaboratorInfo, error)
AddCollaborator func(collaborator *Collaborator) error
) )
// Typed errors // Typed errors
......
package models
import (
"time"
)
const (
ROLE_READ_WRITE = "ReadWrite"
ROLE_READ = "Read"
)
type RoleType string
type Collaborator struct {
Id int64
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
}
// read only projection
type CollaboratorInfo struct {
AccountId int64
Role string
Email string
}
func NewCollaborator(accountId int64, forAccountId int64) *Collaborator {
return &Collaborator{
AccountId: accountId,
ForAccountId: forAccountId,
Role: ROLE_READ,
Created: time.Now(),
Updated: time.Now(),
}
}
package api
import (
"github.com/torkelo/grafana-pro/pkg/middleware"
"github.com/torkelo/grafana-pro/pkg/models"
"github.com/torkelo/grafana-pro/pkg/routes/dtos"
"github.com/torkelo/grafana-pro/pkg/utils"
)
func GetAccount(c *middleware.Context) {
model := dtos.AccountInfo{
Name: c.UserAccount.Name,
Email: c.UserAccount.Email,
}
collaborators, err := models.GetCollaboratorsForAccount(c.UserAccount.Id)
if err != nil {
c.JsonApiErr(500, "Failed to fetch collaboratos", err)
return
}
for _, collaborator := range collaborators {
model.Collaborators = append(model.Collaborators, &dtos.Collaborator{
AccountId: collaborator.AccountId,
Role: collaborator.Role,
Email: collaborator.Email,
})
}
c.JSON(200, model)
}
func AddCollaborator(c *middleware.Context) {
var model dtos.AddCollaboratorCommand
if !c.JsonBody(&model) {
c.JSON(400, utils.DynMap{"message": "Invalid request"})
return
}
accountToAdd, err := models.GetAccountByLogin(model.Email)
if err != nil {
c.JSON(404, utils.DynMap{"message": "Collaborator not found"})
return
}
if accountToAdd.Id == c.UserAccount.Id {
c.JSON(400, utils.DynMap{"message": "Cannot add yourself as collaborator"})
return
}
var collaborator = models.NewCollaborator(accountToAdd.Id, c.UserAccount.Id)
collaborator.Role = models.ROLE_READ_WRITE
err = models.AddCollaborator(collaborator)
if err != nil {
c.JSON(400, utils.DynMap{"message": err.Error()})
return
}
c.Status(204)
}
...@@ -3,7 +3,7 @@ package api ...@@ -3,7 +3,7 @@ package api
import ( import (
"github.com/torkelo/grafana-pro/pkg/middleware" "github.com/torkelo/grafana-pro/pkg/middleware"
"github.com/torkelo/grafana-pro/pkg/models" "github.com/torkelo/grafana-pro/pkg/models"
"github.com/torkelo/grafana-pro/pkg/routes/apimodel" "github.com/torkelo/grafana-pro/pkg/routes/dtos"
"github.com/torkelo/grafana-pro/pkg/utils" "github.com/torkelo/grafana-pro/pkg/utils"
) )
...@@ -63,7 +63,7 @@ func convertToStringArray(arr []interface{}) []string { ...@@ -63,7 +63,7 @@ func convertToStringArray(arr []interface{}) []string {
} }
func PostDashboard(c *middleware.Context) { func PostDashboard(c *middleware.Context) {
var command apimodel.SaveDashboardCommand var command dtos.SaveDashboardCommand
if !c.JsonBody(&command) { if !c.JsonBody(&command) {
c.JsonApiErr(400, "bad request", nil) c.JsonApiErr(400, "bad request", nil)
......
package apimodel package dtos
import ( import (
"crypto/md5" "crypto/md5"
...@@ -8,19 +8,35 @@ import ( ...@@ -8,19 +8,35 @@ import (
"github.com/torkelo/grafana-pro/pkg/models" "github.com/torkelo/grafana-pro/pkg/models"
) )
type LoginResultDto struct { type LoginResult struct {
Status string `json:"status"` Status string `json:"status"`
User CurrentUserDto `json:"user"` User CurrentUser `json:"user"`
} }
type CurrentUserDto struct { type CurrentUser struct {
Login string `json:"login"` Login string `json:"login"`
Email string `json:"email"` Email string `json:"email"`
GravatarUrl string `json:"gravatarUrl"` GravatarUrl string `json:"gravatarUrl"`
} }
func NewCurrentUserDto(account *models.Account) *CurrentUserDto { type AccountInfo struct {
model := &CurrentUserDto{} Email string `json:"email"`
Name string `json:"name"`
Collaborators []*Collaborator `json:"collaborators"`
}
type Collaborator struct {
AccountId int64 `json:"accountId"`
Email string `json:"email"`
Role string `json:"role"`
}
type AddCollaboratorCommand struct {
Email string `json:"email" binding:"required"`
}
func NewCurrentUser(account *models.Account) *CurrentUser {
model := &CurrentUser{}
if account != nil { if account != nil {
model.Login = account.Login model.Login = account.Login
model.Email = account.Email model.Email = account.Email
......
...@@ -4,7 +4,7 @@ import ( ...@@ -4,7 +4,7 @@ import (
"github.com/Unknwon/macaron" "github.com/Unknwon/macaron"
"github.com/torkelo/grafana-pro/pkg/middleware" "github.com/torkelo/grafana-pro/pkg/middleware"
"github.com/torkelo/grafana-pro/pkg/routes/api" "github.com/torkelo/grafana-pro/pkg/routes/api"
"github.com/torkelo/grafana-pro/pkg/routes/apimodel" "github.com/torkelo/grafana-pro/pkg/routes/dtos"
"github.com/torkelo/grafana-pro/pkg/routes/login" "github.com/torkelo/grafana-pro/pkg/routes/login"
) )
...@@ -20,6 +20,11 @@ func Register(m *macaron.Macaron) { ...@@ -20,6 +20,11 @@ func Register(m *macaron.Macaron) {
m.Get("/login", Index) m.Get("/login", Index)
m.Get("/login/:name", login.OAuthLogin) m.Get("/login/:name", login.OAuthLogin)
// account
m.Get("/account/", auth, Index)
m.Get("/api/account/", auth, api.GetAccount)
m.Post("/api/account/collaborators/add", auth, api.AddCollaborator)
// user register // user register
m.Get("/register/*_", Index) m.Get("/register/*_", Index)
m.Post("/api/account", api.CreateAccount) m.Post("/api/account", api.CreateAccount)
...@@ -36,7 +41,7 @@ func Register(m *macaron.Macaron) { ...@@ -36,7 +41,7 @@ func Register(m *macaron.Macaron) {
} }
func Index(ctx *middleware.Context) { func Index(ctx *middleware.Context) {
ctx.Data["User"] = apimodel.NewCurrentUserDto(ctx.UserAccount) ctx.Data["User"] = dtos.NewCurrentUser(ctx.UserAccount)
ctx.HTML(200, "index") ctx.HTML(200, "index")
} }
......
package login package login
import ( import (
"github.com/gin-gonic/gin"
"github.com/torkelo/grafana-pro/pkg/log" "github.com/torkelo/grafana-pro/pkg/log"
"github.com/torkelo/grafana-pro/pkg/middleware" "github.com/torkelo/grafana-pro/pkg/middleware"
"github.com/torkelo/grafana-pro/pkg/models" "github.com/torkelo/grafana-pro/pkg/models"
"github.com/torkelo/grafana-pro/pkg/routes/apimodel" "github.com/torkelo/grafana-pro/pkg/routes/dtos"
"github.com/torkelo/grafana-pro/pkg/utils"
) )
type loginJsonModel struct { type loginJsonModel struct {
...@@ -18,24 +18,24 @@ func LoginPost(c *middleware.Context) { ...@@ -18,24 +18,24 @@ func LoginPost(c *middleware.Context) {
var loginModel loginJsonModel var loginModel loginJsonModel
if !c.JsonBody(&loginModel) { if !c.JsonBody(&loginModel) {
c.JSON(400, gin.H{"status": "bad request"}) c.JSON(400, utils.DynMap{"status": "bad request"})
return return
} }
account, err := models.GetAccountByLogin(loginModel.Email) account, err := models.GetAccountByLogin(loginModel.Email)
if err != nil { if err != nil {
c.JSON(401, gin.H{"status": "unauthorized"}) c.JSON(401, utils.DynMap{"status": "unauthorized"})
return return
} }
if loginModel.Password != account.Password { if loginModel.Password != account.Password {
c.JSON(401, gin.H{"status": "unauthorized"}) c.JSON(401, utils.DynMap{"status": "unauthorized"})
return return
} }
loginUserWithAccount(account, c) loginUserWithAccount(account, c)
var resp = &apimodel.LoginResultDto{} var resp = &dtos.LoginResult{}
resp.Status = "Logged in" resp.Status = "Logged in"
resp.User.Login = account.Login resp.User.Login = account.Login
...@@ -52,5 +52,5 @@ func loginUserWithAccount(account *models.Account, c *middleware.Context) { ...@@ -52,5 +52,5 @@ func loginUserWithAccount(account *models.Account, c *middleware.Context) {
func LogoutPost(c *middleware.Context) { func LogoutPost(c *middleware.Context) {
c.Session.Delete("accountId") c.Session.Delete("accountId")
c.JSON(200, gin.H{"status": "logged out"}) c.JSON(200, utils.DynMap{"status": "logged out"})
} }
...@@ -27,7 +27,7 @@ var ( ...@@ -27,7 +27,7 @@ var (
) )
func Init() { func Init() {
tables = append(tables, new(models.Account), new(models.Dashboard)) tables = append(tables, new(models.Account), new(models.Dashboard), new(models.Collaborator))
models.CreateAccount = CreateAccount models.CreateAccount = CreateAccount
models.GetAccount = GetAccount models.GetAccount = GetAccount
...@@ -36,6 +36,8 @@ func Init() { ...@@ -36,6 +36,8 @@ func Init() {
models.SaveDashboard = SaveDashboard models.SaveDashboard = SaveDashboard
models.SearchQuery = SearchQuery models.SearchQuery = SearchQuery
models.DeleteDashboard = DeleteDashboard models.DeleteDashboard = DeleteDashboard
models.GetCollaboratorsForAccount = GetCollaboratorsForAccount
models.AddCollaborator = AddCollaborator
} }
func LoadModelsConfig() { func LoadModelsConfig() {
......
...@@ -57,3 +57,31 @@ func GetAccountByLogin(emailOrLogin string) (*models.Account, error) { ...@@ -57,3 +57,31 @@ func GetAccountByLogin(emailOrLogin string) (*models.Account, error) {
return account, nil return account, nil
} }
func GetCollaboratorsForAccount(accountId int64) ([]*models.CollaboratorInfo, error) {
collaborators := make([]*models.CollaboratorInfo, 0)
sess := x.Table("Collaborator")
sess.Join("INNER", "Account", "Account.id=Collaborator.account_Id")
err := sess.Find(&collaborators)
return collaborators, err
}
func AddCollaborator(collaborator *models.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
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment