ldap_test.go 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632
  1. package login
  2. import (
  3. "context"
  4. "crypto/tls"
  5. "testing"
  6. "github.com/grafana/grafana/pkg/bus"
  7. "github.com/grafana/grafana/pkg/log"
  8. m "github.com/grafana/grafana/pkg/models"
  9. . "github.com/smartystreets/goconvey/convey"
  10. "gopkg.in/ldap.v3"
  11. )
  12. func TestLdapAuther(t *testing.T) {
  13. Convey("initialBind", t, func() {
  14. Convey("Given bind dn and password configured", func() {
  15. conn := &mockLdapConn{}
  16. var actualUsername, actualPassword string
  17. conn.bindProvider = func(username, password string) error {
  18. actualUsername = username
  19. actualPassword = password
  20. return nil
  21. }
  22. ldapAuther := &ldapAuther{
  23. conn: conn,
  24. server: &LdapServerConf{
  25. BindDN: "cn=%s,o=users,dc=grafana,dc=org",
  26. BindPassword: "bindpwd",
  27. },
  28. }
  29. err := ldapAuther.initialBind("user", "pwd")
  30. So(err, ShouldBeNil)
  31. So(ldapAuther.requireSecondBind, ShouldBeTrue)
  32. So(actualUsername, ShouldEqual, "cn=user,o=users,dc=grafana,dc=org")
  33. So(actualPassword, ShouldEqual, "bindpwd")
  34. })
  35. Convey("Given bind dn configured", func() {
  36. conn := &mockLdapConn{}
  37. var actualUsername, actualPassword string
  38. conn.bindProvider = func(username, password string) error {
  39. actualUsername = username
  40. actualPassword = password
  41. return nil
  42. }
  43. ldapAuther := &ldapAuther{
  44. conn: conn,
  45. server: &LdapServerConf{
  46. BindDN: "cn=%s,o=users,dc=grafana,dc=org",
  47. },
  48. }
  49. err := ldapAuther.initialBind("user", "pwd")
  50. So(err, ShouldBeNil)
  51. So(ldapAuther.requireSecondBind, ShouldBeFalse)
  52. So(actualUsername, ShouldEqual, "cn=user,o=users,dc=grafana,dc=org")
  53. So(actualPassword, ShouldEqual, "pwd")
  54. })
  55. Convey("Given empty bind dn and password", func() {
  56. conn := &mockLdapConn{}
  57. unauthenticatedBindWasCalled := false
  58. var actualUsername string
  59. conn.unauthenticatedBindProvider = func(username string) error {
  60. unauthenticatedBindWasCalled = true
  61. actualUsername = username
  62. return nil
  63. }
  64. ldapAuther := &ldapAuther{
  65. conn: conn,
  66. server: &LdapServerConf{},
  67. }
  68. err := ldapAuther.initialBind("user", "pwd")
  69. So(err, ShouldBeNil)
  70. So(ldapAuther.requireSecondBind, ShouldBeTrue)
  71. So(unauthenticatedBindWasCalled, ShouldBeTrue)
  72. So(actualUsername, ShouldBeEmpty)
  73. })
  74. })
  75. Convey("serverBind", t, func() {
  76. Convey("Given bind dn and password configured", func() {
  77. conn := &mockLdapConn{}
  78. var actualUsername, actualPassword string
  79. conn.bindProvider = func(username, password string) error {
  80. actualUsername = username
  81. actualPassword = password
  82. return nil
  83. }
  84. ldapAuther := &ldapAuther{
  85. conn: conn,
  86. server: &LdapServerConf{
  87. BindDN: "o=users,dc=grafana,dc=org",
  88. BindPassword: "bindpwd",
  89. },
  90. }
  91. err := ldapAuther.serverBind()
  92. So(err, ShouldBeNil)
  93. So(actualUsername, ShouldEqual, "o=users,dc=grafana,dc=org")
  94. So(actualPassword, ShouldEqual, "bindpwd")
  95. })
  96. Convey("Given bind dn configured", func() {
  97. conn := &mockLdapConn{}
  98. unauthenticatedBindWasCalled := false
  99. var actualUsername string
  100. conn.unauthenticatedBindProvider = func(username string) error {
  101. unauthenticatedBindWasCalled = true
  102. actualUsername = username
  103. return nil
  104. }
  105. ldapAuther := &ldapAuther{
  106. conn: conn,
  107. server: &LdapServerConf{
  108. BindDN: "o=users,dc=grafana,dc=org",
  109. },
  110. }
  111. err := ldapAuther.serverBind()
  112. So(err, ShouldBeNil)
  113. So(unauthenticatedBindWasCalled, ShouldBeTrue)
  114. So(actualUsername, ShouldEqual, "o=users,dc=grafana,dc=org")
  115. })
  116. Convey("Given empty bind dn and password", func() {
  117. conn := &mockLdapConn{}
  118. unauthenticatedBindWasCalled := false
  119. var actualUsername string
  120. conn.unauthenticatedBindProvider = func(username string) error {
  121. unauthenticatedBindWasCalled = true
  122. actualUsername = username
  123. return nil
  124. }
  125. ldapAuther := &ldapAuther{
  126. conn: conn,
  127. server: &LdapServerConf{},
  128. }
  129. err := ldapAuther.serverBind()
  130. So(err, ShouldBeNil)
  131. So(unauthenticatedBindWasCalled, ShouldBeTrue)
  132. So(actualUsername, ShouldBeEmpty)
  133. })
  134. })
  135. Convey("When translating ldap user to grafana user", t, func() {
  136. var user1 = &m.User{}
  137. bus.AddHandlerCtx("test", func(ctx context.Context, cmd *m.UpsertUserCommand) error {
  138. cmd.Result = user1
  139. cmd.Result.Login = "torkelo"
  140. return nil
  141. })
  142. Convey("Given no ldap group map match", func() {
  143. ldapAuther := NewLdapAuthenticator(&LdapServerConf{
  144. LdapGroups: []*LdapGroupToOrgRole{{}},
  145. })
  146. _, err := ldapAuther.GetGrafanaUserFor(nil, &LdapUserInfo{})
  147. So(err, ShouldEqual, ErrInvalidCredentials)
  148. })
  149. ldapAutherScenario("Given wildcard group match", func(sc *scenarioContext) {
  150. ldapAuther := NewLdapAuthenticator(&LdapServerConf{
  151. LdapGroups: []*LdapGroupToOrgRole{
  152. {GroupDN: "*", OrgRole: "Admin"},
  153. },
  154. })
  155. sc.userQueryReturns(user1)
  156. result, err := ldapAuther.GetGrafanaUserFor(nil, &LdapUserInfo{})
  157. So(err, ShouldBeNil)
  158. So(result, ShouldEqual, user1)
  159. })
  160. ldapAutherScenario("Given exact group match", func(sc *scenarioContext) {
  161. ldapAuther := NewLdapAuthenticator(&LdapServerConf{
  162. LdapGroups: []*LdapGroupToOrgRole{
  163. {GroupDN: "cn=users", OrgRole: "Admin"},
  164. },
  165. })
  166. sc.userQueryReturns(user1)
  167. result, err := ldapAuther.GetGrafanaUserFor(nil, &LdapUserInfo{MemberOf: []string{"cn=users"}})
  168. So(err, ShouldBeNil)
  169. So(result, ShouldEqual, user1)
  170. })
  171. ldapAutherScenario("Given group match with different case", func(sc *scenarioContext) {
  172. ldapAuther := NewLdapAuthenticator(&LdapServerConf{
  173. LdapGroups: []*LdapGroupToOrgRole{
  174. {GroupDN: "cn=users", OrgRole: "Admin"},
  175. },
  176. })
  177. sc.userQueryReturns(user1)
  178. result, err := ldapAuther.GetGrafanaUserFor(nil, &LdapUserInfo{MemberOf: []string{"CN=users"}})
  179. So(err, ShouldBeNil)
  180. So(result, ShouldEqual, user1)
  181. })
  182. ldapAutherScenario("Given no existing grafana user", func(sc *scenarioContext) {
  183. ldapAuther := NewLdapAuthenticator(&LdapServerConf{
  184. LdapGroups: []*LdapGroupToOrgRole{
  185. {GroupDN: "cn=admin", OrgRole: "Admin"},
  186. {GroupDN: "cn=editor", OrgRole: "Editor"},
  187. {GroupDN: "*", OrgRole: "Viewer"},
  188. },
  189. })
  190. sc.userQueryReturns(nil)
  191. result, err := ldapAuther.GetGrafanaUserFor(nil, &LdapUserInfo{
  192. DN: "torkelo",
  193. Username: "torkelo",
  194. Email: "my@email.com",
  195. MemberOf: []string{"cn=editor"},
  196. })
  197. So(err, ShouldBeNil)
  198. Convey("Should return new user", func() {
  199. So(result.Login, ShouldEqual, "torkelo")
  200. })
  201. Convey("Should set isGrafanaAdmin to false by default", func() {
  202. So(result.IsAdmin, ShouldBeFalse)
  203. })
  204. })
  205. })
  206. Convey("When syncing ldap groups to grafana org roles", t, func() {
  207. ldapAutherScenario("given no current user orgs", func(sc *scenarioContext) {
  208. ldapAuther := NewLdapAuthenticator(&LdapServerConf{
  209. LdapGroups: []*LdapGroupToOrgRole{
  210. {GroupDN: "cn=users", OrgRole: "Admin"},
  211. },
  212. })
  213. sc.userOrgsQueryReturns([]*m.UserOrgDTO{})
  214. _, err := ldapAuther.GetGrafanaUserFor(nil, &LdapUserInfo{
  215. MemberOf: []string{"cn=users"},
  216. })
  217. Convey("Should create new org user", func() {
  218. So(err, ShouldBeNil)
  219. So(sc.addOrgUserCmd, ShouldNotBeNil)
  220. So(sc.addOrgUserCmd.Role, ShouldEqual, m.ROLE_ADMIN)
  221. })
  222. })
  223. ldapAutherScenario("given different current org role", func(sc *scenarioContext) {
  224. ldapAuther := NewLdapAuthenticator(&LdapServerConf{
  225. LdapGroups: []*LdapGroupToOrgRole{
  226. {GroupDN: "cn=users", OrgId: 1, OrgRole: "Admin"},
  227. },
  228. })
  229. sc.userOrgsQueryReturns([]*m.UserOrgDTO{{OrgId: 1, Role: m.ROLE_EDITOR}})
  230. _, err := ldapAuther.GetGrafanaUserFor(nil, &LdapUserInfo{
  231. MemberOf: []string{"cn=users"},
  232. })
  233. Convey("Should update org role", func() {
  234. So(err, ShouldBeNil)
  235. So(sc.updateOrgUserCmd, ShouldNotBeNil)
  236. So(sc.updateOrgUserCmd.Role, ShouldEqual, m.ROLE_ADMIN)
  237. So(sc.setUsingOrgCmd.OrgId, ShouldEqual, 1)
  238. })
  239. })
  240. ldapAutherScenario("given current org role is removed in ldap", func(sc *scenarioContext) {
  241. ldapAuther := NewLdapAuthenticator(&LdapServerConf{
  242. LdapGroups: []*LdapGroupToOrgRole{
  243. {GroupDN: "cn=users", OrgId: 2, OrgRole: "Admin"},
  244. },
  245. })
  246. sc.userOrgsQueryReturns([]*m.UserOrgDTO{
  247. {OrgId: 1, Role: m.ROLE_EDITOR},
  248. {OrgId: 2, Role: m.ROLE_EDITOR},
  249. })
  250. _, err := ldapAuther.GetGrafanaUserFor(nil, &LdapUserInfo{
  251. MemberOf: []string{"cn=users"},
  252. })
  253. Convey("Should remove org role", func() {
  254. So(err, ShouldBeNil)
  255. So(sc.removeOrgUserCmd, ShouldNotBeNil)
  256. So(sc.setUsingOrgCmd.OrgId, ShouldEqual, 2)
  257. })
  258. })
  259. ldapAutherScenario("given org role is updated in config", func(sc *scenarioContext) {
  260. ldapAuther := NewLdapAuthenticator(&LdapServerConf{
  261. LdapGroups: []*LdapGroupToOrgRole{
  262. {GroupDN: "cn=admin", OrgId: 1, OrgRole: "Admin"},
  263. {GroupDN: "cn=users", OrgId: 1, OrgRole: "Viewer"},
  264. },
  265. })
  266. sc.userOrgsQueryReturns([]*m.UserOrgDTO{{OrgId: 1, Role: m.ROLE_EDITOR}})
  267. _, err := ldapAuther.GetGrafanaUserFor(nil, &LdapUserInfo{
  268. MemberOf: []string{"cn=users"},
  269. })
  270. Convey("Should update org role", func() {
  271. So(err, ShouldBeNil)
  272. So(sc.removeOrgUserCmd, ShouldBeNil)
  273. So(sc.updateOrgUserCmd, ShouldNotBeNil)
  274. So(sc.setUsingOrgCmd.OrgId, ShouldEqual, 1)
  275. })
  276. })
  277. ldapAutherScenario("given multiple matching ldap groups", func(sc *scenarioContext) {
  278. ldapAuther := NewLdapAuthenticator(&LdapServerConf{
  279. LdapGroups: []*LdapGroupToOrgRole{
  280. {GroupDN: "cn=admins", OrgId: 1, OrgRole: "Admin"},
  281. {GroupDN: "*", OrgId: 1, OrgRole: "Viewer"},
  282. },
  283. })
  284. sc.userOrgsQueryReturns([]*m.UserOrgDTO{{OrgId: 1, Role: m.ROLE_ADMIN}})
  285. _, err := ldapAuther.GetGrafanaUserFor(nil, &LdapUserInfo{
  286. MemberOf: []string{"cn=admins"},
  287. })
  288. Convey("Should take first match, and ignore subsequent matches", func() {
  289. So(err, ShouldBeNil)
  290. So(sc.updateOrgUserCmd, ShouldBeNil)
  291. So(sc.setUsingOrgCmd.OrgId, ShouldEqual, 1)
  292. })
  293. })
  294. ldapAutherScenario("given multiple matching ldap groups and no existing groups", func(sc *scenarioContext) {
  295. ldapAuther := NewLdapAuthenticator(&LdapServerConf{
  296. LdapGroups: []*LdapGroupToOrgRole{
  297. {GroupDN: "cn=admins", OrgId: 1, OrgRole: "Admin"},
  298. {GroupDN: "*", OrgId: 1, OrgRole: "Viewer"},
  299. },
  300. })
  301. sc.userOrgsQueryReturns([]*m.UserOrgDTO{})
  302. _, err := ldapAuther.GetGrafanaUserFor(nil, &LdapUserInfo{
  303. MemberOf: []string{"cn=admins"},
  304. })
  305. Convey("Should take first match, and ignore subsequent matches", func() {
  306. So(err, ShouldBeNil)
  307. So(sc.addOrgUserCmd.Role, ShouldEqual, m.ROLE_ADMIN)
  308. So(sc.setUsingOrgCmd.OrgId, ShouldEqual, 1)
  309. })
  310. Convey("Should not update permissions unless specified", func() {
  311. So(err, ShouldBeNil)
  312. So(sc.updateUserPermissionsCmd, ShouldBeNil)
  313. })
  314. })
  315. ldapAutherScenario("given ldap groups with grafana_admin=true", func(sc *scenarioContext) {
  316. trueVal := true
  317. ldapAuther := NewLdapAuthenticator(&LdapServerConf{
  318. LdapGroups: []*LdapGroupToOrgRole{
  319. {GroupDN: "cn=admins", OrgId: 1, OrgRole: "Admin", IsGrafanaAdmin: &trueVal},
  320. },
  321. })
  322. sc.userOrgsQueryReturns([]*m.UserOrgDTO{})
  323. _, err := ldapAuther.GetGrafanaUserFor(nil, &LdapUserInfo{
  324. MemberOf: []string{"cn=admins"},
  325. })
  326. Convey("Should create user with admin set to true", func() {
  327. So(err, ShouldBeNil)
  328. So(sc.updateUserPermissionsCmd.IsGrafanaAdmin, ShouldBeTrue)
  329. })
  330. })
  331. })
  332. Convey("When calling SyncUser", t, func() {
  333. mockLdapConnection := &mockLdapConn{}
  334. ldapAuther := NewLdapAuthenticator(
  335. &LdapServerConf{
  336. Host: "",
  337. RootCACert: "",
  338. LdapGroups: []*LdapGroupToOrgRole{
  339. {GroupDN: "*", OrgRole: "Admin"},
  340. },
  341. Attr: LdapAttributeMap{
  342. Username: "username",
  343. Surname: "surname",
  344. Email: "email",
  345. Name: "name",
  346. MemberOf: "memberof",
  347. },
  348. SearchBaseDNs: []string{"BaseDNHere"},
  349. },
  350. )
  351. dialCalled := false
  352. ldapDial = func(network, addr string) (ILdapConn, error) {
  353. dialCalled = true
  354. return mockLdapConnection, nil
  355. }
  356. entry := ldap.Entry{
  357. DN: "dn", Attributes: []*ldap.EntryAttribute{
  358. {Name: "username", Values: []string{"roelgerrits"}},
  359. {Name: "surname", Values: []string{"Gerrits"}},
  360. {Name: "email", Values: []string{"roel@test.com"}},
  361. {Name: "name", Values: []string{"Roel"}},
  362. {Name: "memberof", Values: []string{"admins"}},
  363. }}
  364. result := ldap.SearchResult{Entries: []*ldap.Entry{&entry}}
  365. mockLdapConnection.setSearchResult(&result)
  366. ldapAutherScenario("When ldapUser found call syncInfo and orgRoles", func(sc *scenarioContext) {
  367. // arrange
  368. query := &m.LoginUserQuery{
  369. Username: "roelgerrits",
  370. }
  371. sc.userQueryReturns(&m.User{
  372. Id: 1,
  373. Email: "roel@test.net",
  374. Name: "Roel Gerrits",
  375. Login: "roelgerrits",
  376. })
  377. sc.userOrgsQueryReturns([]*m.UserOrgDTO{})
  378. // act
  379. syncErrResult := ldapAuther.SyncUser(query)
  380. // assert
  381. So(dialCalled, ShouldBeTrue)
  382. So(syncErrResult, ShouldBeNil)
  383. // User should be searched in ldap
  384. So(mockLdapConnection.searchCalled, ShouldBeTrue)
  385. // Info should be updated (email differs)
  386. So(sc.updateUserCmd.Email, ShouldEqual, "roel@test.com")
  387. // User should have admin privileges
  388. So(sc.addOrgUserCmd.UserId, ShouldEqual, 1)
  389. So(sc.addOrgUserCmd.Role, ShouldEqual, "Admin")
  390. })
  391. })
  392. Convey("When searching for a user and not all five attributes are mapped", t, func() {
  393. mockLdapConnection := &mockLdapConn{}
  394. entry := ldap.Entry{
  395. DN: "dn", Attributes: []*ldap.EntryAttribute{
  396. {Name: "username", Values: []string{"roelgerrits"}},
  397. {Name: "surname", Values: []string{"Gerrits"}},
  398. {Name: "email", Values: []string{"roel@test.com"}},
  399. {Name: "name", Values: []string{"Roel"}},
  400. {Name: "memberof", Values: []string{"admins"}},
  401. }}
  402. result := ldap.SearchResult{Entries: []*ldap.Entry{&entry}}
  403. mockLdapConnection.setSearchResult(&result)
  404. // Set up attribute map without surname and email
  405. ldapAuther := &ldapAuther{
  406. server: &LdapServerConf{
  407. Attr: LdapAttributeMap{
  408. Username: "username",
  409. Name: "name",
  410. MemberOf: "memberof",
  411. },
  412. SearchBaseDNs: []string{"BaseDNHere"},
  413. },
  414. conn: mockLdapConnection,
  415. log: log.New("test-logger"),
  416. }
  417. searchResult, err := ldapAuther.searchForUser("roelgerrits")
  418. So(err, ShouldBeNil)
  419. So(searchResult, ShouldNotBeNil)
  420. // User should be searched in ldap
  421. So(mockLdapConnection.searchCalled, ShouldBeTrue)
  422. // No empty attributes should be added to the search request
  423. So(len(mockLdapConnection.searchAttributes), ShouldEqual, 3)
  424. })
  425. }
  426. type mockLdapConn struct {
  427. result *ldap.SearchResult
  428. searchCalled bool
  429. searchAttributes []string
  430. bindProvider func(username, password string) error
  431. unauthenticatedBindProvider func(username string) error
  432. }
  433. func (c *mockLdapConn) Bind(username, password string) error {
  434. if c.bindProvider != nil {
  435. return c.bindProvider(username, password)
  436. }
  437. return nil
  438. }
  439. func (c *mockLdapConn) UnauthenticatedBind(username string) error {
  440. if c.unauthenticatedBindProvider != nil {
  441. return c.unauthenticatedBindProvider(username)
  442. }
  443. return nil
  444. }
  445. func (c *mockLdapConn) Close() {}
  446. func (c *mockLdapConn) setSearchResult(result *ldap.SearchResult) {
  447. c.result = result
  448. }
  449. func (c *mockLdapConn) Search(sr *ldap.SearchRequest) (*ldap.SearchResult, error) {
  450. c.searchCalled = true
  451. c.searchAttributes = sr.Attributes
  452. return c.result, nil
  453. }
  454. func (c *mockLdapConn) StartTLS(*tls.Config) error {
  455. return nil
  456. }
  457. func ldapAutherScenario(desc string, fn scenarioFunc) {
  458. Convey(desc, func() {
  459. defer bus.ClearBusHandlers()
  460. sc := &scenarioContext{}
  461. loginService := &LoginService{
  462. Bus: bus.GetBus(),
  463. }
  464. bus.AddHandler("test", loginService.UpsertUser)
  465. bus.AddHandlerCtx("test", func(ctx context.Context, cmd *m.SyncTeamsCommand) error {
  466. return nil
  467. })
  468. bus.AddHandlerCtx("test", func(ctx context.Context, cmd *m.UpdateUserPermissionsCommand) error {
  469. sc.updateUserPermissionsCmd = cmd
  470. return nil
  471. })
  472. bus.AddHandler("test", func(cmd *m.GetUserByAuthInfoQuery) error {
  473. sc.getUserByAuthInfoQuery = cmd
  474. sc.getUserByAuthInfoQuery.Result = &m.User{Login: cmd.Login}
  475. return nil
  476. })
  477. bus.AddHandler("test", func(cmd *m.GetUserOrgListQuery) error {
  478. sc.getUserOrgListQuery = cmd
  479. return nil
  480. })
  481. bus.AddHandler("test", func(cmd *m.CreateUserCommand) error {
  482. sc.createUserCmd = cmd
  483. sc.createUserCmd.Result = m.User{Login: cmd.Login}
  484. return nil
  485. })
  486. bus.AddHandler("test", func(cmd *m.AddOrgUserCommand) error {
  487. sc.addOrgUserCmd = cmd
  488. return nil
  489. })
  490. bus.AddHandler("test", func(cmd *m.UpdateOrgUserCommand) error {
  491. sc.updateOrgUserCmd = cmd
  492. return nil
  493. })
  494. bus.AddHandler("test", func(cmd *m.RemoveOrgUserCommand) error {
  495. sc.removeOrgUserCmd = cmd
  496. return nil
  497. })
  498. bus.AddHandler("test", func(cmd *m.UpdateUserCommand) error {
  499. sc.updateUserCmd = cmd
  500. return nil
  501. })
  502. bus.AddHandler("test", func(cmd *m.SetUsingOrgCommand) error {
  503. sc.setUsingOrgCmd = cmd
  504. return nil
  505. })
  506. fn(sc)
  507. })
  508. }
  509. type scenarioContext struct {
  510. getUserByAuthInfoQuery *m.GetUserByAuthInfoQuery
  511. getUserOrgListQuery *m.GetUserOrgListQuery
  512. createUserCmd *m.CreateUserCommand
  513. addOrgUserCmd *m.AddOrgUserCommand
  514. updateOrgUserCmd *m.UpdateOrgUserCommand
  515. removeOrgUserCmd *m.RemoveOrgUserCommand
  516. updateUserCmd *m.UpdateUserCommand
  517. setUsingOrgCmd *m.SetUsingOrgCommand
  518. updateUserPermissionsCmd *m.UpdateUserPermissionsCommand
  519. }
  520. func (sc *scenarioContext) userQueryReturns(user *m.User) {
  521. bus.AddHandler("test", func(query *m.GetUserByAuthInfoQuery) error {
  522. if user == nil {
  523. return m.ErrUserNotFound
  524. }
  525. query.Result = user
  526. return nil
  527. })
  528. bus.AddHandler("test", func(query *m.SetAuthInfoCommand) error {
  529. return nil
  530. })
  531. }
  532. func (sc *scenarioContext) userOrgsQueryReturns(orgs []*m.UserOrgDTO) {
  533. bus.AddHandler("test", func(query *m.GetUserOrgListQuery) error {
  534. query.Result = orgs
  535. return nil
  536. })
  537. }
  538. type scenarioFunc func(c *scenarioContext)