Commit 951ce0a1 by Torkel Ödegaard

API token -> API key rename

parent db371d2a
Subproject commit d2f21bc93e96d9ac36b1925c0b0b137a7edc94d2 Subproject commit 11b74baf7920bcd4e39b5e77bfb49e6b08752dc2
...@@ -58,13 +58,13 @@ func Register(r *macaron.Macaron) { ...@@ -58,13 +58,13 @@ func Register(r *macaron.Macaron) {
r.Delete("/users/:id", RemoveAccountUser) r.Delete("/users/:id", RemoveAccountUser)
}, reqAccountAdmin) }, reqAccountAdmin)
// Token // auth api keys
r.Group("/tokens", func() { r.Group("/auth/keys", func() {
r.Combo("/"). r.Combo("/").
Get(GetTokens). Get(GetApiKeys).
Post(bind(m.AddTokenCommand{}), AddToken). Post(bind(m.AddApiKeyCommand{}), AddApiKey).
Put(bind(m.UpdateTokenCommand{}), UpdateToken) Put(bind(m.UpdateApiKeyCommand{}), UpdateApiKey)
r.Delete("/:id", DeleteToken) r.Delete("/:id", DeleteApiKey)
}, reqAccountAdmin) }, reqAccountAdmin)
// Data sources // Data sources
......
...@@ -7,65 +7,65 @@ import ( ...@@ -7,65 +7,65 @@ import (
"github.com/torkelo/grafana-pro/pkg/util" "github.com/torkelo/grafana-pro/pkg/util"
) )
func GetTokens(c *middleware.Context) { func GetApiKeys(c *middleware.Context) {
query := m.GetTokensQuery{AccountId: c.AccountId} query := m.GetApiKeysQuery{AccountId: c.AccountId}
if err := bus.Dispatch(&query); err != nil { if err := bus.Dispatch(&query); err != nil {
c.JsonApiErr(500, "Failed to list tokens", err) c.JsonApiErr(500, "Failed to list api keys", err)
return return
} }
result := make([]*m.TokenDTO, len(query.Result)) result := make([]*m.ApiKeyDTO, len(query.Result))
for i, t := range query.Result { for i, t := range query.Result {
result[i] = &m.TokenDTO{ result[i] = &m.ApiKeyDTO{
Id: t.Id, Id: t.Id,
Name: t.Name, Name: t.Name,
Role: t.Role, Role: t.Role,
Token: t.Token, Key: t.Key,
} }
} }
c.JSON(200, result) c.JSON(200, result)
} }
func DeleteToken(c *middleware.Context) { func DeleteApiKey(c *middleware.Context) {
id := c.ParamsInt64(":id") id := c.ParamsInt64(":id")
cmd := &m.DeleteTokenCommand{Id: id, AccountId: c.AccountId} cmd := &m.DeleteApiKeyCommand{Id: id, AccountId: c.AccountId}
err := bus.Dispatch(cmd) err := bus.Dispatch(cmd)
if err != nil { if err != nil {
c.JsonApiErr(500, "Failed to delete token", err) c.JsonApiErr(500, "Failed to delete API key", err)
return return
} }
c.JsonOK("Token deleted") c.JsonOK("API key deleted")
} }
func AddToken(c *middleware.Context, cmd m.AddTokenCommand) { func AddApiKey(c *middleware.Context, cmd m.AddApiKeyCommand) {
if !cmd.Role.IsValid() { if !cmd.Role.IsValid() {
c.JsonApiErr(400, "Invalid role specified", nil) c.JsonApiErr(400, "Invalid role specified", nil)
return return
} }
cmd.AccountId = c.AccountId cmd.AccountId = c.AccountId
cmd.Token = util.GetRandomString(64) cmd.Key = util.GetRandomString(64)
if err := bus.Dispatch(&cmd); err != nil { if err := bus.Dispatch(&cmd); err != nil {
c.JsonApiErr(500, "Failed to add token", err) c.JsonApiErr(500, "Failed to add API key", err)
return return
} }
result := &m.TokenDTO{ result := &m.ApiKeyDTO{
Id: cmd.Result.Id, Id: cmd.Result.Id,
Name: cmd.Result.Name, Name: cmd.Result.Name,
Role: cmd.Result.Role, Role: cmd.Result.Role,
Token: cmd.Result.Token, Key: cmd.Result.Key,
} }
c.JSON(200, result) c.JSON(200, result)
} }
func UpdateToken(c *middleware.Context, cmd m.UpdateTokenCommand) { func UpdateApiKey(c *middleware.Context, cmd m.UpdateApiKeyCommand) {
if !cmd.Role.IsValid() { if !cmd.Role.IsValid() {
c.JsonApiErr(400, "Invalid role specified", nil) c.JsonApiErr(400, "Invalid role specified", nil)
return return
...@@ -75,9 +75,9 @@ func UpdateToken(c *middleware.Context, cmd m.UpdateTokenCommand) { ...@@ -75,9 +75,9 @@ func UpdateToken(c *middleware.Context, cmd m.UpdateTokenCommand) {
err := bus.Dispatch(&cmd) err := bus.Dispatch(&cmd)
if err != nil { if err != nil {
c.JsonApiErr(500, "Failed to update token", err) c.JsonApiErr(500, "Failed to update api key", err)
return return
} }
c.JsonOK("Token updated") c.JsonOK("API key updated")
} }
...@@ -31,12 +31,12 @@ func getRequestUserId(c *Context) int64 { ...@@ -31,12 +31,12 @@ func getRequestUserId(c *Context) int64 {
return 0 return 0
} }
func getApiToken(c *Context) string { func getApiKey(c *Context) string {
header := c.Req.Header.Get("Authorization") header := c.Req.Header.Get("Authorization")
parts := strings.SplitN(header, " ", 2) parts := strings.SplitN(header, " ", 2)
if len(parts) == 2 || parts[0] == "Bearer" { if len(parts) == 2 || parts[0] == "Bearer" {
token := parts[1] key := parts[1]
return token return key
} }
return "" return ""
......
...@@ -39,22 +39,22 @@ func GetContextHandler() macaron.Handler { ...@@ -39,22 +39,22 @@ func GetContextHandler() macaron.Handler {
ctx.IsSignedIn = true ctx.IsSignedIn = true
ctx.SignedInUser = query.Result ctx.SignedInUser = query.Result
} }
} else if token := getApiToken(ctx); token != "" { } else if key := getApiKey(ctx); key != "" {
// Try API Key auth // Try API Key auth
tokenQuery := m.GetTokenByTokenQuery{Token: token} keyQuery := m.GetApiKeyByKeyQuery{Key: key}
if err := bus.Dispatch(&tokenQuery); err != nil { if err := bus.Dispatch(&keyQuery); err != nil {
ctx.JsonApiErr(401, "Invalid token", err) ctx.JsonApiErr(401, "Invalid API key", err)
return return
} else { } else {
tokenInfo := tokenQuery.Result keyInfo := keyQuery.Result
ctx.IsSignedIn = true ctx.IsSignedIn = true
ctx.SignedInUser = &m.SignedInUser{} ctx.SignedInUser = &m.SignedInUser{}
// TODO: fix this // TODO: fix this
ctx.AccountRole = tokenInfo.Role ctx.AccountRole = keyInfo.Role
ctx.ApiKeyId = tokenInfo.Id ctx.ApiKeyId = keyInfo.Id
ctx.AccountId = tokenInfo.AccountId ctx.AccountId = keyInfo.AccountId
} }
} }
......
...@@ -5,62 +5,61 @@ import ( ...@@ -5,62 +5,61 @@ import (
"time" "time"
) )
var ErrInvalidToken = errors.New("Invalid token") var ErrInvalidApiKey = errors.New("Invalid API Key")
type Token struct { type ApiKey struct {
Id int64 Id int64
AccountId int64 `xorm:"not null unique(uix_account_id_name)"` AccountId int64
Name string `xorm:"not null unique(uix_account_id_name)"` Name string
Token string `xorm:"UNIQUE NOT NULL"` Key string
Role RoleType `xorm:"not null"` Role RoleType
Created time.Time Created time.Time
Updated time.Time Updated time.Time
} }
// --------------------- // ---------------------
// COMMANDS // COMMANDS
type AddTokenCommand struct { type AddApiKeyCommand struct {
Name string `json:"name" binding:"required"` Name string `json:"name" binding:"required"`
Role RoleType `json:"role" binding:"required"` Role RoleType `json:"role" binding:"required"`
AccountId int64 `json:"-"` AccountId int64 `json:"-"`
Token string `json:"-"` Key string `json:"-"`
Result *Token `json:"-"`
Result *ApiKey `json:"-"`
} }
type UpdateTokenCommand struct { type UpdateApiKeyCommand struct {
Id int64 `json:"id"` Id int64 `json:"id"`
Name string `json:"name"` Name string `json:"name"`
Role RoleType `json:"role"` Role RoleType `json:"role"`
AccountId int64 `json:"-"` AccountId int64 `json:"-"`
Result *Token `json:"-"`
} }
type DeleteTokenCommand struct { type DeleteApiKeyCommand struct {
Id int64 `json:"id"` Id int64 `json:"id"`
AccountId int64 `json:"-"` AccountId int64 `json:"-"`
Result *Token `json:"-"`
} }
// ---------------------- // ----------------------
// QUERIES // QUERIES
type GetTokensQuery struct { type GetApiKeysQuery struct {
AccountId int64 AccountId int64
Result []*Token Result []*ApiKey
} }
type GetTokenByTokenQuery struct { type GetApiKeyByKeyQuery struct {
Token string Key string
Result *Token Result *ApiKey
} }
// ------------------------ // ------------------------
// DTO & Projections // DTO & Projections
type TokenDTO struct { type ApiKeyDTO struct {
Id int64 `json:"id"` Id int64 `json:"id"`
Name string `json:"name"` Name string `json:"name"`
Token string `json:"token"` Key string `json:"key"`
Role RoleType `json:"role"` Role RoleType `json:"role"`
} }
...@@ -9,35 +9,35 @@ import ( ...@@ -9,35 +9,35 @@ import (
) )
func init() { func init() {
bus.AddHandler("sql", GetTokens) bus.AddHandler("sql", GetApiKeys)
bus.AddHandler("sql", GetTokenByToken) bus.AddHandler("sql", GetApiKeyByKey)
bus.AddHandler("sql", UpdateToken) bus.AddHandler("sql", UpdateApiKey)
bus.AddHandler("sql", DeleteToken) bus.AddHandler("sql", DeleteApiKey)
bus.AddHandler("sql", AddToken) bus.AddHandler("sql", AddApiKey)
} }
func GetTokens(query *m.GetTokensQuery) error { func GetApiKeys(query *m.GetApiKeysQuery) error {
sess := x.Limit(100, 0).Where("account_id=?", query.AccountId).Asc("name") sess := x.Limit(100, 0).Where("account_id=?", query.AccountId).Asc("name")
query.Result = make([]*m.Token, 0) query.Result = make([]*m.ApiKey, 0)
return sess.Find(&query.Result) return sess.Find(&query.Result)
} }
func DeleteToken(cmd *m.DeleteTokenCommand) error { func DeleteApiKey(cmd *m.DeleteApiKeyCommand) error {
return inTransaction(func(sess *xorm.Session) error { return inTransaction(func(sess *xorm.Session) error {
var rawSql = "DELETE FROM token WHERE id=? and account_id=?" var rawSql = "DELETE FROM api_key WHERE id=? and account_id=?"
_, err := sess.Exec(rawSql, cmd.Id, cmd.AccountId) _, err := sess.Exec(rawSql, cmd.Id, cmd.AccountId)
return err return err
}) })
} }
func AddToken(cmd *m.AddTokenCommand) error { func AddApiKey(cmd *m.AddApiKeyCommand) error {
return inTransaction(func(sess *xorm.Session) error { return inTransaction(func(sess *xorm.Session) error {
t := m.Token{ t := m.ApiKey{
AccountId: cmd.AccountId, AccountId: cmd.AccountId,
Name: cmd.Name, Name: cmd.Name,
Role: cmd.Role, Role: cmd.Role,
Token: cmd.Token, Key: cmd.Key,
Created: time.Now(), Created: time.Now(),
Updated: time.Now(), Updated: time.Now(),
} }
...@@ -50,32 +50,30 @@ func AddToken(cmd *m.AddTokenCommand) error { ...@@ -50,32 +50,30 @@ func AddToken(cmd *m.AddTokenCommand) error {
}) })
} }
func UpdateToken(cmd *m.UpdateTokenCommand) error { func UpdateApiKey(cmd *m.UpdateApiKeyCommand) error {
return inTransaction(func(sess *xorm.Session) error { return inTransaction(func(sess *xorm.Session) error {
t := m.Token{ t := m.ApiKey{
Id: cmd.Id, Id: cmd.Id,
AccountId: cmd.AccountId, AccountId: cmd.AccountId,
Name: cmd.Name, Name: cmd.Name,
Role: cmd.Role, Role: cmd.Role,
Updated: time.Now(), Updated: time.Now(),
} }
_, err := sess.Where("id=? and account_id=?", t.Id, t.AccountId).Update(&t) _, err := sess.Where("id=? and account_id=?", t.Id, t.AccountId).Update(&t)
return err return err
}) })
} }
func GetTokenByToken(query *m.GetTokenByTokenQuery) error { func GetApiKeyByKey(query *m.GetApiKeyByKeyQuery) error {
var token m.Token var apikey m.ApiKey
has, err := x.Where("token=?", query.Token).Get(&token) has, err := x.Where("key=?", query.Key).Get(&apikey)
if err != nil { if err != nil {
return err return err
} else if has == false { } else if has == false {
return m.ErrInvalidToken return m.ErrInvalidApiKey
} }
query.Result = &token query.Result = &apikey
return nil return nil
} }
...@@ -2,13 +2,19 @@ package sqlstore ...@@ -2,13 +2,19 @@ package sqlstore
import . "github.com/torkelo/grafana-pro/pkg/services/sqlstore/migrator" import . "github.com/torkelo/grafana-pro/pkg/services/sqlstore/migrator"
// --- Migration Guide line ---
// 1. Never change a migration that is committed and pushed to master
// 2. Always add new migrations (to change or undo previous migrations)
// 3. Some migraitons are not yet written (rename column, table, drop table, index etc)
// 4
func addMigrations(mg *Migrator) { func addMigrations(mg *Migrator) {
addMigrationLogMigrations(mg) addMigrationLogMigrations(mg)
addUserMigrations(mg) addUserMigrations(mg)
addAccountMigrations(mg) addAccountMigrations(mg)
addDashboardMigration(mg) addDashboardMigration(mg)
addDataSourceMigration(mg) addDataSourceMigration(mg)
addTokenMigrations(mg) addApiKeyMigrations(mg)
} }
func addMigrationLogMigrations(mg *Migrator) { func addMigrationLogMigrations(mg *Migrator) {
...@@ -131,19 +137,22 @@ func addDataSourceMigration(mg *Migrator) { ...@@ -131,19 +137,22 @@ func addDataSourceMigration(mg *Migrator) {
Table("data_source").Columns("account_id", "name").Unique()) Table("data_source").Columns("account_id", "name").Unique())
} }
func addTokenMigrations(mg *Migrator) { func addApiKeyMigrations(mg *Migrator) {
mg.AddMigration("create token table", new(AddTableMigration). mg.AddMigration("create api_key table", new(AddTableMigration).
Name("token").WithColumns( Name("api_key").WithColumns(
&Column{Name: "id", Type: DB_BigInt, IsPrimaryKey: true, IsAutoIncrement: true}, &Column{Name: "id", Type: DB_BigInt, IsPrimaryKey: true, IsAutoIncrement: true},
&Column{Name: "account_id", Type: DB_BigInt, Nullable: false}, &Column{Name: "account_id", Type: DB_BigInt, Nullable: false},
&Column{Name: "name", Type: DB_NVarchar, Length: 255, Nullable: false}, &Column{Name: "name", Type: DB_NVarchar, Length: 255, Nullable: false},
&Column{Name: "token", Type: DB_NVarchar, Length: 255, Nullable: false}, &Column{Name: "key", Type: DB_Varchar, Length: 64, Nullable: false},
&Column{Name: "role", Type: DB_NVarchar, Length: 255, Nullable: false}, &Column{Name: "role", Type: DB_NVarchar, Length: 255, Nullable: false},
&Column{Name: "created", Type: DB_DateTime, Nullable: false}, &Column{Name: "created", Type: DB_DateTime, Nullable: false},
&Column{Name: "updated", Type: DB_DateTime, Nullable: false}, &Column{Name: "updated", Type: DB_DateTime, Nullable: false},
)) ))
//------- indexes ------------------ //------- indexes ------------------
mg.AddMigration("add index token.account_id", new(AddIndexMigration). mg.AddMigration("add index api_key.account_id", new(AddIndexMigration).
Table("token").Columns("account_id")) Table("api_key").Columns("account_id"))
mg.AddMigration("add index api_key.key", new(AddIndexMigration).
Table("api_key").Columns("key").Unique())
} }
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