admin_test.go 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426
  1. package foodgroup
  2. import (
  3. "context"
  4. "io"
  5. "log/slog"
  6. "net/mail"
  7. "testing"
  8. "github.com/stretchr/testify/assert"
  9. "github.com/stretchr/testify/mock"
  10. "github.com/mk6i/open-oscar-server/config"
  11. "github.com/mk6i/open-oscar-server/state"
  12. "github.com/mk6i/open-oscar-server/wire"
  13. )
  14. func TestAdminService_ConfirmRequest(t *testing.T) {
  15. cases := []struct {
  16. // name is the unit test name
  17. name string
  18. // cfg is the app configuration
  19. cfg config.Config
  20. // inputSNAC is the SNAC sent from the client to the server
  21. inputSNAC wire.SNACMessage
  22. // mockParams is the list of params sent to mocks that satisfy this
  23. // method's dependencies
  24. mockParams mockParams
  25. // instance is the session of the user
  26. instance *state.SessionInstance
  27. // expectOutput is the SNAC sent from the server to client
  28. expectOutput wire.SNACMessage
  29. // expectErr is the expected error returned
  30. expectErr error
  31. }{
  32. {
  33. name: "unconfirmed account sends confirmation request",
  34. instance: newTestInstance("chattingchuck"),
  35. inputSNAC: wire.SNACMessage{
  36. Frame: wire.SNACFrame{
  37. FoodGroup: wire.Admin,
  38. SubGroup: wire.AdminAcctConfirmRequest,
  39. RequestID: 1234,
  40. },
  41. Body: wire.SNAC_0x07_0x06_AdminConfirmRequest{},
  42. },
  43. expectOutput: wire.SNACMessage{
  44. Frame: wire.SNACFrame{
  45. FoodGroup: wire.Admin,
  46. SubGroup: wire.AdminAcctConfirmReply,
  47. RequestID: 1234,
  48. },
  49. Body: wire.SNAC_0x07_0x07_AdminConfirmReply{
  50. Status: wire.AdminAcctConfirmStatusEmailSent,
  51. },
  52. },
  53. mockParams: mockParams{
  54. accountManagerParams: accountManagerParams{
  55. accountManagerEmailAddressParams: accountManagerEmailAddressParams{
  56. {
  57. screenName: state.NewIdentScreenName("chattingchuck"),
  58. emailAddress: &mail.Address{
  59. Address: "chuck@aol.com",
  60. },
  61. err: nil,
  62. },
  63. },
  64. accountManagerConfirmStatusParams: accountManagerConfirmStatusParams{
  65. {
  66. screenName: state.NewIdentScreenName("chattingchuck"),
  67. confirmStatus: false,
  68. err: nil,
  69. },
  70. },
  71. accountManagerUpdateConfirmStatusParams: accountManagerUpdateConfirmStatusParams{
  72. {
  73. confirmStatus: true,
  74. screenName: state.NewIdentScreenName("chattingchuck"),
  75. err: nil,
  76. },
  77. },
  78. },
  79. buddyBroadcasterParams: buddyBroadcasterParams{
  80. broadcastBuddyArrivedParams: broadcastBuddyArrivedParams{
  81. {
  82. screenName: state.DisplayScreenName("Chatting Chuck"),
  83. },
  84. },
  85. },
  86. },
  87. },
  88. {
  89. name: "already confirmed account sends confirmation request",
  90. instance: newTestInstance("chattingchuck"),
  91. inputSNAC: wire.SNACMessage{
  92. Frame: wire.SNACFrame{
  93. FoodGroup: wire.Admin,
  94. SubGroup: wire.AdminAcctConfirmRequest,
  95. RequestID: 1234,
  96. },
  97. Body: wire.SNAC_0x07_0x06_AdminConfirmRequest{},
  98. },
  99. expectOutput: wire.SNACMessage{
  100. Frame: wire.SNACFrame{
  101. FoodGroup: wire.Admin,
  102. SubGroup: wire.AdminAcctConfirmReply,
  103. RequestID: 1234,
  104. },
  105. Body: wire.SNAC_0x07_0x07_AdminConfirmReply{
  106. Status: wire.AdminAcctConfirmStatusAlreadyConfirmed,
  107. },
  108. },
  109. mockParams: mockParams{
  110. accountManagerParams: accountManagerParams{
  111. accountManagerEmailAddressParams: accountManagerEmailAddressParams{
  112. {
  113. screenName: state.NewIdentScreenName("chattingchuck"),
  114. emailAddress: &mail.Address{
  115. Address: "chuck@aol.com",
  116. },
  117. err: nil,
  118. },
  119. },
  120. accountManagerConfirmStatusParams: accountManagerConfirmStatusParams{
  121. {
  122. screenName: state.NewIdentScreenName("chattingchuck"),
  123. confirmStatus: true,
  124. err: nil,
  125. },
  126. },
  127. },
  128. },
  129. },
  130. {
  131. name: "acccount with no email address sends confirmation request",
  132. instance: newTestInstance("chattingchuck"),
  133. inputSNAC: wire.SNACMessage{
  134. Frame: wire.SNACFrame{
  135. FoodGroup: wire.Admin,
  136. SubGroup: wire.AdminAcctConfirmRequest,
  137. RequestID: 1234,
  138. },
  139. Body: wire.SNAC_0x07_0x06_AdminConfirmRequest{},
  140. },
  141. expectOutput: wire.SNACMessage{
  142. Frame: wire.SNACFrame{
  143. FoodGroup: wire.Admin,
  144. SubGroup: wire.AdminAcctConfirmReply,
  145. RequestID: 1234,
  146. },
  147. Body: wire.SNAC_0x07_0x07_AdminConfirmReply{
  148. Status: wire.AdminAcctConfirmStatusServerError,
  149. },
  150. },
  151. mockParams: mockParams{
  152. accountManagerParams: accountManagerParams{
  153. accountManagerEmailAddressParams: accountManagerEmailAddressParams{
  154. {
  155. screenName: state.NewIdentScreenName("chattingchuck"),
  156. emailAddress: nil,
  157. err: state.ErrNoEmailAddress,
  158. },
  159. },
  160. },
  161. },
  162. },
  163. }
  164. for _, tc := range cases {
  165. t.Run(tc.name, func(t *testing.T) {
  166. messageRelayer := newMockMessageRelayer(t)
  167. accountManager := newMockAccountManager(t)
  168. buddyBroadcaster := newMockbuddyBroadcaster(t)
  169. for _, params := range tc.mockParams.accountManagerEmailAddressParams {
  170. accountManager.EXPECT().
  171. EmailAddress(matchContext(), params.screenName).
  172. Return(params.emailAddress, params.err)
  173. }
  174. for _, params := range tc.mockParams.accountManagerConfirmStatusParams {
  175. accountManager.EXPECT().
  176. ConfirmStatus(matchContext(), params.screenName).
  177. Return(params.confirmStatus, params.err)
  178. }
  179. for _, params := range tc.mockParams.accountManagerUpdateConfirmStatusParams {
  180. accountManager.EXPECT().
  181. UpdateConfirmStatus(matchContext(), params.screenName, params.confirmStatus).
  182. Return(params.err)
  183. }
  184. for _, params := range tc.mockParams.broadcastBuddyArrivedParams {
  185. buddyBroadcaster.EXPECT().
  186. BroadcastBuddyArrived(mock.Anything, tc.instance.IdentScreenName(), tc.instance.Session().TLVUserInfo()).
  187. Return(params.err)
  188. }
  189. svc := AdminService{
  190. messageRelayer: messageRelayer,
  191. accountManager: accountManager,
  192. buddyBroadcaster: buddyBroadcaster,
  193. }
  194. outputSNAC, err := svc.ConfirmRequest(context.Background(), tc.instance, tc.inputSNAC.Frame)
  195. assert.ErrorIs(t, err, tc.expectErr)
  196. if tc.expectErr != nil {
  197. return
  198. }
  199. assert.Equal(t, tc.expectOutput, outputSNAC)
  200. })
  201. }
  202. }
  203. func TestAdminService_InfoQuery(t *testing.T) {
  204. cases := []struct {
  205. // name is the unit test name
  206. name string
  207. // cfg is the app configuration
  208. cfg config.Config
  209. // inputSNAC is the SNAC sent from the client to the server
  210. inputSNAC wire.SNACMessage
  211. // mockParams is the list of params sent to mocks that satisfy this
  212. // method's dependencies
  213. mockParams mockParams
  214. // instance is the session of the user
  215. instance *state.SessionInstance
  216. // expectOutput is the SNAC sent from the server to client
  217. expectOutput wire.SNACMessage
  218. // expectErr is the expected error returned
  219. expectErr error
  220. }{
  221. {
  222. name: "user requests account registration status",
  223. instance: newTestInstance("chattingchuck"),
  224. inputSNAC: wire.SNACMessage{
  225. Frame: wire.SNACFrame{
  226. FoodGroup: wire.Admin,
  227. SubGroup: wire.AdminInfoQuery,
  228. RequestID: 1337,
  229. },
  230. Body: wire.SNAC_0x07_0x02_AdminInfoQuery{
  231. TLVRestBlock: wire.TLVRestBlock{
  232. TLVList: wire.TLVList{
  233. wire.NewTLVBE(wire.AdminTLVRegistrationStatus, uint16(0x00))},
  234. },
  235. },
  236. },
  237. expectOutput: wire.SNACMessage{
  238. Frame: wire.SNACFrame{
  239. FoodGroup: wire.Admin,
  240. SubGroup: wire.AdminInfoReply,
  241. RequestID: 1337,
  242. },
  243. Body: wire.SNAC_0x07_0x03_AdminInfoReply{
  244. Permissions: wire.AdminInfoPermissionsReadWrite,
  245. TLVBlock: wire.TLVBlock{
  246. TLVList: wire.TLVList{
  247. wire.NewTLVBE(wire.AdminTLVRegistrationStatus, wire.AdminInfoRegStatusLimitDisclosure),
  248. },
  249. },
  250. },
  251. },
  252. mockParams: mockParams{
  253. accountManagerParams: accountManagerParams{
  254. accountManagerRegStatusParams: accountManagerRegStatusParams{
  255. {
  256. screenName: state.NewIdentScreenName("chattingchuck"),
  257. regStatus: wire.AdminInfoRegStatusLimitDisclosure,
  258. err: nil,
  259. },
  260. },
  261. },
  262. },
  263. },
  264. {
  265. name: "user requests account email address",
  266. instance: newTestInstance("chattingchuck"),
  267. inputSNAC: wire.SNACMessage{
  268. Frame: wire.SNACFrame{
  269. FoodGroup: wire.Admin,
  270. SubGroup: wire.AdminInfoQuery,
  271. RequestID: 1337,
  272. },
  273. Body: wire.SNAC_0x07_0x02_AdminInfoQuery{
  274. TLVRestBlock: wire.TLVRestBlock{
  275. TLVList: wire.TLVList{
  276. wire.NewTLVBE(wire.AdminTLVEmailAddress, uint16(0x00))},
  277. },
  278. },
  279. },
  280. expectOutput: wire.SNACMessage{
  281. Frame: wire.SNACFrame{
  282. FoodGroup: wire.Admin,
  283. SubGroup: wire.AdminInfoReply,
  284. RequestID: 1337,
  285. },
  286. Body: wire.SNAC_0x07_0x03_AdminInfoReply{
  287. Permissions: wire.AdminInfoPermissionsReadWrite,
  288. TLVBlock: wire.TLVBlock{
  289. TLVList: wire.TLVList{
  290. wire.NewTLVBE(wire.AdminTLVEmailAddress, "chattingchuck@aol.com"),
  291. },
  292. },
  293. },
  294. },
  295. mockParams: mockParams{
  296. accountManagerParams: accountManagerParams{
  297. accountManagerEmailAddressParams: accountManagerEmailAddressParams{
  298. {
  299. screenName: state.NewIdentScreenName("chattingchuck"),
  300. emailAddress: &mail.Address{
  301. Address: "chattingchuck@aol.com",
  302. },
  303. err: nil,
  304. },
  305. },
  306. },
  307. },
  308. },
  309. {
  310. name: "user requests account email address but not set",
  311. instance: newTestInstance("chattingchuck"),
  312. inputSNAC: wire.SNACMessage{
  313. Frame: wire.SNACFrame{
  314. FoodGroup: wire.Admin,
  315. SubGroup: wire.AdminInfoQuery,
  316. RequestID: 1337,
  317. },
  318. Body: wire.SNAC_0x07_0x02_AdminInfoQuery{
  319. TLVRestBlock: wire.TLVRestBlock{
  320. TLVList: wire.TLVList{
  321. wire.NewTLVBE(wire.AdminTLVEmailAddress, uint16(0x00))},
  322. },
  323. },
  324. },
  325. expectOutput: wire.SNACMessage{
  326. Frame: wire.SNACFrame{
  327. FoodGroup: wire.Admin,
  328. SubGroup: wire.AdminInfoReply,
  329. RequestID: 1337,
  330. },
  331. Body: wire.SNAC_0x07_0x03_AdminInfoReply{
  332. Permissions: wire.AdminInfoPermissionsReadWrite,
  333. TLVBlock: wire.TLVBlock{
  334. TLVList: wire.TLVList{
  335. wire.NewTLVBE(wire.AdminTLVEmailAddress, ""),
  336. },
  337. },
  338. },
  339. },
  340. mockParams: mockParams{
  341. accountManagerParams: accountManagerParams{
  342. accountManagerEmailAddressParams: accountManagerEmailAddressParams{
  343. {
  344. screenName: state.NewIdentScreenName("chattingchuck"),
  345. emailAddress: nil,
  346. err: state.ErrNoEmailAddress,
  347. },
  348. },
  349. },
  350. },
  351. },
  352. {
  353. name: "user requests formatted screenname",
  354. instance: newTestInstance("ChattingChuck"),
  355. inputSNAC: wire.SNACMessage{
  356. Frame: wire.SNACFrame{
  357. FoodGroup: wire.Admin,
  358. SubGroup: wire.AdminInfoQuery,
  359. RequestID: 1337,
  360. },
  361. Body: wire.SNAC_0x07_0x02_AdminInfoQuery{
  362. TLVRestBlock: wire.TLVRestBlock{
  363. TLVList: wire.TLVList{
  364. wire.NewTLVBE(wire.AdminTLVScreenNameFormatted, uint16(0x00))},
  365. },
  366. },
  367. },
  368. expectOutput: wire.SNACMessage{
  369. Frame: wire.SNACFrame{
  370. FoodGroup: wire.Admin,
  371. SubGroup: wire.AdminInfoReply,
  372. RequestID: 1337,
  373. },
  374. Body: wire.SNAC_0x07_0x03_AdminInfoReply{
  375. Permissions: wire.AdminInfoPermissionsReadWrite,
  376. TLVBlock: wire.TLVBlock{
  377. TLVList: wire.TLVList{
  378. wire.NewTLVBE(wire.AdminTLVScreenNameFormatted, "ChattingChuck"),
  379. },
  380. },
  381. },
  382. },
  383. },
  384. {
  385. name: "user requests invalid TLV",
  386. instance: newTestInstance("ChattingChuck"),
  387. inputSNAC: wire.SNACMessage{
  388. Frame: wire.SNACFrame{
  389. FoodGroup: wire.Admin,
  390. SubGroup: wire.AdminInfoQuery,
  391. RequestID: 1337,
  392. },
  393. Body: wire.SNAC_0x07_0x02_AdminInfoQuery{
  394. TLVRestBlock: wire.TLVRestBlock{
  395. TLVList: wire.TLVList{
  396. wire.NewTLVBE(uint16(0x99), uint16(0x00))},
  397. },
  398. },
  399. },
  400. expectOutput: wire.SNACMessage{
  401. Frame: wire.SNACFrame{
  402. FoodGroup: wire.Admin,
  403. SubGroup: wire.AdminErr,
  404. RequestID: 1337,
  405. },
  406. Body: wire.SNACError{
  407. Code: wire.ErrorCodeNotSupportedByHost,
  408. },
  409. },
  410. },
  411. }
  412. for _, tc := range cases {
  413. t.Run(tc.name, func(t *testing.T) {
  414. messageRelayer := newMockMessageRelayer(t)
  415. accountManager := newMockAccountManager(t)
  416. buddyBroadcaster := newMockbuddyBroadcaster(t)
  417. for _, params := range tc.mockParams.accountManagerRegStatusParams {
  418. accountManager.EXPECT().
  419. RegStatus(matchContext(), params.screenName).
  420. Return(params.regStatus, params.err)
  421. }
  422. for _, params := range tc.mockParams.accountManagerEmailAddressParams {
  423. accountManager.EXPECT().
  424. EmailAddress(matchContext(), params.screenName).
  425. Return(params.emailAddress, params.err)
  426. }
  427. svc := AdminService{
  428. messageRelayer: messageRelayer,
  429. accountManager: accountManager,
  430. buddyBroadcaster: buddyBroadcaster,
  431. }
  432. outputSNAC, err := svc.InfoQuery(context.Background(), tc.instance, tc.inputSNAC.Frame, tc.inputSNAC.Body.(wire.SNAC_0x07_0x02_AdminInfoQuery))
  433. assert.ErrorIs(t, err, tc.expectErr)
  434. if tc.expectErr != nil {
  435. return
  436. }
  437. assert.Equal(t, tc.expectOutput, outputSNAC)
  438. })
  439. }
  440. }
  441. func TestAdminService_InfoChangeRequest_ScreenName(t *testing.T) {
  442. cases := []struct {
  443. // name is the unit test name
  444. name string
  445. // cfg is the app configuration
  446. cfg config.Config
  447. // inputSNAC is the SNAC sent from the client to the server
  448. inputSNAC wire.SNACMessage
  449. // mockParams is the list of params sent to mocks that satisfy this
  450. // method's dependencies
  451. mockParams mockParams
  452. // instance is the session of the user
  453. instance *state.SessionInstance
  454. // expectOutput is the SNAC sent from the server to client
  455. expectOutput wire.SNACMessage
  456. // expectErr is the expected error returned
  457. expectErr error
  458. }{
  459. {
  460. name: "user changes screen name format successfully aim < 6",
  461. instance: newTestInstance("chattingchuck"),
  462. mockParams: mockParams{
  463. accountManagerParams: accountManagerParams{
  464. accountManagerUpdateDisplayScreenNameParams: accountManagerUpdateDisplayScreenNameParams{
  465. {
  466. displayScreenName: state.DisplayScreenName("Chatting Chuck"),
  467. },
  468. },
  469. },
  470. buddyBroadcasterParams: buddyBroadcasterParams{
  471. broadcastBuddyArrivedParams: broadcastBuddyArrivedParams{
  472. {
  473. screenName: state.DisplayScreenName("Chatting Chuck"),
  474. },
  475. },
  476. },
  477. messageRelayerParams: messageRelayerParams{
  478. relayToScreenNameParams: relayToScreenNameParams{
  479. {
  480. screenName: state.NewIdentScreenName("Chatting Chuck"),
  481. message: wire.SNACMessage{
  482. Frame: wire.SNACFrame{
  483. FoodGroup: wire.OService,
  484. SubGroup: wire.OServiceUserInfoUpdate,
  485. },
  486. Body: newOServiceUserInfoUpdate(newTestInstance("Chatting Chuck")),
  487. },
  488. },
  489. },
  490. },
  491. },
  492. inputSNAC: wire.SNACMessage{
  493. Frame: wire.SNACFrame{
  494. FoodGroup: wire.Admin,
  495. SubGroup: wire.AdminInfoChangeRequest,
  496. RequestID: 1337,
  497. },
  498. Body: wire.SNAC_0x07_0x04_AdminInfoChangeRequest{
  499. TLVRestBlock: wire.TLVRestBlock{
  500. TLVList: wire.TLVList{
  501. wire.NewTLVBE(wire.AdminTLVScreenNameFormatted, "Chatting Chuck"),
  502. },
  503. },
  504. },
  505. },
  506. expectOutput: wire.SNACMessage{
  507. Frame: wire.SNACFrame{
  508. FoodGroup: wire.Admin,
  509. SubGroup: wire.AdminInfoChangeReply,
  510. RequestID: 1337,
  511. },
  512. Body: wire.SNAC_0x07_0x05_AdminChangeReply{
  513. Permissions: wire.AdminInfoPermissionsReadWrite,
  514. TLVBlock: wire.TLVBlock{
  515. TLVList: wire.TLVList{
  516. wire.NewTLVBE(wire.AdminTLVScreenNameFormatted, "Chatting Chuck"),
  517. },
  518. },
  519. },
  520. },
  521. },
  522. {
  523. name: "user changes screen name format successfully aim >= 6",
  524. instance: newTestInstance("chattingchuck", sessOptSetFoodGroupVersion(wire.OService, 4)),
  525. mockParams: mockParams{
  526. accountManagerParams: accountManagerParams{
  527. accountManagerUpdateDisplayScreenNameParams: accountManagerUpdateDisplayScreenNameParams{
  528. {
  529. displayScreenName: state.DisplayScreenName("Chatting Chuck"),
  530. },
  531. },
  532. },
  533. buddyBroadcasterParams: buddyBroadcasterParams{
  534. broadcastBuddyArrivedParams: broadcastBuddyArrivedParams{
  535. {
  536. screenName: state.DisplayScreenName("Chatting Chuck"),
  537. },
  538. },
  539. },
  540. messageRelayerParams: messageRelayerParams{
  541. relayToScreenNameParams: relayToScreenNameParams{
  542. {
  543. screenName: state.NewIdentScreenName("Chatting Chuck"),
  544. message: wire.SNACMessage{
  545. Frame: wire.SNACFrame{
  546. FoodGroup: wire.OService,
  547. SubGroup: wire.OServiceUserInfoUpdate,
  548. },
  549. Body: newOServiceUserInfoUpdate(newTestInstance("Chatting Chuck", sessOptSetFoodGroupVersion(wire.OService, 4))),
  550. },
  551. },
  552. },
  553. },
  554. },
  555. inputSNAC: wire.SNACMessage{
  556. Frame: wire.SNACFrame{
  557. FoodGroup: wire.Admin,
  558. SubGroup: wire.AdminInfoChangeRequest,
  559. RequestID: 1337,
  560. },
  561. Body: wire.SNAC_0x07_0x04_AdminInfoChangeRequest{
  562. TLVRestBlock: wire.TLVRestBlock{
  563. TLVList: wire.TLVList{
  564. wire.NewTLVBE(wire.AdminTLVScreenNameFormatted, "Chatting Chuck"),
  565. },
  566. },
  567. },
  568. },
  569. expectOutput: wire.SNACMessage{
  570. Frame: wire.SNACFrame{
  571. FoodGroup: wire.Admin,
  572. SubGroup: wire.AdminInfoChangeReply,
  573. RequestID: 1337,
  574. },
  575. Body: wire.SNAC_0x07_0x05_AdminChangeReply{
  576. Permissions: wire.AdminInfoPermissionsReadWrite,
  577. TLVBlock: wire.TLVBlock{
  578. TLVList: wire.TLVList{
  579. wire.NewTLVBE(wire.AdminTLVScreenNameFormatted, "Chatting Chuck"),
  580. },
  581. },
  582. },
  583. },
  584. },
  585. {
  586. name: "proposed screen name is too long",
  587. instance: newTestInstance("chattingchuck"),
  588. inputSNAC: wire.SNACMessage{
  589. Frame: wire.SNACFrame{
  590. FoodGroup: wire.Admin,
  591. SubGroup: wire.AdminInfoChangeRequest,
  592. RequestID: 1337,
  593. },
  594. Body: wire.SNAC_0x07_0x04_AdminInfoChangeRequest{
  595. TLVRestBlock: wire.TLVRestBlock{
  596. TLVList: wire.TLVList{
  597. wire.NewTLVBE(wire.AdminTLVScreenNameFormatted, "c h a t t i n g c h u c k")},
  598. },
  599. },
  600. },
  601. expectOutput: wire.SNACMessage{
  602. Frame: wire.SNACFrame{
  603. FoodGroup: wire.Admin,
  604. SubGroup: wire.AdminInfoChangeReply,
  605. RequestID: 1337,
  606. },
  607. Body: wire.SNAC_0x07_0x05_AdminChangeReply{
  608. Permissions: wire.AdminInfoPermissionsReadWrite,
  609. TLVBlock: wire.TLVBlock{
  610. TLVList: wire.TLVList{
  611. wire.NewTLVBE(wire.AdminTLVErrorCode, wire.AdminInfoErrorInvalidNickNameLength),
  612. wire.NewTLVBE(wire.AdminTLVUrl, ""),
  613. },
  614. },
  615. },
  616. },
  617. },
  618. {
  619. name: "proposed screen name does not match session screen name",
  620. instance: newTestInstance("chattingchuck"),
  621. inputSNAC: wire.SNACMessage{
  622. Frame: wire.SNACFrame{
  623. FoodGroup: wire.Admin,
  624. SubGroup: wire.AdminInfoChangeRequest,
  625. RequestID: 1337,
  626. },
  627. Body: wire.SNAC_0x07_0x04_AdminInfoChangeRequest{
  628. TLVRestBlock: wire.TLVRestBlock{
  629. TLVList: wire.TLVList{
  630. wire.NewTLVBE(wire.AdminTLVScreenNameFormatted, "QuietQuinton")},
  631. },
  632. },
  633. },
  634. expectOutput: wire.SNACMessage{
  635. Frame: wire.SNACFrame{
  636. FoodGroup: wire.Admin,
  637. SubGroup: wire.AdminInfoChangeReply,
  638. RequestID: 1337,
  639. },
  640. Body: wire.SNAC_0x07_0x05_AdminChangeReply{
  641. Permissions: wire.AdminInfoPermissionsReadWrite,
  642. TLVBlock: wire.TLVBlock{
  643. TLVList: wire.TLVList{
  644. wire.NewTLVBE(wire.AdminTLVErrorCode, wire.AdminInfoErrorValidateNickName),
  645. wire.NewTLVBE(wire.AdminTLVUrl, ""),
  646. },
  647. },
  648. },
  649. },
  650. },
  651. {
  652. name: "proposed screen name ends in a space",
  653. instance: newTestInstance("chattingchuck"),
  654. inputSNAC: wire.SNACMessage{
  655. Frame: wire.SNACFrame{
  656. FoodGroup: wire.Admin,
  657. SubGroup: wire.AdminInfoChangeRequest,
  658. RequestID: 1337,
  659. },
  660. Body: wire.SNAC_0x07_0x04_AdminInfoChangeRequest{
  661. TLVRestBlock: wire.TLVRestBlock{
  662. TLVList: wire.TLVList{
  663. wire.NewTLVBE(wire.AdminTLVScreenNameFormatted, "ChattingChuck ")},
  664. },
  665. },
  666. },
  667. expectOutput: wire.SNACMessage{
  668. Frame: wire.SNACFrame{
  669. FoodGroup: wire.Admin,
  670. SubGroup: wire.AdminInfoChangeReply,
  671. RequestID: 1337,
  672. },
  673. Body: wire.SNAC_0x07_0x05_AdminChangeReply{
  674. Permissions: wire.AdminInfoPermissionsReadWrite,
  675. TLVBlock: wire.TLVBlock{
  676. TLVList: wire.TLVList{
  677. wire.NewTLVBE(wire.AdminTLVErrorCode, wire.AdminInfoErrorInvalidNickName),
  678. wire.NewTLVBE(wire.AdminTLVUrl, ""),
  679. },
  680. },
  681. },
  682. },
  683. },
  684. }
  685. for _, tc := range cases {
  686. t.Run(tc.name, func(t *testing.T) {
  687. messageRelayer := newMockMessageRelayer(t)
  688. accountManager := newMockAccountManager(t)
  689. mockBuddyBroadcaster := newMockbuddyBroadcaster(t)
  690. for _, params := range tc.mockParams.accountManagerUpdateDisplayScreenNameParams {
  691. accountManager.EXPECT().
  692. UpdateDisplayScreenName(matchContext(), params.displayScreenName).
  693. Return(params.err)
  694. }
  695. for _, params := range tc.mockParams.broadcastBuddyArrivedParams {
  696. mockBuddyBroadcaster.EXPECT().
  697. BroadcastBuddyArrived(mock.Anything, state.NewIdentScreenName(params.screenName.String()), mock.MatchedBy(func(userInfo wire.TLVUserInfo) bool {
  698. return userInfo.ScreenName == params.screenName.String()
  699. })).
  700. Return(params.err)
  701. }
  702. for _, params := range tc.mockParams.relayToScreenNameParams {
  703. p := params
  704. messageRelayer.EXPECT().
  705. RelayToScreenName(mock.Anything, p.screenName, p.message)
  706. }
  707. svc := AdminService{
  708. accountManager: accountManager,
  709. buddyBroadcaster: mockBuddyBroadcaster,
  710. messageRelayer: messageRelayer,
  711. }
  712. outputSNAC, err := svc.InfoChangeRequest(context.Background(), tc.instance, tc.inputSNAC.Frame, tc.inputSNAC.Body.(wire.SNAC_0x07_0x04_AdminInfoChangeRequest))
  713. assert.ErrorIs(t, err, tc.expectErr)
  714. if tc.expectErr != nil {
  715. return
  716. }
  717. assert.Equal(t, tc.expectOutput, outputSNAC)
  718. })
  719. }
  720. }
  721. func TestAdminService_InfoChangeRequest_EmailAddress(t *testing.T) {
  722. // One case needs a 320 character long email address
  723. longEmailAddress := "longemailaddress@"
  724. for i := 0; i < 50; i++ {
  725. longEmailAddress += "domain"
  726. }
  727. longEmailAddress += ".com"
  728. cases := []struct {
  729. // name is the unit test name
  730. name string
  731. // cfg is the app configuration
  732. cfg config.Config
  733. // inputSNAC is the SNAC sent from the client to the server
  734. inputSNAC wire.SNACMessage
  735. // mockParams is the list of params sent to mocks that satisfy this
  736. // method's dependencies
  737. mockParams mockParams
  738. // instance is the session of the user
  739. instance *state.SessionInstance
  740. // expectOutput is the SNAC sent from the server to client
  741. expectOutput wire.SNACMessage
  742. // expectErr is the expected error returned
  743. expectErr error
  744. }{
  745. {
  746. name: "user changes email address successfully",
  747. instance: newTestInstance("chattingchuck"),
  748. mockParams: mockParams{
  749. accountManagerParams: accountManagerParams{
  750. accountManagerUpdateEmailAddressParams: accountManagerUpdateEmailAddressParams{
  751. {
  752. screenName: state.NewIdentScreenName("chattingchuck"),
  753. emailAddress: &mail.Address{
  754. Address: "chattingchuck@aol.com",
  755. },
  756. },
  757. },
  758. },
  759. },
  760. inputSNAC: wire.SNACMessage{
  761. Frame: wire.SNACFrame{
  762. FoodGroup: wire.Admin,
  763. SubGroup: wire.AdminInfoChangeRequest,
  764. RequestID: 1337,
  765. },
  766. Body: wire.SNAC_0x07_0x04_AdminInfoChangeRequest{
  767. TLVRestBlock: wire.TLVRestBlock{
  768. TLVList: wire.TLVList{
  769. wire.NewTLVBE(wire.AdminTLVEmailAddress, "chattingchuck@aol.com"),
  770. },
  771. },
  772. },
  773. },
  774. expectOutput: wire.SNACMessage{
  775. Frame: wire.SNACFrame{
  776. FoodGroup: wire.Admin,
  777. SubGroup: wire.AdminInfoChangeReply,
  778. RequestID: 1337,
  779. },
  780. Body: wire.SNAC_0x07_0x05_AdminChangeReply{
  781. Permissions: wire.AdminInfoPermissionsReadWrite,
  782. TLVBlock: wire.TLVBlock{
  783. TLVList: wire.TLVList{
  784. wire.NewTLVBE(wire.AdminTLVEmailAddress, "chattingchuck@aol.com"),
  785. },
  786. },
  787. },
  788. },
  789. },
  790. {
  791. name: "proposed email address invalid rfc 5322 format",
  792. instance: newTestInstance("chattingchuck"),
  793. inputSNAC: wire.SNACMessage{
  794. Frame: wire.SNACFrame{
  795. FoodGroup: wire.Admin,
  796. SubGroup: wire.AdminInfoChangeRequest,
  797. RequestID: 1337,
  798. },
  799. Body: wire.SNAC_0x07_0x04_AdminInfoChangeRequest{
  800. TLVRestBlock: wire.TLVRestBlock{
  801. TLVList: wire.TLVList{
  802. wire.NewTLVBE(wire.AdminTLVEmailAddress, "chattingchuck@@@@@@@aol.com"),
  803. },
  804. },
  805. },
  806. },
  807. expectOutput: wire.SNACMessage{
  808. Frame: wire.SNACFrame{
  809. FoodGroup: wire.Admin,
  810. SubGroup: wire.AdminInfoChangeReply,
  811. RequestID: 1337,
  812. },
  813. Body: wire.SNAC_0x07_0x05_AdminChangeReply{
  814. Permissions: wire.AdminInfoPermissionsReadWrite,
  815. TLVBlock: wire.TLVBlock{
  816. TLVList: wire.TLVList{
  817. wire.NewTLVBE(wire.AdminTLVErrorCode, wire.AdminInfoErrorInvalidEmail),
  818. wire.NewTLVBE(wire.AdminTLVUrl, ""),
  819. },
  820. },
  821. },
  822. },
  823. },
  824. {
  825. name: "proposed email address too long",
  826. instance: newTestInstance("chattingchuck"),
  827. inputSNAC: wire.SNACMessage{
  828. Frame: wire.SNACFrame{
  829. FoodGroup: wire.Admin,
  830. SubGroup: wire.AdminInfoChangeRequest,
  831. RequestID: 1337,
  832. },
  833. Body: wire.SNAC_0x07_0x04_AdminInfoChangeRequest{
  834. TLVRestBlock: wire.TLVRestBlock{
  835. TLVList: wire.TLVList{
  836. wire.NewTLVBE(wire.AdminTLVEmailAddress, longEmailAddress),
  837. },
  838. },
  839. },
  840. },
  841. expectOutput: wire.SNACMessage{
  842. Frame: wire.SNACFrame{
  843. FoodGroup: wire.Admin,
  844. SubGroup: wire.AdminInfoChangeReply,
  845. RequestID: 1337,
  846. },
  847. Body: wire.SNAC_0x07_0x05_AdminChangeReply{
  848. Permissions: wire.AdminInfoPermissionsReadWrite,
  849. TLVBlock: wire.TLVBlock{
  850. TLVList: wire.TLVList{
  851. wire.NewTLVBE(wire.AdminTLVErrorCode, wire.AdminInfoErrorInvalidEmailLength),
  852. wire.NewTLVBE(wire.AdminTLVUrl, ""),
  853. },
  854. },
  855. },
  856. },
  857. },
  858. }
  859. for _, tc := range cases {
  860. t.Run(tc.name, func(t *testing.T) {
  861. messageRelayer := newMockMessageRelayer(t)
  862. accountManager := newMockAccountManager(t)
  863. buddyBroadcaster := newMockbuddyBroadcaster(t)
  864. for _, params := range tc.mockParams.accountManagerUpdateEmailAddressParams {
  865. accountManager.EXPECT().
  866. UpdateEmailAddress(matchContext(), params.screenName, params.emailAddress).
  867. Return(params.err)
  868. }
  869. svc := AdminService{
  870. accountManager: accountManager,
  871. buddyBroadcaster: buddyBroadcaster,
  872. messageRelayer: messageRelayer,
  873. }
  874. outputSNAC, err := svc.InfoChangeRequest(context.Background(), tc.instance, tc.inputSNAC.Frame, tc.inputSNAC.Body.(wire.SNAC_0x07_0x04_AdminInfoChangeRequest))
  875. assert.ErrorIs(t, err, tc.expectErr)
  876. if tc.expectErr != nil {
  877. return
  878. }
  879. assert.Equal(t, tc.expectOutput, outputSNAC)
  880. })
  881. }
  882. }
  883. func TestAdminService_InfoChangeRequest_RegStatus(t *testing.T) {
  884. cases := []struct {
  885. // name is the unit test name
  886. name string
  887. // cfg is the app configuration
  888. cfg config.Config
  889. // inputSNAC is the SNAC sent from the client to the server
  890. inputSNAC wire.SNACMessage
  891. // mockParams is the list of params sent to mocks that satisfy this
  892. // method's dependencies
  893. mockParams mockParams
  894. // instance is the session of the user
  895. instance *state.SessionInstance
  896. // expectOutput is the SNAC sent from the server to client
  897. expectOutput wire.SNACMessage
  898. // expectErr is the expected error returned
  899. expectErr error
  900. }{
  901. {
  902. name: "user changes reg preference successfully",
  903. instance: newTestInstance("chattingchuck"),
  904. mockParams: mockParams{
  905. accountManagerParams: accountManagerParams{
  906. accountManagerUpdateRegStatusParams: accountManagerUpdateRegStatusParams{
  907. {
  908. screenName: state.NewIdentScreenName("chattingchuck"),
  909. regStatus: wire.AdminInfoRegStatusNoDisclosure,
  910. },
  911. },
  912. },
  913. },
  914. inputSNAC: wire.SNACMessage{
  915. Frame: wire.SNACFrame{
  916. FoodGroup: wire.Admin,
  917. SubGroup: wire.AdminInfoChangeRequest,
  918. RequestID: 1337,
  919. },
  920. Body: wire.SNAC_0x07_0x04_AdminInfoChangeRequest{
  921. TLVRestBlock: wire.TLVRestBlock{
  922. TLVList: wire.TLVList{
  923. wire.NewTLVBE(wire.AdminTLVRegistrationStatus, wire.AdminInfoRegStatusNoDisclosure),
  924. },
  925. },
  926. },
  927. },
  928. expectOutput: wire.SNACMessage{
  929. Frame: wire.SNACFrame{
  930. FoodGroup: wire.Admin,
  931. SubGroup: wire.AdminInfoChangeReply,
  932. RequestID: 1337,
  933. },
  934. Body: wire.SNAC_0x07_0x05_AdminChangeReply{
  935. Permissions: wire.AdminInfoPermissionsReadWrite,
  936. TLVBlock: wire.TLVBlock{
  937. TLVList: wire.TLVList{
  938. wire.NewTLVBE(wire.AdminTLVRegistrationStatus, wire.AdminInfoRegStatusNoDisclosure),
  939. },
  940. },
  941. },
  942. },
  943. },
  944. {
  945. name: "proposed reg preference invalid",
  946. instance: newTestInstance("chattingchuck"),
  947. inputSNAC: wire.SNACMessage{
  948. Frame: wire.SNACFrame{
  949. FoodGroup: wire.Admin,
  950. SubGroup: wire.AdminInfoChangeRequest,
  951. RequestID: 1337,
  952. },
  953. Body: wire.SNAC_0x07_0x04_AdminInfoChangeRequest{
  954. TLVRestBlock: wire.TLVRestBlock{
  955. TLVList: wire.TLVList{
  956. wire.NewTLVBE(wire.AdminTLVRegistrationStatus, uint16(0x1337)),
  957. },
  958. },
  959. },
  960. },
  961. expectOutput: wire.SNACMessage{
  962. Frame: wire.SNACFrame{
  963. FoodGroup: wire.Admin,
  964. SubGroup: wire.AdminInfoChangeReply,
  965. RequestID: 1337,
  966. },
  967. Body: wire.SNAC_0x07_0x05_AdminChangeReply{
  968. Permissions: wire.AdminInfoPermissionsReadWrite,
  969. TLVBlock: wire.TLVBlock{
  970. TLVList: wire.TLVList{
  971. wire.NewTLVBE(wire.AdminTLVErrorCode, wire.AdminInfoErrorInvalidRegistrationPreference),
  972. wire.NewTLVBE(wire.AdminTLVUrl, ""),
  973. },
  974. },
  975. },
  976. },
  977. },
  978. }
  979. for _, tc := range cases {
  980. t.Run(tc.name, func(t *testing.T) {
  981. messageRelayer := newMockMessageRelayer(t)
  982. accountManager := newMockAccountManager(t)
  983. buddyBroadcaster := newMockbuddyBroadcaster(t)
  984. for _, params := range tc.mockParams.accountManagerUpdateRegStatusParams {
  985. accountManager.EXPECT().
  986. UpdateRegStatus(context.Background(), params.screenName, params.regStatus).
  987. Return(params.err)
  988. }
  989. svc := AdminService{
  990. accountManager: accountManager,
  991. buddyBroadcaster: buddyBroadcaster,
  992. messageRelayer: messageRelayer,
  993. }
  994. outputSNAC, err := svc.InfoChangeRequest(context.Background(), tc.instance, tc.inputSNAC.Frame, tc.inputSNAC.Body.(wire.SNAC_0x07_0x04_AdminInfoChangeRequest))
  995. assert.ErrorIs(t, err, tc.expectErr)
  996. if tc.expectErr != nil {
  997. return
  998. }
  999. assert.Equal(t, tc.expectOutput, outputSNAC)
  1000. })
  1001. }
  1002. }
  1003. func TestAdminService_InfoChangeRequest_Password(t *testing.T) {
  1004. cases := []struct {
  1005. // name is the unit test name
  1006. name string
  1007. // cfg is the app configuration
  1008. cfg config.Config
  1009. // inputSNAC is the SNAC sent from the client to the server
  1010. inputSNAC wire.SNACMessage
  1011. // mockParams is the list of params sent to mocks that satisfy this
  1012. // method's dependencies
  1013. mockParams mockParams
  1014. // instance is the session of the user
  1015. instance *state.SessionInstance
  1016. // expectOutput is the SNAC sent from the server to client
  1017. expectOutput wire.SNACMessage
  1018. // expectErr is the expected error returned
  1019. expectErr error
  1020. }{
  1021. {
  1022. name: "user changes password successfully",
  1023. instance: newTestInstance("me"),
  1024. mockParams: mockParams{
  1025. accountManagerParams: accountManagerParams{
  1026. accountManagerSetUserPasswordParams: accountManagerSetUserPasswordParams{
  1027. {
  1028. screenName: state.NewIdentScreenName("me"),
  1029. password: "newpass",
  1030. },
  1031. },
  1032. accountManagerUserParams: accountManagerUserParams{
  1033. {
  1034. screenName: state.NewIdentScreenName("me"),
  1035. result: func() *state.User {
  1036. user := &state.User{
  1037. AuthKey: "auth_key",
  1038. }
  1039. assert.NoError(t, user.HashPassword("oldpass"))
  1040. return user
  1041. }(),
  1042. },
  1043. },
  1044. },
  1045. },
  1046. inputSNAC: wire.SNACMessage{
  1047. Frame: wire.SNACFrame{
  1048. FoodGroup: wire.Admin,
  1049. SubGroup: wire.AdminInfoChangeRequest,
  1050. RequestID: 1337,
  1051. },
  1052. Body: wire.SNAC_0x07_0x04_AdminInfoChangeRequest{
  1053. TLVRestBlock: wire.TLVRestBlock{
  1054. TLVList: wire.TLVList{
  1055. wire.NewTLVBE(wire.AdminTLVOldPassword, "oldpass"),
  1056. wire.NewTLVBE(wire.AdminTLVNewPassword, "newpass"),
  1057. },
  1058. },
  1059. },
  1060. },
  1061. expectOutput: wire.SNACMessage{
  1062. Frame: wire.SNACFrame{
  1063. FoodGroup: wire.Admin,
  1064. SubGroup: wire.AdminInfoChangeReply,
  1065. RequestID: 1337,
  1066. },
  1067. Body: wire.SNAC_0x07_0x05_AdminChangeReply{
  1068. Permissions: wire.AdminInfoPermissionsReadWrite,
  1069. TLVBlock: wire.TLVBlock{
  1070. TLVList: wire.TLVList{
  1071. wire.NewTLVBE(wire.AdminTLVNewPassword, []byte{}),
  1072. },
  1073. },
  1074. },
  1075. },
  1076. },
  1077. {
  1078. name: "user changes password, invalid new password length",
  1079. instance: newTestInstance("me"),
  1080. mockParams: mockParams{
  1081. accountManagerParams: accountManagerParams{
  1082. accountManagerSetUserPasswordParams: accountManagerSetUserPasswordParams{
  1083. {
  1084. screenName: state.NewIdentScreenName("me"),
  1085. password: "newpass",
  1086. err: state.ErrPasswordInvalid,
  1087. },
  1088. },
  1089. accountManagerUserParams: accountManagerUserParams{
  1090. {
  1091. screenName: state.NewIdentScreenName("me"),
  1092. result: func() *state.User {
  1093. user := &state.User{
  1094. AuthKey: "auth_key",
  1095. }
  1096. assert.NoError(t, user.HashPassword("oldpass"))
  1097. return user
  1098. }(),
  1099. },
  1100. },
  1101. },
  1102. },
  1103. inputSNAC: wire.SNACMessage{
  1104. Frame: wire.SNACFrame{
  1105. FoodGroup: wire.Admin,
  1106. SubGroup: wire.AdminInfoChangeRequest,
  1107. RequestID: 1337,
  1108. },
  1109. Body: wire.SNAC_0x07_0x04_AdminInfoChangeRequest{
  1110. TLVRestBlock: wire.TLVRestBlock{
  1111. TLVList: wire.TLVList{
  1112. wire.NewTLVBE(wire.AdminTLVOldPassword, "oldpass"),
  1113. wire.NewTLVBE(wire.AdminTLVNewPassword, "newpass"),
  1114. },
  1115. },
  1116. },
  1117. },
  1118. expectOutput: wire.SNACMessage{
  1119. Frame: wire.SNACFrame{
  1120. FoodGroup: wire.Admin,
  1121. SubGroup: wire.AdminInfoChangeReply,
  1122. RequestID: 1337,
  1123. },
  1124. Body: wire.SNAC_0x07_0x05_AdminChangeReply{
  1125. Permissions: wire.AdminInfoPermissionsReadWrite,
  1126. TLVBlock: wire.TLVBlock{
  1127. TLVList: wire.TLVList{
  1128. wire.NewTLVBE(wire.AdminTLVNewPassword, []byte{}),
  1129. wire.NewTLVBE(wire.AdminTLVErrorCode, wire.AdminInfoErrorInvalidPasswordLength),
  1130. },
  1131. },
  1132. },
  1133. },
  1134. },
  1135. {
  1136. name: "user changes password, set user password runtime error",
  1137. instance: newTestInstance("me"),
  1138. mockParams: mockParams{
  1139. accountManagerParams: accountManagerParams{
  1140. accountManagerSetUserPasswordParams: accountManagerSetUserPasswordParams{
  1141. {
  1142. screenName: state.NewIdentScreenName("me"),
  1143. password: "newpass",
  1144. err: io.EOF,
  1145. },
  1146. },
  1147. accountManagerUserParams: accountManagerUserParams{
  1148. {
  1149. screenName: state.NewIdentScreenName("me"),
  1150. result: func() *state.User {
  1151. user := &state.User{
  1152. AuthKey: "auth_key",
  1153. }
  1154. assert.NoError(t, user.HashPassword("oldpass"))
  1155. return user
  1156. }(),
  1157. },
  1158. },
  1159. },
  1160. },
  1161. inputSNAC: wire.SNACMessage{
  1162. Frame: wire.SNACFrame{
  1163. FoodGroup: wire.Admin,
  1164. SubGroup: wire.AdminInfoChangeRequest,
  1165. RequestID: 1337,
  1166. },
  1167. Body: wire.SNAC_0x07_0x04_AdminInfoChangeRequest{
  1168. TLVRestBlock: wire.TLVRestBlock{
  1169. TLVList: wire.TLVList{
  1170. wire.NewTLVBE(wire.AdminTLVOldPassword, "oldpass"),
  1171. wire.NewTLVBE(wire.AdminTLVNewPassword, "newpass"),
  1172. },
  1173. },
  1174. },
  1175. },
  1176. expectOutput: wire.SNACMessage{
  1177. Frame: wire.SNACFrame{
  1178. FoodGroup: wire.Admin,
  1179. SubGroup: wire.AdminInfoChangeReply,
  1180. RequestID: 1337,
  1181. },
  1182. Body: wire.SNAC_0x07_0x05_AdminChangeReply{
  1183. Permissions: wire.AdminInfoPermissionsReadWrite,
  1184. TLVBlock: wire.TLVBlock{
  1185. TLVList: wire.TLVList{
  1186. wire.NewTLVBE(wire.AdminTLVNewPassword, []byte{}),
  1187. wire.NewTLVBE(wire.AdminTLVErrorCode, wire.AdminInfoErrorAllOtherErrors),
  1188. },
  1189. },
  1190. },
  1191. },
  1192. },
  1193. {
  1194. name: "user changes password, old password is invalid",
  1195. instance: newTestInstance("me"),
  1196. mockParams: mockParams{
  1197. accountManagerParams: accountManagerParams{
  1198. accountManagerUserParams: accountManagerUserParams{
  1199. {
  1200. screenName: state.NewIdentScreenName("me"),
  1201. result: func() *state.User {
  1202. user := &state.User{
  1203. AuthKey: "auth_key",
  1204. }
  1205. assert.NoError(t, user.HashPassword("oldpass"))
  1206. return user
  1207. }(),
  1208. },
  1209. },
  1210. },
  1211. },
  1212. inputSNAC: wire.SNACMessage{
  1213. Frame: wire.SNACFrame{
  1214. FoodGroup: wire.Admin,
  1215. SubGroup: wire.AdminInfoChangeRequest,
  1216. RequestID: 1337,
  1217. },
  1218. Body: wire.SNAC_0x07_0x04_AdminInfoChangeRequest{
  1219. TLVRestBlock: wire.TLVRestBlock{
  1220. TLVList: wire.TLVList{
  1221. wire.NewTLVBE(wire.AdminTLVOldPassword, "oldpassbad"),
  1222. wire.NewTLVBE(wire.AdminTLVNewPassword, "newpass"),
  1223. },
  1224. },
  1225. },
  1226. },
  1227. expectOutput: wire.SNACMessage{
  1228. Frame: wire.SNACFrame{
  1229. FoodGroup: wire.Admin,
  1230. SubGroup: wire.AdminInfoChangeReply,
  1231. RequestID: 1337,
  1232. },
  1233. Body: wire.SNAC_0x07_0x05_AdminChangeReply{
  1234. Permissions: wire.AdminInfoPermissionsReadWrite,
  1235. TLVBlock: wire.TLVBlock{
  1236. TLVList: wire.TLVList{
  1237. wire.NewTLVBE(wire.AdminTLVNewPassword, []byte{}),
  1238. wire.NewTLVBE(wire.AdminTLVErrorCode, wire.AdminInfoErrorValidatePassword),
  1239. },
  1240. },
  1241. },
  1242. },
  1243. },
  1244. {
  1245. name: "user changes password, user not found",
  1246. instance: newTestInstance("me"),
  1247. mockParams: mockParams{
  1248. accountManagerParams: accountManagerParams{
  1249. accountManagerUserParams: accountManagerUserParams{
  1250. {
  1251. screenName: state.NewIdentScreenName("me"),
  1252. result: nil,
  1253. },
  1254. },
  1255. },
  1256. },
  1257. inputSNAC: wire.SNACMessage{
  1258. Frame: wire.SNACFrame{
  1259. FoodGroup: wire.Admin,
  1260. SubGroup: wire.AdminInfoChangeRequest,
  1261. RequestID: 1337,
  1262. },
  1263. Body: wire.SNAC_0x07_0x04_AdminInfoChangeRequest{
  1264. TLVRestBlock: wire.TLVRestBlock{
  1265. TLVList: wire.TLVList{
  1266. wire.NewTLVBE(wire.AdminTLVOldPassword, "oldpass"),
  1267. wire.NewTLVBE(wire.AdminTLVNewPassword, "newpass"),
  1268. },
  1269. },
  1270. },
  1271. },
  1272. expectOutput: wire.SNACMessage{
  1273. Frame: wire.SNACFrame{
  1274. FoodGroup: wire.Admin,
  1275. SubGroup: wire.AdminInfoChangeReply,
  1276. RequestID: 1337,
  1277. },
  1278. Body: wire.SNAC_0x07_0x05_AdminChangeReply{
  1279. Permissions: wire.AdminInfoPermissionsReadWrite,
  1280. TLVBlock: wire.TLVBlock{
  1281. TLVList: wire.TLVList{
  1282. wire.NewTLVBE(wire.AdminTLVNewPassword, []byte{}),
  1283. wire.NewTLVBE(wire.AdminTLVErrorCode, wire.AdminInfoErrorAllOtherErrors),
  1284. },
  1285. },
  1286. },
  1287. },
  1288. },
  1289. {
  1290. name: "user changes password, user lookup runtime error",
  1291. instance: newTestInstance("me"),
  1292. mockParams: mockParams{
  1293. accountManagerParams: accountManagerParams{
  1294. accountManagerUserParams: accountManagerUserParams{
  1295. {
  1296. screenName: state.NewIdentScreenName("me"),
  1297. err: io.EOF,
  1298. },
  1299. },
  1300. },
  1301. },
  1302. inputSNAC: wire.SNACMessage{
  1303. Frame: wire.SNACFrame{
  1304. FoodGroup: wire.Admin,
  1305. SubGroup: wire.AdminInfoChangeRequest,
  1306. RequestID: 1337,
  1307. },
  1308. Body: wire.SNAC_0x07_0x04_AdminInfoChangeRequest{
  1309. TLVRestBlock: wire.TLVRestBlock{
  1310. TLVList: wire.TLVList{
  1311. wire.NewTLVBE(wire.AdminTLVOldPassword, "oldpass"),
  1312. wire.NewTLVBE(wire.AdminTLVNewPassword, "newpass"),
  1313. },
  1314. },
  1315. },
  1316. },
  1317. expectOutput: wire.SNACMessage{
  1318. Frame: wire.SNACFrame{
  1319. FoodGroup: wire.Admin,
  1320. SubGroup: wire.AdminInfoChangeReply,
  1321. RequestID: 1337,
  1322. },
  1323. Body: wire.SNAC_0x07_0x05_AdminChangeReply{
  1324. Permissions: wire.AdminInfoPermissionsReadWrite,
  1325. TLVBlock: wire.TLVBlock{
  1326. TLVList: wire.TLVList{
  1327. wire.NewTLVBE(wire.AdminTLVNewPassword, []byte{}),
  1328. wire.NewTLVBE(wire.AdminTLVErrorCode, wire.AdminInfoErrorAllOtherErrors),
  1329. },
  1330. },
  1331. },
  1332. },
  1333. },
  1334. {
  1335. name: "user changes password, missing old password",
  1336. instance: newTestInstance("me"),
  1337. mockParams: mockParams{},
  1338. inputSNAC: wire.SNACMessage{
  1339. Frame: wire.SNACFrame{
  1340. FoodGroup: wire.Admin,
  1341. SubGroup: wire.AdminInfoChangeRequest,
  1342. RequestID: 1337,
  1343. },
  1344. Body: wire.SNAC_0x07_0x04_AdminInfoChangeRequest{
  1345. TLVRestBlock: wire.TLVRestBlock{
  1346. TLVList: wire.TLVList{
  1347. wire.NewTLVBE(wire.AdminTLVNewPassword, "newpass"),
  1348. },
  1349. },
  1350. },
  1351. },
  1352. expectOutput: wire.SNACMessage{
  1353. Frame: wire.SNACFrame{
  1354. FoodGroup: wire.Admin,
  1355. SubGroup: wire.AdminInfoChangeReply,
  1356. RequestID: 1337,
  1357. },
  1358. Body: wire.SNAC_0x07_0x05_AdminChangeReply{
  1359. Permissions: wire.AdminInfoPermissionsReadWrite,
  1360. TLVBlock: wire.TLVBlock{
  1361. TLVList: wire.TLVList{
  1362. wire.NewTLVBE(wire.AdminTLVNewPassword, []byte{}),
  1363. wire.NewTLVBE(wire.AdminTLVErrorCode, wire.AdminInfoErrorNeedOldPassword),
  1364. },
  1365. },
  1366. },
  1367. },
  1368. },
  1369. }
  1370. for _, tc := range cases {
  1371. t.Run(tc.name, func(t *testing.T) {
  1372. accountManager := newMockAccountManager(t)
  1373. for _, params := range tc.mockParams.accountManagerUserParams {
  1374. accountManager.EXPECT().
  1375. User(matchContext(), params.screenName).
  1376. Return(params.result, params.err)
  1377. }
  1378. for _, params := range tc.mockParams.accountManagerSetUserPasswordParams {
  1379. accountManager.EXPECT().
  1380. SetUserPassword(matchContext(), params.screenName, params.password).
  1381. Return(params.err)
  1382. }
  1383. svc := AdminService{
  1384. accountManager: accountManager,
  1385. logger: slog.Default(),
  1386. }
  1387. outputSNAC, err := svc.InfoChangeRequest(context.Background(), tc.instance, tc.inputSNAC.Frame, tc.inputSNAC.Body.(wire.SNAC_0x07_0x04_AdminInfoChangeRequest))
  1388. assert.ErrorIs(t, err, tc.expectErr)
  1389. if tc.expectErr != nil {
  1390. return
  1391. }
  1392. assert.Equal(t, tc.expectOutput, outputSNAC)
  1393. })
  1394. }
  1395. }