middleware_test.go 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. package middleware
  2. import (
  3. "encoding/json"
  4. "net/http"
  5. "net/http/httptest"
  6. "path/filepath"
  7. "testing"
  8. "github.com/Unknwon/macaron"
  9. "github.com/grafana/grafana/pkg/bus"
  10. m "github.com/grafana/grafana/pkg/models"
  11. "github.com/grafana/grafana/pkg/setting"
  12. "github.com/grafana/grafana/pkg/util"
  13. "github.com/macaron-contrib/session"
  14. . "github.com/smartystreets/goconvey/convey"
  15. )
  16. func TestMiddlewareContext(t *testing.T) {
  17. Convey("Given the grafana middleware", t, func() {
  18. middlewareScenario("middleware should add context to injector", func(sc *scenarioContext) {
  19. sc.fakeReq("GET", "/").exec()
  20. So(sc.context, ShouldNotBeNil)
  21. })
  22. middlewareScenario("Default middleware should allow get request", func(sc *scenarioContext) {
  23. sc.fakeReq("GET", "/").exec()
  24. So(sc.resp.Code, ShouldEqual, 200)
  25. })
  26. middlewareScenario("Non api request should init session", func(sc *scenarioContext) {
  27. sc.fakeReq("GET", "/").exec()
  28. So(sc.resp.Header().Get("Set-Cookie"), ShouldContainSubstring, "grafana_sess")
  29. })
  30. middlewareScenario("Invalid api key", func(sc *scenarioContext) {
  31. sc.apiKey = "invalid_key_test"
  32. sc.fakeReq("GET", "/").exec()
  33. Convey("Should not init session", func() {
  34. So(sc.resp.Header().Get("Set-Cookie"), ShouldBeEmpty)
  35. })
  36. Convey("Should return 401", func() {
  37. So(sc.resp.Code, ShouldEqual, 401)
  38. So(sc.respJson["message"], ShouldEqual, "Invalid API key")
  39. })
  40. })
  41. middlewareScenario("Valid api key", func(sc *scenarioContext) {
  42. keyhash := util.EncodePassword("v5nAwpMafFP6znaS4urhdWDLS5511M42", "asd")
  43. bus.AddHandler("test", func(query *m.GetApiKeyByNameQuery) error {
  44. query.Result = &m.ApiKey{OrgId: 12, Role: m.ROLE_EDITOR, Key: keyhash}
  45. return nil
  46. })
  47. sc.fakeReq("GET", "/").withValidApiKey().exec()
  48. Convey("Should return 200", func() {
  49. So(sc.resp.Code, ShouldEqual, 200)
  50. })
  51. Convey("Should init middleware context", func() {
  52. So(sc.context.IsSignedIn, ShouldEqual, true)
  53. So(sc.context.OrgId, ShouldEqual, 12)
  54. So(sc.context.OrgRole, ShouldEqual, m.ROLE_EDITOR)
  55. })
  56. })
  57. middlewareScenario("Valid api key, but does not match db hash", func(sc *scenarioContext) {
  58. keyhash := "something_not_matching"
  59. bus.AddHandler("test", func(query *m.GetApiKeyByNameQuery) error {
  60. query.Result = &m.ApiKey{OrgId: 12, Role: m.ROLE_EDITOR, Key: keyhash}
  61. return nil
  62. })
  63. sc.fakeReq("GET", "/").withValidApiKey().exec()
  64. Convey("Should return api key invalid", func() {
  65. So(sc.resp.Code, ShouldEqual, 401)
  66. So(sc.respJson["message"], ShouldEqual, "Invalid API key")
  67. })
  68. })
  69. middlewareScenario("UserId in session", func(sc *scenarioContext) {
  70. sc.fakeReq("GET", "/").handler(func(c *Context) {
  71. c.Session.Set(SESS_KEY_USERID, int64(12))
  72. }).exec()
  73. bus.AddHandler("test", func(query *m.GetSignedInUserQuery) error {
  74. query.Result = &m.SignedInUser{OrgId: 2, UserId: 12}
  75. return nil
  76. })
  77. sc.fakeReq("GET", "/").exec()
  78. Convey("should init context with user info", func() {
  79. So(sc.context.IsSignedIn, ShouldBeTrue)
  80. So(sc.context.UserId, ShouldEqual, 12)
  81. })
  82. })
  83. middlewareScenario("When anonymous access is enabled", func(sc *scenarioContext) {
  84. setting.AnonymousEnabled = true
  85. setting.AnonymousOrgName = "test"
  86. setting.AnonymousOrgRole = string(m.ROLE_EDITOR)
  87. bus.AddHandler("test", func(query *m.GetOrgByNameQuery) error {
  88. So(query.Name, ShouldEqual, "test")
  89. query.Result = &m.Org{Id: 2, Name: "test"}
  90. return nil
  91. })
  92. sc.fakeReq("GET", "/").exec()
  93. Convey("should init context with org info", func() {
  94. So(sc.context.UserId, ShouldEqual, 0)
  95. So(sc.context.OrgId, ShouldEqual, 2)
  96. So(sc.context.OrgRole, ShouldEqual, m.ROLE_EDITOR)
  97. })
  98. Convey("context signed in should be false", func() {
  99. So(sc.context.IsSignedIn, ShouldBeFalse)
  100. })
  101. })
  102. })
  103. }
  104. func middlewareScenario(desc string, fn scenarioFunc) {
  105. Convey(desc, func() {
  106. defer bus.ClearBusHandlers()
  107. sc := &scenarioContext{}
  108. viewsPath, _ := filepath.Abs("../../public/views")
  109. sc.m = macaron.New()
  110. sc.m.Use(macaron.Renderer(macaron.RenderOptions{
  111. Directory: viewsPath,
  112. Delims: macaron.Delims{Left: "[[", Right: "]]"},
  113. }))
  114. sc.m.Use(GetContextHandler())
  115. // mock out gc goroutine
  116. startSessionGC = func() {}
  117. sc.m.Use(Sessioner(&session.Options{}))
  118. sc.m.Get("/", func(c *Context) {
  119. sc.context = c
  120. if sc.handlerFunc != nil {
  121. sc.handlerFunc(sc.context)
  122. }
  123. })
  124. fn(sc)
  125. })
  126. }
  127. type scenarioContext struct {
  128. m *macaron.Macaron
  129. context *Context
  130. resp *httptest.ResponseRecorder
  131. apiKey string
  132. respJson map[string]interface{}
  133. handlerFunc handlerFunc
  134. req *http.Request
  135. }
  136. func (sc *scenarioContext) withValidApiKey() *scenarioContext {
  137. sc.apiKey = "eyJrIjoidjVuQXdwTWFmRlA2em5hUzR1cmhkV0RMUzU1MTFNNDIiLCJuIjoiYXNkIiwiaWQiOjF9"
  138. return sc
  139. }
  140. func (sc *scenarioContext) withInvalidApiKey() *scenarioContext {
  141. sc.apiKey = "nvalidhhhhds"
  142. return sc
  143. }
  144. func (sc *scenarioContext) fakeReq(method, url string) *scenarioContext {
  145. sc.resp = httptest.NewRecorder()
  146. req, err := http.NewRequest(method, url, nil)
  147. So(err, ShouldBeNil)
  148. sc.req = req
  149. // add session cookie from last request
  150. if sc.context != nil {
  151. if sc.context.Session.ID() != "" {
  152. req.Header.Add("Cookie", "grafana_sess="+sc.context.Session.ID()+";")
  153. }
  154. }
  155. return sc
  156. }
  157. func (sc *scenarioContext) handler(fn handlerFunc) *scenarioContext {
  158. sc.handlerFunc = fn
  159. return sc
  160. }
  161. func (sc *scenarioContext) exec() {
  162. if sc.apiKey != "" {
  163. sc.req.Header.Add("Authorization", "Bearer "+sc.apiKey)
  164. }
  165. sc.m.ServeHTTP(sc.resp, sc.req)
  166. if sc.resp.Header().Get("Content-Type") == "application/json; charset=UTF-8" {
  167. err := json.NewDecoder(sc.resp.Body).Decode(&sc.respJson)
  168. So(err, ShouldBeNil)
  169. }
  170. }
  171. type scenarioFunc func(c *scenarioContext)
  172. type handlerFunc func(c *Context)