Commit f04932aa by Torkel Ödegaard

More work on collaborators, and sql store

parent 4eefa734
......@@ -6,11 +6,13 @@ import (
)
var (
CreateAccount func(acccount *Account) error
UpdateAccount func(acccount *Account) error
GetAccountByLogin func(emailOrName string) (*Account, error)
GetAccount func(accountId int64) (*Account, error)
GetOtherAccountsFor func(accountId int64) ([]*OtherAccount, error)
CreateAccount func(acccount *Account) error
UpdateAccount func(acccount *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
)
// 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
import (
"github.com/torkelo/grafana-pro/pkg/middleware"
"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"
)
......@@ -63,7 +63,7 @@ func convertToStringArray(arr []interface{}) []string {
}
func PostDashboard(c *middleware.Context) {
var command apimodel.SaveDashboardCommand
var command dtos.SaveDashboardCommand
if !c.JsonBody(&command) {
c.JsonApiErr(400, "bad request", nil)
......
package apimodel
package dtos
import (
"crypto/md5"
......@@ -8,19 +8,35 @@ import (
"github.com/torkelo/grafana-pro/pkg/models"
)
type LoginResultDto struct {
Status string `json:"status"`
User CurrentUserDto `json:"user"`
type LoginResult struct {
Status string `json:"status"`
User CurrentUser `json:"user"`
}
type CurrentUserDto struct {
type CurrentUser struct {
Login string `json:"login"`
Email string `json:"email"`
GravatarUrl string `json:"gravatarUrl"`
}
func NewCurrentUserDto(account *models.Account) *CurrentUserDto {
model := &CurrentUserDto{}
type AccountInfo struct {
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 {
model.Login = account.Login
model.Email = account.Email
......
......@@ -4,7 +4,7 @@ import (
"github.com/Unknwon/macaron"
"github.com/torkelo/grafana-pro/pkg/middleware"
"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"
)
......@@ -20,6 +20,11 @@ func Register(m *macaron.Macaron) {
m.Get("/login", Index)
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
m.Get("/register/*_", Index)
m.Post("/api/account", api.CreateAccount)
......@@ -36,7 +41,7 @@ func Register(m *macaron.Macaron) {
}
func Index(ctx *middleware.Context) {
ctx.Data["User"] = apimodel.NewCurrentUserDto(ctx.UserAccount)
ctx.Data["User"] = dtos.NewCurrentUser(ctx.UserAccount)
ctx.HTML(200, "index")
}
......
package login
import (
"github.com/gin-gonic/gin"
"github.com/torkelo/grafana-pro/pkg/log"
"github.com/torkelo/grafana-pro/pkg/middleware"
"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 {
......@@ -18,24 +18,24 @@ func LoginPost(c *middleware.Context) {
var loginModel loginJsonModel
if !c.JsonBody(&loginModel) {
c.JSON(400, gin.H{"status": "bad request"})
c.JSON(400, utils.DynMap{"status": "bad request"})
return
}
account, err := models.GetAccountByLogin(loginModel.Email)
if err != nil {
c.JSON(401, gin.H{"status": "unauthorized"})
c.JSON(401, utils.DynMap{"status": "unauthorized"})
return
}
if loginModel.Password != account.Password {
c.JSON(401, gin.H{"status": "unauthorized"})
c.JSON(401, utils.DynMap{"status": "unauthorized"})
return
}
loginUserWithAccount(account, c)
var resp = &apimodel.LoginResultDto{}
var resp = &dtos.LoginResult{}
resp.Status = "Logged in"
resp.User.Login = account.Login
......@@ -52,5 +52,5 @@ func loginUserWithAccount(account *models.Account, c *middleware.Context) {
func LogoutPost(c *middleware.Context) {
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 (
)
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.GetAccount = GetAccount
......@@ -36,6 +36,8 @@ func Init() {
models.SaveDashboard = SaveDashboard
models.SearchQuery = SearchQuery
models.DeleteDashboard = DeleteDashboard
models.GetCollaboratorsForAccount = GetCollaboratorsForAccount
models.AddCollaborator = AddCollaborator
}
func LoadModelsConfig() {
......
......@@ -57,3 +57,31 @@ func GetAccountByLogin(emailOrLogin string) (*models.Account, error) {
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