user_factory_spec.rb 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546
  1. require 'rails_helper'
  2. RSpec.describe Import::Ldap::UserFactory do
  3. describe '.import' do
  4. it 'responds to .import' do
  5. expect(described_class).to respond_to(:import)
  6. end
  7. it 'imports users matching the configured filter' do
  8. config = {
  9. user_filter: '(objectClass=user)',
  10. group_filter: '(objectClass=group)',
  11. user_uid: 'uid',
  12. user_attributes: {
  13. 'uid' => 'login',
  14. 'email' => 'email',
  15. }
  16. }
  17. mocked_entry = build(:ldap_entry)
  18. mocked_entry['uid'] = ['exampleuid']
  19. mocked_entry['email'] = ['example@example.com']
  20. mocked_ldap = double(
  21. host: 'ldap.example.com',
  22. port: 636,
  23. ssl: true,
  24. base_dn: 'dc=example,dc=com'
  25. )
  26. # group user role mapping
  27. expect(mocked_ldap).to receive(:search)
  28. # user counting
  29. allow(mocked_ldap).to receive(:count).and_return(1)
  30. # user search
  31. expect(mocked_ldap).to receive(:search).and_yield(mocked_entry)
  32. expect do
  33. described_class.import(
  34. config: config,
  35. ldap: mocked_ldap
  36. )
  37. end.to change {
  38. User.count
  39. }.by(1)
  40. end
  41. it 'deactivates lost users' do
  42. config = {
  43. user_filter: '(objectClass=user)',
  44. group_filter: '(objectClass=group)',
  45. user_uid: 'uid',
  46. user_attributes: {
  47. 'uid' => 'login',
  48. 'email' => 'email',
  49. }
  50. }
  51. persistent_entry = build(:ldap_entry)
  52. persistent_entry['uid'] = ['exampleuid']
  53. persistent_entry['email'] = ['example@example.com']
  54. lost_entry = build(:ldap_entry)
  55. lost_entry['uid'] = ['exampleuid_lost']
  56. lost_entry['email'] = ['lost@example.com']
  57. mocked_ldap = double(
  58. host: 'ldap.example.com',
  59. port: 636,
  60. ssl: true,
  61. base_dn: 'dc=example,dc=com'
  62. )
  63. # group user role mapping
  64. expect(mocked_ldap).to receive(:search)
  65. # user counting
  66. expect(mocked_ldap).to receive(:count).and_return(2)
  67. # user search
  68. expect(mocked_ldap).to receive(:search).and_yield(persistent_entry).and_yield(lost_entry)
  69. described_class.import(
  70. config: config,
  71. ldap: mocked_ldap,
  72. )
  73. # group user role mapping
  74. expect(mocked_ldap).to receive(:search)
  75. # user counting
  76. expect(mocked_ldap).to receive(:count).and_return(1)
  77. # user search
  78. expect(mocked_ldap).to receive(:search).and_yield(persistent_entry)
  79. expect do
  80. described_class.import(
  81. config: config,
  82. ldap: mocked_ldap,
  83. )
  84. end.to change {
  85. User.find_by(email: 'lost@example.com').active
  86. }
  87. end
  88. it 're-activates previously lost users' do
  89. config = {
  90. user_filter: '(objectClass=user)',
  91. group_filter: '(objectClass=group)',
  92. user_uid: 'uid',
  93. user_attributes: {
  94. 'uid' => 'login',
  95. 'email' => 'email',
  96. }
  97. }
  98. persistent_entry = build(:ldap_entry)
  99. persistent_entry['uid'] = ['exampleuid']
  100. persistent_entry['email'] = ['example@example.com']
  101. lost_entry = build(:ldap_entry)
  102. lost_entry['uid'] = ['exampleuid_lost']
  103. lost_entry['email'] = ['lost@example.com']
  104. mocked_ldap = double(
  105. host: 'ldap.example.com',
  106. port: 636,
  107. ssl: true,
  108. base_dn: 'dc=example,dc=com'
  109. )
  110. # group user role mapping
  111. expect(mocked_ldap).to receive(:search)
  112. # user counting
  113. expect(mocked_ldap).to receive(:count).and_return(2)
  114. # user search
  115. expect(mocked_ldap).to receive(:search).and_yield(persistent_entry).and_yield(lost_entry)
  116. described_class.import(
  117. config: config,
  118. ldap: mocked_ldap,
  119. )
  120. # group user role mapping
  121. expect(mocked_ldap).to receive(:search)
  122. # user counting
  123. expect(mocked_ldap).to receive(:count).and_return(1)
  124. # user search
  125. expect(mocked_ldap).to receive(:search).and_yield(persistent_entry)
  126. described_class.import(
  127. config: config,
  128. ldap: mocked_ldap,
  129. )
  130. # group user role mapping
  131. expect(mocked_ldap).to receive(:search)
  132. # user counting
  133. expect(mocked_ldap).to receive(:count).and_return(2)
  134. # user search
  135. expect(mocked_ldap).to receive(:search).and_yield(persistent_entry).and_yield(lost_entry)
  136. expect do
  137. described_class.import(
  138. config: config,
  139. ldap: mocked_ldap,
  140. )
  141. end.to change {
  142. User.find_by(email: 'lost@example.com').active
  143. }
  144. end
  145. it 'deactivates skipped users' do
  146. config = {
  147. user_filter: '(objectClass=user)',
  148. group_filter: '(objectClass=group)',
  149. user_uid: 'uid',
  150. user_attributes: {
  151. 'uid' => 'login',
  152. 'email' => 'email',
  153. },
  154. }
  155. lost_entry = build(:ldap_entry)
  156. lost_entry['uid'] = ['exampleuid']
  157. lost_entry['email'] = ['example@example.com']
  158. mocked_ldap = double(
  159. host: 'ldap.example.com',
  160. port: 636,
  161. ssl: true,
  162. base_dn: 'dc=example,dc=com'
  163. )
  164. # group user role mapping
  165. expect(mocked_ldap).to receive(:search)
  166. # user counting
  167. expect(mocked_ldap).to receive(:count).and_return(2)
  168. # user search
  169. expect(mocked_ldap).to receive(:search).and_yield(lost_entry)
  170. described_class.import(
  171. config: config,
  172. ldap: mocked_ldap,
  173. )
  174. # activate skipping
  175. config[:unassigned_users] = 'skip_sync'
  176. config[:group_role_map] = {
  177. 'dummy' => %w[1 2],
  178. }
  179. # group user role mapping
  180. mocked_entry = build(:ldap_entry)
  181. mocked_entry['dn'] = 'dummy'
  182. mocked_entry['member'] = ['dummy']
  183. expect(mocked_ldap).to receive(:search).and_yield(mocked_entry)
  184. # user counting
  185. expect(mocked_ldap).to receive(:count).and_return(1)
  186. # user search
  187. expect(mocked_ldap).to receive(:search).and_yield(lost_entry)
  188. expect do
  189. described_class.import(
  190. config: config,
  191. ldap: mocked_ldap,
  192. )
  193. end.to change {
  194. User.find_by(email: 'example@example.com').active
  195. }
  196. end
  197. context 'dry run' do
  198. it "doesn't sync users" do
  199. config = {
  200. user_filter: '(objectClass=user)',
  201. group_filter: '(objectClass=group)',
  202. user_uid: 'uid',
  203. user_attributes: {
  204. 'uid' => 'login',
  205. 'email' => 'email',
  206. }
  207. }
  208. mocked_entry = build(:ldap_entry)
  209. mocked_entry['uid'] = ['exampleuid']
  210. mocked_entry['email'] = ['example@example.com']
  211. mocked_ldap = double(
  212. host: 'ldap.example.com',
  213. port: 636,
  214. ssl: true,
  215. base_dn: 'dc=example,dc=com'
  216. )
  217. # group user role mapping
  218. expect(mocked_ldap).to receive(:search)
  219. # user counting
  220. expect(mocked_ldap).to receive(:count).and_return(1)
  221. # user search
  222. expect(mocked_ldap).to receive(:search).and_yield(mocked_entry)
  223. expect do
  224. described_class.import(
  225. config: config,
  226. ldap: mocked_ldap,
  227. dry_run: true
  228. )
  229. end.not_to change {
  230. User.count
  231. }
  232. end
  233. it "doesn't deactivates lost users" do
  234. config = {
  235. user_filter: '(objectClass=user)',
  236. group_filter: '(objectClass=group)',
  237. user_uid: 'uid',
  238. user_attributes: {
  239. 'uid' => 'login',
  240. 'email' => 'email',
  241. }
  242. }
  243. persistent_entry = build(:ldap_entry)
  244. persistent_entry['uid'] = ['exampleuid']
  245. persistent_entry['email'] = ['example@example.com']
  246. lost_entry = build(:ldap_entry)
  247. lost_entry['uid'] = ['exampleuid']
  248. lost_entry['email'] = ['example@example.com']
  249. mocked_ldap = double(
  250. host: 'ldap.example.com',
  251. port: 636,
  252. ssl: true,
  253. base_dn: 'dc=example,dc=com'
  254. )
  255. # group user role mapping
  256. expect(mocked_ldap).to receive(:search)
  257. # user counting
  258. expect(mocked_ldap).to receive(:count).and_return(2)
  259. # user search
  260. expect(mocked_ldap).to receive(:search).and_yield(persistent_entry).and_yield(lost_entry)
  261. described_class.import(
  262. config: config,
  263. ldap: mocked_ldap,
  264. dry_run: true
  265. )
  266. # group user role mapping
  267. expect(mocked_ldap).to receive(:search)
  268. # user counting
  269. expect(mocked_ldap).to receive(:count).and_return(1)
  270. # user search
  271. expect(mocked_ldap).to receive(:search).and_yield(persistent_entry)
  272. expect do
  273. described_class.import(
  274. config: config,
  275. ldap: mocked_ldap,
  276. dry_run: true
  277. )
  278. end.not_to change {
  279. User.count
  280. }
  281. end
  282. end
  283. end
  284. describe '.add_to_statistics' do
  285. it 'responds to .add_to_statistics' do
  286. expect(described_class).to respond_to(:add_to_statistics)
  287. end
  288. it 'adds statistics per user role' do
  289. mocked_backend_instance = double(
  290. action: :created,
  291. resource: double(
  292. role_ids: [1, 2]
  293. )
  294. )
  295. # initialize empty statistic
  296. described_class.reset_statistics
  297. described_class.add_to_statistics(mocked_backend_instance)
  298. expected = {
  299. role_ids: {
  300. 1 => {
  301. created: 1,
  302. updated: 0,
  303. unchanged: 0,
  304. failed: 0,
  305. deactivated: 0,
  306. },
  307. 2 => {
  308. created: 1,
  309. updated: 0,
  310. unchanged: 0,
  311. failed: 0,
  312. deactivated: 0,
  313. },
  314. },
  315. skipped: 0,
  316. created: 1,
  317. updated: 0,
  318. unchanged: 0,
  319. failed: 0,
  320. deactivated: 0,
  321. }
  322. expect(described_class.statistics).to include(expected)
  323. end
  324. it 'adds deactivated users' do
  325. config = {
  326. user_filter: '(objectClass=user)',
  327. group_filter: '(objectClass=group)',
  328. user_uid: 'uid',
  329. user_attributes: {
  330. 'uid' => 'login',
  331. 'email' => 'email',
  332. }
  333. }
  334. persistent_entry = build(:ldap_entry)
  335. persistent_entry['uid'] = ['exampleuid']
  336. persistent_entry['email'] = ['example@example.com']
  337. lost_entry = build(:ldap_entry)
  338. lost_entry['uid'] = ['exampleuid_lost']
  339. lost_entry['email'] = ['lost@example.com']
  340. mocked_ldap = double(
  341. host: 'ldap.example.com',
  342. port: 636,
  343. ssl: true,
  344. base_dn: 'dc=example,dc=com'
  345. )
  346. # group user role mapping
  347. expect(mocked_ldap).to receive(:search)
  348. # user counting
  349. allow(mocked_ldap).to receive(:count).and_return(2)
  350. # user search
  351. expect(mocked_ldap).to receive(:search).and_yield(persistent_entry).and_yield(lost_entry)
  352. described_class.import(
  353. config: config,
  354. ldap: mocked_ldap,
  355. )
  356. # simulate new import
  357. described_class.reset_statistics
  358. # group user role mapping
  359. expect(mocked_ldap).to receive(:search)
  360. # user counting
  361. allow(mocked_ldap).to receive(:count).and_return(1)
  362. # user search
  363. expect(mocked_ldap).to receive(:search).and_yield(persistent_entry)
  364. described_class.import(
  365. config: config,
  366. ldap: mocked_ldap,
  367. )
  368. expected = {
  369. skipped: 0,
  370. created: 0,
  371. updated: 0,
  372. unchanged: 1,
  373. failed: 0,
  374. deactivated: 1,
  375. }
  376. expect(described_class.statistics).to include(expected)
  377. end
  378. it 'skips not created instances' do
  379. mocked_backend_instance = double(
  380. action: :skipped,
  381. resource: nil,
  382. )
  383. # initialize empty statistic
  384. described_class.reset_statistics
  385. described_class.add_to_statistics(mocked_backend_instance)
  386. expected = {
  387. skipped: 1,
  388. created: 0,
  389. updated: 0,
  390. unchanged: 0,
  391. failed: 0,
  392. deactivated: 0,
  393. }
  394. expect(described_class.statistics).to include(expected)
  395. end
  396. it 'skips unwanted actions instances' do
  397. mocked_backend_instance = double(
  398. action: :skipped,
  399. resource: double(
  400. role_ids: [1, 2]
  401. )
  402. )
  403. # initialize empty statistic
  404. described_class.reset_statistics
  405. described_class.add_to_statistics(mocked_backend_instance)
  406. expected = {
  407. skipped: 1,
  408. created: 0,
  409. updated: 0,
  410. unchanged: 0,
  411. failed: 0,
  412. deactivated: 0,
  413. }
  414. expect(described_class.statistics).to include(expected)
  415. end
  416. end
  417. describe '.user_roles' do
  418. it 'responds to .user_roles' do
  419. expect(described_class).to respond_to(:user_roles)
  420. end
  421. it 'fetches the user DN to local role mapping' do
  422. group_dn = 'dn=... admin group...'
  423. user_dn = 'dn=... admin user...'
  424. config = {
  425. group_filter: '(objectClass=group)',
  426. group_role_map: {
  427. group_dn => %w[1 2],
  428. }
  429. }
  430. mocked_entry = build(:ldap_entry)
  431. mocked_entry['dn'] = group_dn
  432. mocked_entry['member'] = [user_dn]
  433. mocked_ldap = double()
  434. expect(mocked_ldap).to receive(:search).and_yield(mocked_entry)
  435. user_roles = described_class.user_roles(
  436. ldap: mocked_ldap,
  437. config: config,
  438. )
  439. expected = {
  440. user_dn => [1, 2]
  441. }
  442. expect(user_roles).to be_a(Hash)
  443. expect(user_roles).to eq(expected)
  444. end
  445. end
  446. end