server_account_test.go 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485
  1. package server
  2. import (
  3. "fmt"
  4. "github.com/stretchr/testify/require"
  5. "heckel.io/ntfy/user"
  6. "heckel.io/ntfy/util"
  7. "io"
  8. "testing"
  9. "time"
  10. )
  11. func TestAccount_Signup_Success(t *testing.T) {
  12. conf := newTestConfigWithAuthFile(t)
  13. conf.EnableSignup = true
  14. s := newTestServer(t, conf)
  15. rr := request(t, s, "POST", "/v1/account", `{"username":"phil", "password":"mypass"}`, nil)
  16. require.Equal(t, 200, rr.Code)
  17. rr = request(t, s, "POST", "/v1/account/token", "", map[string]string{
  18. "Authorization": util.BasicAuth("phil", "mypass"),
  19. })
  20. require.Equal(t, 200, rr.Code)
  21. token, _ := util.UnmarshalJSON[apiAccountTokenResponse](io.NopCloser(rr.Body))
  22. require.NotEmpty(t, token.Token)
  23. require.True(t, time.Now().Add(71*time.Hour).Unix() < token.Expires)
  24. rr = request(t, s, "GET", "/v1/account", "", map[string]string{
  25. "Authorization": util.BearerAuth(token.Token),
  26. })
  27. require.Equal(t, 200, rr.Code)
  28. account, _ := util.UnmarshalJSON[apiAccountResponse](io.NopCloser(rr.Body))
  29. require.Equal(t, "phil", account.Username)
  30. require.Equal(t, "user", account.Role)
  31. }
  32. func TestAccount_Signup_UserExists(t *testing.T) {
  33. conf := newTestConfigWithAuthFile(t)
  34. conf.EnableSignup = true
  35. s := newTestServer(t, conf)
  36. rr := request(t, s, "POST", "/v1/account", `{"username":"phil", "password":"mypass"}`, nil)
  37. require.Equal(t, 200, rr.Code)
  38. rr = request(t, s, "POST", "/v1/account", `{"username":"phil", "password":"mypass"}`, nil)
  39. require.Equal(t, 409, rr.Code)
  40. require.Equal(t, 40901, toHTTPError(t, rr.Body.String()).Code)
  41. }
  42. func TestAccount_Signup_LimitReached(t *testing.T) {
  43. conf := newTestConfigWithAuthFile(t)
  44. conf.EnableSignup = true
  45. s := newTestServer(t, conf)
  46. for i := 0; i < 3; i++ {
  47. rr := request(t, s, "POST", "/v1/account", fmt.Sprintf(`{"username":"phil%d", "password":"mypass"}`, i), nil)
  48. require.Equal(t, 200, rr.Code)
  49. }
  50. rr := request(t, s, "POST", "/v1/account", `{"username":"thiswontwork", "password":"mypass"}`, nil)
  51. require.Equal(t, 429, rr.Code)
  52. require.Equal(t, 42906, toHTTPError(t, rr.Body.String()).Code)
  53. }
  54. func TestAccount_Signup_AsUser(t *testing.T) {
  55. conf := newTestConfigWithAuthFile(t)
  56. conf.EnableSignup = true
  57. s := newTestServer(t, conf)
  58. require.Nil(t, s.userManager.AddUser("phil", "phil", user.RoleAdmin, "unit-test"))
  59. require.Nil(t, s.userManager.AddUser("ben", "ben", user.RoleUser, "unit-test"))
  60. rr := request(t, s, "POST", "/v1/account", `{"username":"emma", "password":"emma"}`, map[string]string{
  61. "Authorization": util.BasicAuth("phil", "phil"),
  62. })
  63. require.Equal(t, 200, rr.Code)
  64. rr = request(t, s, "POST", "/v1/account", `{"username":"marian", "password":"marian"}`, map[string]string{
  65. "Authorization": util.BasicAuth("ben", "ben"),
  66. })
  67. require.Equal(t, 401, rr.Code)
  68. }
  69. func TestAccount_Signup_Disabled(t *testing.T) {
  70. conf := newTestConfigWithAuthFile(t)
  71. conf.EnableSignup = false
  72. s := newTestServer(t, conf)
  73. rr := request(t, s, "POST", "/v1/account", `{"username":"phil", "password":"mypass"}`, nil)
  74. require.Equal(t, 400, rr.Code)
  75. require.Equal(t, 40022, toHTTPError(t, rr.Body.String()).Code)
  76. }
  77. func TestAccount_Get_Anonymous(t *testing.T) {
  78. conf := newTestConfigWithAuthFile(t)
  79. conf.VisitorRequestLimitReplenish = 86 * time.Second
  80. conf.VisitorEmailLimitReplenish = time.Hour
  81. conf.VisitorAttachmentTotalSizeLimit = 5123
  82. conf.AttachmentFileSizeLimit = 512
  83. s := newTestServer(t, conf)
  84. s.smtpSender = &testMailer{}
  85. rr := request(t, s, "GET", "/v1/account", "", nil)
  86. require.Equal(t, 200, rr.Code)
  87. account, _ := util.UnmarshalJSON[apiAccountResponse](io.NopCloser(rr.Body))
  88. require.Equal(t, "*", account.Username)
  89. require.Equal(t, string(user.RoleAnonymous), account.Role)
  90. require.Equal(t, "ip", account.Limits.Basis)
  91. require.Equal(t, int64(1004), account.Limits.Messages) // I hate this
  92. require.Equal(t, int64(24), account.Limits.Emails) // I hate this
  93. require.Equal(t, int64(5123), account.Limits.AttachmentTotalSize)
  94. require.Equal(t, int64(512), account.Limits.AttachmentFileSize)
  95. require.Equal(t, int64(0), account.Stats.Messages)
  96. require.Equal(t, int64(1004), account.Stats.MessagesRemaining)
  97. require.Equal(t, int64(0), account.Stats.Emails)
  98. require.Equal(t, int64(24), account.Stats.EmailsRemaining)
  99. rr = request(t, s, "POST", "/mytopic", "", nil)
  100. require.Equal(t, 200, rr.Code)
  101. rr = request(t, s, "POST", "/mytopic", "", map[string]string{
  102. "Email": "phil@ntfy.sh",
  103. })
  104. require.Equal(t, 200, rr.Code)
  105. rr = request(t, s, "GET", "/v1/account", "", nil)
  106. require.Equal(t, 200, rr.Code)
  107. account, _ = util.UnmarshalJSON[apiAccountResponse](io.NopCloser(rr.Body))
  108. require.Equal(t, int64(2), account.Stats.Messages)
  109. require.Equal(t, int64(1002), account.Stats.MessagesRemaining)
  110. require.Equal(t, int64(1), account.Stats.Emails)
  111. require.Equal(t, int64(23), account.Stats.EmailsRemaining)
  112. }
  113. func TestAccount_ChangeSettings(t *testing.T) {
  114. s := newTestServer(t, newTestConfigWithAuthFile(t))
  115. require.Nil(t, s.userManager.AddUser("phil", "phil", user.RoleUser, "unit-test"))
  116. user, _ := s.userManager.User("phil")
  117. token, _ := s.userManager.CreateToken(user)
  118. rr := request(t, s, "PATCH", "/v1/account/settings", `{"notification": {"sound": "juntos"},"ignored": true}`, map[string]string{
  119. "Authorization": util.BasicAuth("phil", "phil"),
  120. })
  121. require.Equal(t, 200, rr.Code)
  122. rr = request(t, s, "PATCH", "/v1/account/settings", `{"notification": {"delete_after": 86400}, "language": "de"}`, map[string]string{
  123. "Authorization": util.BearerAuth(token.Value),
  124. })
  125. require.Equal(t, 200, rr.Code)
  126. rr = request(t, s, "GET", "/v1/account", `{"username":"marian", "password":"marian"}`, map[string]string{
  127. "Authorization": util.BearerAuth(token.Value),
  128. })
  129. require.Equal(t, 200, rr.Code)
  130. account, _ := util.UnmarshalJSON[apiAccountResponse](io.NopCloser(rr.Body))
  131. require.Equal(t, "de", account.Language)
  132. require.Equal(t, 86400, account.Notification.DeleteAfter)
  133. require.Equal(t, "juntos", account.Notification.Sound)
  134. require.Equal(t, 0, account.Notification.MinPriority) // Not set
  135. }
  136. func TestAccount_Subscription_AddUpdateDelete(t *testing.T) {
  137. s := newTestServer(t, newTestConfigWithAuthFile(t))
  138. require.Nil(t, s.userManager.AddUser("phil", "phil", user.RoleUser, "unit-test"))
  139. rr := request(t, s, "POST", "/v1/account/subscription", `{"base_url": "http://abc.com", "topic": "def"}`, map[string]string{
  140. "Authorization": util.BasicAuth("phil", "phil"),
  141. })
  142. require.Equal(t, 200, rr.Code)
  143. rr = request(t, s, "GET", "/v1/account", "", map[string]string{
  144. "Authorization": util.BasicAuth("phil", "phil"),
  145. })
  146. require.Equal(t, 200, rr.Code)
  147. account, _ := util.UnmarshalJSON[apiAccountResponse](io.NopCloser(rr.Body))
  148. require.Equal(t, 1, len(account.Subscriptions))
  149. require.NotEmpty(t, account.Subscriptions[0].ID)
  150. require.Equal(t, "http://abc.com", account.Subscriptions[0].BaseURL)
  151. require.Equal(t, "def", account.Subscriptions[0].Topic)
  152. require.Equal(t, "", account.Subscriptions[0].DisplayName)
  153. subscriptionID := account.Subscriptions[0].ID
  154. rr = request(t, s, "PATCH", "/v1/account/subscription/"+subscriptionID, `{"display_name": "ding dong"}`, map[string]string{
  155. "Authorization": util.BasicAuth("phil", "phil"),
  156. })
  157. require.Equal(t, 200, rr.Code)
  158. rr = request(t, s, "GET", "/v1/account", "", map[string]string{
  159. "Authorization": util.BasicAuth("phil", "phil"),
  160. })
  161. require.Equal(t, 200, rr.Code)
  162. account, _ = util.UnmarshalJSON[apiAccountResponse](io.NopCloser(rr.Body))
  163. require.Equal(t, 1, len(account.Subscriptions))
  164. require.Equal(t, subscriptionID, account.Subscriptions[0].ID)
  165. require.Equal(t, "http://abc.com", account.Subscriptions[0].BaseURL)
  166. require.Equal(t, "def", account.Subscriptions[0].Topic)
  167. require.Equal(t, "ding dong", account.Subscriptions[0].DisplayName)
  168. rr = request(t, s, "DELETE", "/v1/account/subscription/"+subscriptionID, "", map[string]string{
  169. "Authorization": util.BasicAuth("phil", "phil"),
  170. })
  171. require.Equal(t, 200, rr.Code)
  172. rr = request(t, s, "GET", "/v1/account", "", map[string]string{
  173. "Authorization": util.BasicAuth("phil", "phil"),
  174. })
  175. require.Equal(t, 200, rr.Code)
  176. account, _ = util.UnmarshalJSON[apiAccountResponse](io.NopCloser(rr.Body))
  177. require.Equal(t, 0, len(account.Subscriptions))
  178. }
  179. func TestAccount_ChangePassword(t *testing.T) {
  180. s := newTestServer(t, newTestConfigWithAuthFile(t))
  181. require.Nil(t, s.userManager.AddUser("phil", "phil", user.RoleUser, "unit-test"))
  182. rr := request(t, s, "POST", "/v1/account/password", `{"password": "new password"}`, map[string]string{
  183. "Authorization": util.BasicAuth("phil", "phil"),
  184. })
  185. require.Equal(t, 200, rr.Code)
  186. rr = request(t, s, "GET", "/v1/account", "", map[string]string{
  187. "Authorization": util.BasicAuth("phil", "phil"),
  188. })
  189. require.Equal(t, 401, rr.Code)
  190. rr = request(t, s, "GET", "/v1/account", "", map[string]string{
  191. "Authorization": util.BasicAuth("phil", "new password"),
  192. })
  193. require.Equal(t, 200, rr.Code)
  194. }
  195. func TestAccount_ChangePassword_NoAccount(t *testing.T) {
  196. s := newTestServer(t, newTestConfigWithAuthFile(t))
  197. rr := request(t, s, "POST", "/v1/account/password", `{"password": "new password"}`, nil)
  198. require.Equal(t, 401, rr.Code)
  199. }
  200. func TestAccount_ExtendToken(t *testing.T) {
  201. s := newTestServer(t, newTestConfigWithAuthFile(t))
  202. require.Nil(t, s.userManager.AddUser("phil", "phil", user.RoleUser, "unit-test"))
  203. rr := request(t, s, "POST", "/v1/account/token", "", map[string]string{
  204. "Authorization": util.BasicAuth("phil", "phil"),
  205. })
  206. require.Equal(t, 200, rr.Code)
  207. token, err := util.UnmarshalJSON[apiAccountTokenResponse](io.NopCloser(rr.Body))
  208. require.Nil(t, err)
  209. time.Sleep(time.Second)
  210. rr = request(t, s, "PATCH", "/v1/account/token", "", map[string]string{
  211. "Authorization": util.BearerAuth(token.Token),
  212. })
  213. require.Equal(t, 200, rr.Code)
  214. extendedToken, err := util.UnmarshalJSON[apiAccountTokenResponse](io.NopCloser(rr.Body))
  215. require.Nil(t, err)
  216. require.Equal(t, token.Token, extendedToken.Token)
  217. require.True(t, token.Expires < extendedToken.Expires)
  218. }
  219. func TestAccount_ExtendToken_NoTokenProvided(t *testing.T) {
  220. s := newTestServer(t, newTestConfigWithAuthFile(t))
  221. require.Nil(t, s.userManager.AddUser("phil", "phil", user.RoleUser, "unit-test"))
  222. rr := request(t, s, "PATCH", "/v1/account/token", "", map[string]string{
  223. "Authorization": util.BasicAuth("phil", "phil"), // Not Bearer!
  224. })
  225. require.Equal(t, 400, rr.Code)
  226. require.Equal(t, 40023, toHTTPError(t, rr.Body.String()).Code)
  227. }
  228. func TestAccount_DeleteToken(t *testing.T) {
  229. s := newTestServer(t, newTestConfigWithAuthFile(t))
  230. require.Nil(t, s.userManager.AddUser("phil", "phil", user.RoleUser, "unit-test"))
  231. rr := request(t, s, "POST", "/v1/account/token", "", map[string]string{
  232. "Authorization": util.BasicAuth("phil", "phil"),
  233. })
  234. require.Equal(t, 200, rr.Code)
  235. token, err := util.UnmarshalJSON[apiAccountTokenResponse](io.NopCloser(rr.Body))
  236. require.Nil(t, err)
  237. // Delete token failure (using basic auth)
  238. rr = request(t, s, "DELETE", "/v1/account/token", "", map[string]string{
  239. "Authorization": util.BasicAuth("phil", "phil"), // Not Bearer!
  240. })
  241. require.Equal(t, 400, rr.Code)
  242. require.Equal(t, 40023, toHTTPError(t, rr.Body.String()).Code)
  243. // Delete token with wrong token
  244. rr = request(t, s, "DELETE", "/v1/account/token", "", map[string]string{
  245. "Authorization": util.BearerAuth("invalidtoken"),
  246. })
  247. require.Equal(t, 401, rr.Code)
  248. // Delete token with correct token
  249. rr = request(t, s, "DELETE", "/v1/account/token", "", map[string]string{
  250. "Authorization": util.BearerAuth(token.Token),
  251. })
  252. require.Equal(t, 200, rr.Code)
  253. // Cannot get account anymore
  254. rr = request(t, s, "GET", "/v1/account", "", map[string]string{
  255. "Authorization": util.BearerAuth(token.Token),
  256. })
  257. require.Equal(t, 401, rr.Code)
  258. }
  259. func TestAccount_Delete_Success(t *testing.T) {
  260. conf := newTestConfigWithAuthFile(t)
  261. conf.EnableSignup = true
  262. s := newTestServer(t, conf)
  263. rr := request(t, s, "POST", "/v1/account", `{"username":"phil", "password":"mypass"}`, nil)
  264. require.Equal(t, 200, rr.Code)
  265. rr = request(t, s, "GET", "/v1/account", "", map[string]string{
  266. "Authorization": util.BasicAuth("phil", "mypass"),
  267. })
  268. require.Equal(t, 200, rr.Code)
  269. rr = request(t, s, "DELETE", "/v1/account", "", map[string]string{
  270. "Authorization": util.BasicAuth("phil", "mypass"),
  271. })
  272. require.Equal(t, 200, rr.Code)
  273. rr = request(t, s, "GET", "/v1/account", "", map[string]string{
  274. "Authorization": util.BasicAuth("phil", "mypass"),
  275. })
  276. require.Equal(t, 401, rr.Code)
  277. }
  278. func TestAccount_Delete_Not_Allowed(t *testing.T) {
  279. conf := newTestConfigWithAuthFile(t)
  280. conf.EnableSignup = true
  281. s := newTestServer(t, conf)
  282. rr := request(t, s, "POST", "/v1/account", `{"username":"phil", "password":"mypass"}`, nil)
  283. require.Equal(t, 200, rr.Code)
  284. rr = request(t, s, "DELETE", "/v1/account", "", nil)
  285. require.Equal(t, 401, rr.Code)
  286. }
  287. func TestAccount_Reservation_AddWithoutTierFails(t *testing.T) {
  288. conf := newTestConfigWithAuthFile(t)
  289. conf.EnableSignup = true
  290. s := newTestServer(t, conf)
  291. rr := request(t, s, "POST", "/v1/account", `{"username":"phil", "password":"mypass"}`, nil)
  292. require.Equal(t, 200, rr.Code)
  293. rr = request(t, s, "POST", "/v1/account/reservation", `{"topic":"mytopic", "everyone":"deny-all"}`, map[string]string{
  294. "Authorization": util.BasicAuth("phil", "mypass"),
  295. })
  296. require.Equal(t, 401, rr.Code)
  297. }
  298. func TestAccount_Reservation_AddAdminSuccess(t *testing.T) {
  299. conf := newTestConfigWithAuthFile(t)
  300. conf.EnableSignup = true
  301. s := newTestServer(t, conf)
  302. require.Nil(t, s.userManager.AddUser("phil", "adminpass", user.RoleAdmin, "unit-test"))
  303. rr := request(t, s, "POST", "/v1/account/reservation", `{"topic":"mytopic","everyone":"deny-all"}`, map[string]string{
  304. "Authorization": util.BasicAuth("phil", "adminpass"),
  305. })
  306. require.Equal(t, 400, rr.Code)
  307. require.Equal(t, 40026, toHTTPError(t, rr.Body.String()).Code)
  308. }
  309. func TestAccount_Reservation_AddRemoveUserWithTierSuccess(t *testing.T) {
  310. conf := newTestConfigWithAuthFile(t)
  311. conf.EnableSignup = true
  312. s := newTestServer(t, conf)
  313. // Create user
  314. rr := request(t, s, "POST", "/v1/account", `{"username":"phil", "password":"mypass"}`, nil)
  315. require.Equal(t, 200, rr.Code)
  316. // Create a tier
  317. require.Nil(t, s.userManager.CreateTier(&user.Tier{
  318. Code: "pro",
  319. Paid: false,
  320. MessagesLimit: 123,
  321. MessagesExpiryDuration: 86400 * time.Second,
  322. EmailsLimit: 32,
  323. ReservationsLimit: 2,
  324. AttachmentFileSizeLimit: 1231231,
  325. AttachmentTotalSizeLimit: 123123,
  326. AttachmentExpiryDuration: 10800 * time.Second,
  327. }))
  328. require.Nil(t, s.userManager.ChangeTier("phil", "pro"))
  329. // Reserve two topics
  330. rr = request(t, s, "POST", "/v1/account/reservation", `{"topic": "mytopic", "everyone":"deny-all"}`, map[string]string{
  331. "Authorization": util.BasicAuth("phil", "mypass"),
  332. })
  333. require.Equal(t, 200, rr.Code)
  334. rr = request(t, s, "POST", "/v1/account/reservation", `{"topic": "another", "everyone":"read-only"}`, map[string]string{
  335. "Authorization": util.BasicAuth("phil", "mypass"),
  336. })
  337. require.Equal(t, 200, rr.Code)
  338. // Trying to reserve a third should fail
  339. rr = request(t, s, "POST", "/v1/account/reservation", `{"topic": "yet-another", "everyone":"deny-all"}`, map[string]string{
  340. "Authorization": util.BasicAuth("phil", "mypass"),
  341. })
  342. require.Equal(t, 429, rr.Code)
  343. // Modify existing should still work
  344. rr = request(t, s, "POST", "/v1/account/reservation", `{"topic": "another", "everyone":"write-only"}`, map[string]string{
  345. "Authorization": util.BasicAuth("phil", "mypass"),
  346. })
  347. require.Equal(t, 200, rr.Code)
  348. // Check account result
  349. rr = request(t, s, "GET", "/v1/account", "", map[string]string{
  350. "Authorization": util.BasicAuth("phil", "mypass"),
  351. })
  352. require.Equal(t, 200, rr.Code)
  353. account, _ := util.UnmarshalJSON[apiAccountResponse](io.NopCloser(rr.Body))
  354. require.Equal(t, "pro", account.Tier.Code)
  355. require.Equal(t, int64(123), account.Limits.Messages)
  356. require.Equal(t, int64(86400), account.Limits.MessagesExpiryDuration)
  357. require.Equal(t, int64(32), account.Limits.Emails)
  358. require.Equal(t, int64(2), account.Limits.Reservations)
  359. require.Equal(t, int64(1231231), account.Limits.AttachmentFileSize)
  360. require.Equal(t, int64(123123), account.Limits.AttachmentTotalSize)
  361. require.Equal(t, int64(10800), account.Limits.AttachmentExpiryDuration)
  362. require.Equal(t, 2, len(account.Reservations))
  363. require.Equal(t, "another", account.Reservations[0].Topic)
  364. require.Equal(t, "write-only", account.Reservations[0].Everyone)
  365. require.Equal(t, "mytopic", account.Reservations[1].Topic)
  366. require.Equal(t, "deny-all", account.Reservations[1].Everyone)
  367. // Delete and re-check
  368. rr = request(t, s, "DELETE", "/v1/account/reservation/another", "", map[string]string{
  369. "Authorization": util.BasicAuth("phil", "mypass"),
  370. })
  371. require.Equal(t, 200, rr.Code)
  372. rr = request(t, s, "GET", "/v1/account", "", map[string]string{
  373. "Authorization": util.BasicAuth("phil", "mypass"),
  374. })
  375. require.Equal(t, 200, rr.Code)
  376. account, _ = util.UnmarshalJSON[apiAccountResponse](io.NopCloser(rr.Body))
  377. require.Equal(t, 1, len(account.Reservations))
  378. require.Equal(t, "mytopic", account.Reservations[0].Topic)
  379. }
  380. func TestAccount_Reservation_PublishByAnonymousFails(t *testing.T) {
  381. conf := newTestConfigWithAuthFile(t)
  382. conf.AuthDefault = user.PermissionReadWrite
  383. conf.EnableSignup = true
  384. s := newTestServer(t, conf)
  385. // Create user with tier
  386. rr := request(t, s, "POST", "/v1/account", `{"username":"phil", "password":"mypass"}`, nil)
  387. require.Equal(t, 200, rr.Code)
  388. require.Nil(t, s.userManager.CreateTier(&user.Tier{
  389. Code: "pro",
  390. MessagesLimit: 20,
  391. ReservationsLimit: 2,
  392. }))
  393. require.Nil(t, s.userManager.ChangeTier("phil", "pro"))
  394. // Reserve a topic
  395. rr = request(t, s, "POST", "/v1/account/reservation", `{"topic": "mytopic", "everyone":"deny-all"}`, map[string]string{
  396. "Authorization": util.BasicAuth("phil", "mypass"),
  397. })
  398. require.Equal(t, 200, rr.Code)
  399. // Publish a message
  400. rr = request(t, s, "POST", "/mytopic", `Howdy`, map[string]string{
  401. "Authorization": util.BasicAuth("phil", "mypass"),
  402. })
  403. require.Equal(t, 200, rr.Code)
  404. // Publish a message (as anonymous)
  405. rr = request(t, s, "POST", "/mytopic", `Howdy`, nil)
  406. require.Equal(t, 403, rr.Code)
  407. }