grafana_login_test.go 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. package login
  2. import (
  3. "testing"
  4. . "github.com/smartystreets/goconvey/convey"
  5. "github.com/grafana/grafana/pkg/bus"
  6. m "github.com/grafana/grafana/pkg/models"
  7. )
  8. func TestGrafanaLogin(t *testing.T) {
  9. Convey("Login using Grafana DB", t, func() {
  10. grafanaLoginScenario("When login with non-existing user", func(sc *grafanaLoginScenarioContext) {
  11. sc.withNonExistingUser()
  12. err := loginUsingGrafanaDB(sc.loginUserQuery)
  13. Convey("it should result in user not found error", func() {
  14. So(err, ShouldEqual, m.ErrUserNotFound)
  15. })
  16. Convey("it should not call password validation", func() {
  17. So(sc.validatePasswordCalled, ShouldBeFalse)
  18. })
  19. Convey("it should not pupulate user object", func() {
  20. So(sc.loginUserQuery.User, ShouldBeNil)
  21. })
  22. })
  23. grafanaLoginScenario("When login with invalid credentials", func(sc *grafanaLoginScenarioContext) {
  24. sc.withInvalidPassword()
  25. err := loginUsingGrafanaDB(sc.loginUserQuery)
  26. Convey("it should result in invalid credentials error", func() {
  27. So(err, ShouldEqual, ErrInvalidCredentials)
  28. })
  29. Convey("it should call password validation", func() {
  30. So(sc.validatePasswordCalled, ShouldBeTrue)
  31. })
  32. Convey("it should not pupulate user object", func() {
  33. So(sc.loginUserQuery.User, ShouldBeNil)
  34. })
  35. })
  36. grafanaLoginScenario("When login with valid credentials", func(sc *grafanaLoginScenarioContext) {
  37. sc.withValidCredentials()
  38. err := loginUsingGrafanaDB(sc.loginUserQuery)
  39. Convey("it should not result in error", func() {
  40. So(err, ShouldBeNil)
  41. })
  42. Convey("it should call password validation", func() {
  43. So(sc.validatePasswordCalled, ShouldBeTrue)
  44. })
  45. Convey("it should pupulate user object", func() {
  46. So(sc.loginUserQuery.User, ShouldNotBeNil)
  47. So(sc.loginUserQuery.User.Login, ShouldEqual, sc.loginUserQuery.Username)
  48. So(sc.loginUserQuery.User.Password, ShouldEqual, sc.loginUserQuery.Password)
  49. })
  50. })
  51. grafanaLoginScenario("When login with disabled user", func(sc *grafanaLoginScenarioContext) {
  52. sc.withDisabledUser()
  53. err := loginUsingGrafanaDB(sc.loginUserQuery)
  54. Convey("it should return user is disabled error", func() {
  55. So(err, ShouldEqual, ErrUserDisabled)
  56. })
  57. Convey("it should not call password validation", func() {
  58. So(sc.validatePasswordCalled, ShouldBeFalse)
  59. })
  60. Convey("it should not pupulate user object", func() {
  61. So(sc.loginUserQuery.User, ShouldBeNil)
  62. })
  63. })
  64. })
  65. }
  66. type grafanaLoginScenarioContext struct {
  67. loginUserQuery *m.LoginUserQuery
  68. validatePasswordCalled bool
  69. }
  70. type grafanaLoginScenarioFunc func(c *grafanaLoginScenarioContext)
  71. func grafanaLoginScenario(desc string, fn grafanaLoginScenarioFunc) {
  72. Convey(desc, func() {
  73. origValidatePassword := validatePassword
  74. sc := &grafanaLoginScenarioContext{
  75. loginUserQuery: &m.LoginUserQuery{
  76. Username: "user",
  77. Password: "pwd",
  78. IpAddress: "192.168.1.1:56433",
  79. },
  80. validatePasswordCalled: false,
  81. }
  82. defer func() {
  83. validatePassword = origValidatePassword
  84. }()
  85. fn(sc)
  86. })
  87. }
  88. func mockPasswordValidation(valid bool, sc *grafanaLoginScenarioContext) {
  89. validatePassword = func(providedPassword string, userPassword string, userSalt string) error {
  90. sc.validatePasswordCalled = true
  91. if !valid {
  92. return ErrInvalidCredentials
  93. }
  94. return nil
  95. }
  96. }
  97. func (sc *grafanaLoginScenarioContext) getUserByLoginQueryReturns(user *m.User) {
  98. bus.AddHandler("test", func(query *m.GetUserByLoginQuery) error {
  99. if user == nil {
  100. return m.ErrUserNotFound
  101. }
  102. query.Result = user
  103. return nil
  104. })
  105. }
  106. func (sc *grafanaLoginScenarioContext) withValidCredentials() {
  107. sc.getUserByLoginQueryReturns(&m.User{
  108. Id: 1,
  109. Login: sc.loginUserQuery.Username,
  110. Password: sc.loginUserQuery.Password,
  111. Salt: "salt",
  112. })
  113. mockPasswordValidation(true, sc)
  114. }
  115. func (sc *grafanaLoginScenarioContext) withNonExistingUser() {
  116. sc.getUserByLoginQueryReturns(nil)
  117. }
  118. func (sc *grafanaLoginScenarioContext) withInvalidPassword() {
  119. sc.getUserByLoginQueryReturns(&m.User{
  120. Password: sc.loginUserQuery.Password,
  121. Salt: "salt",
  122. })
  123. mockPasswordValidation(false, sc)
  124. }
  125. func (sc *grafanaLoginScenarioContext) withDisabledUser() {
  126. sc.getUserByLoginQueryReturns(&m.User{
  127. IsDisabled: true,
  128. })
  129. }