manager_test.go 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023
  1. package user
  2. import (
  3. "database/sql"
  4. "fmt"
  5. "github.com/stretchr/testify/require"
  6. "github.com/stripe/stripe-go/v74"
  7. "golang.org/x/crypto/bcrypt"
  8. "heckel.io/ntfy/util"
  9. "net/netip"
  10. "path/filepath"
  11. "strings"
  12. "testing"
  13. "time"
  14. )
  15. const minBcryptTimingMillis = int64(50) // Ideally should be >100ms, but this should also run on a Raspberry Pi without massive resources
  16. func TestManager_FullScenario_Default_DenyAll(t *testing.T) {
  17. a := newTestManagerFromFile(t, filepath.Join(t.TempDir(), "user.db"), "", PermissionDenyAll, DefaultUserPasswordBcryptCost, DefaultUserStatsQueueWriterInterval)
  18. require.Nil(t, a.AddUser("phil", "phil", RoleAdmin))
  19. require.Nil(t, a.AddUser("ben", "ben", RoleUser))
  20. require.Nil(t, a.AllowAccess("ben", "mytopic", PermissionReadWrite))
  21. require.Nil(t, a.AllowAccess("ben", "readme", PermissionRead))
  22. require.Nil(t, a.AllowAccess("ben", "writeme", PermissionWrite))
  23. require.Nil(t, a.AllowAccess("ben", "everyonewrite", PermissionDenyAll)) // How unfair!
  24. require.Nil(t, a.AllowAccess(Everyone, "announcements", PermissionRead))
  25. require.Nil(t, a.AllowAccess(Everyone, "everyonewrite", PermissionReadWrite))
  26. require.Nil(t, a.AllowAccess(Everyone, "up*", PermissionWrite)) // Everyone can write to /up*
  27. phil, err := a.Authenticate("phil", "phil")
  28. require.Nil(t, err)
  29. require.Equal(t, "phil", phil.Name)
  30. require.True(t, strings.HasPrefix(phil.Hash, "$2a$10$"))
  31. require.Equal(t, RoleAdmin, phil.Role)
  32. philGrants, err := a.Grants("phil")
  33. require.Nil(t, err)
  34. require.Equal(t, []Grant{}, philGrants)
  35. ben, err := a.Authenticate("ben", "ben")
  36. require.Nil(t, err)
  37. require.Equal(t, "ben", ben.Name)
  38. require.True(t, strings.HasPrefix(ben.Hash, "$2a$10$"))
  39. require.Equal(t, RoleUser, ben.Role)
  40. benGrants, err := a.Grants("ben")
  41. require.Nil(t, err)
  42. require.Equal(t, []Grant{
  43. {"mytopic", PermissionReadWrite},
  44. {"writeme", PermissionWrite},
  45. {"readme", PermissionRead},
  46. {"everyonewrite", PermissionDenyAll},
  47. }, benGrants)
  48. notben, err := a.Authenticate("ben", "this is wrong")
  49. require.Nil(t, notben)
  50. require.Equal(t, ErrUnauthenticated, err)
  51. // Admin can do everything
  52. require.Nil(t, a.Authorize(phil, "sometopic", PermissionWrite))
  53. require.Nil(t, a.Authorize(phil, "mytopic", PermissionRead))
  54. require.Nil(t, a.Authorize(phil, "readme", PermissionWrite))
  55. require.Nil(t, a.Authorize(phil, "writeme", PermissionWrite))
  56. require.Nil(t, a.Authorize(phil, "announcements", PermissionWrite))
  57. require.Nil(t, a.Authorize(phil, "everyonewrite", PermissionWrite))
  58. // User cannot do everything
  59. require.Nil(t, a.Authorize(ben, "mytopic", PermissionWrite))
  60. require.Nil(t, a.Authorize(ben, "mytopic", PermissionRead))
  61. require.Nil(t, a.Authorize(ben, "readme", PermissionRead))
  62. require.Equal(t, ErrUnauthorized, a.Authorize(ben, "readme", PermissionWrite))
  63. require.Equal(t, ErrUnauthorized, a.Authorize(ben, "writeme", PermissionRead))
  64. require.Nil(t, a.Authorize(ben, "writeme", PermissionWrite))
  65. require.Nil(t, a.Authorize(ben, "writeme", PermissionWrite))
  66. require.Equal(t, ErrUnauthorized, a.Authorize(ben, "everyonewrite", PermissionRead))
  67. require.Equal(t, ErrUnauthorized, a.Authorize(ben, "everyonewrite", PermissionWrite))
  68. require.Nil(t, a.Authorize(ben, "announcements", PermissionRead))
  69. require.Equal(t, ErrUnauthorized, a.Authorize(ben, "announcements", PermissionWrite))
  70. // Everyone else can do barely anything
  71. require.Equal(t, ErrUnauthorized, a.Authorize(nil, "sometopicnotinthelist", PermissionRead))
  72. require.Equal(t, ErrUnauthorized, a.Authorize(nil, "sometopicnotinthelist", PermissionWrite))
  73. require.Equal(t, ErrUnauthorized, a.Authorize(nil, "mytopic", PermissionRead))
  74. require.Equal(t, ErrUnauthorized, a.Authorize(nil, "mytopic", PermissionWrite))
  75. require.Equal(t, ErrUnauthorized, a.Authorize(nil, "readme", PermissionRead))
  76. require.Equal(t, ErrUnauthorized, a.Authorize(nil, "readme", PermissionWrite))
  77. require.Equal(t, ErrUnauthorized, a.Authorize(nil, "writeme", PermissionRead))
  78. require.Equal(t, ErrUnauthorized, a.Authorize(nil, "writeme", PermissionWrite))
  79. require.Equal(t, ErrUnauthorized, a.Authorize(nil, "announcements", PermissionWrite))
  80. require.Nil(t, a.Authorize(nil, "announcements", PermissionRead))
  81. require.Nil(t, a.Authorize(nil, "everyonewrite", PermissionRead))
  82. require.Nil(t, a.Authorize(nil, "everyonewrite", PermissionWrite))
  83. require.Nil(t, a.Authorize(nil, "up1234", PermissionWrite)) // Wildcard permission
  84. require.Nil(t, a.Authorize(nil, "up5678", PermissionWrite))
  85. }
  86. func TestManager_AddUser_Invalid(t *testing.T) {
  87. a := newTestManager(t, PermissionDenyAll)
  88. require.Equal(t, ErrInvalidArgument, a.AddUser(" invalid ", "pass", RoleAdmin))
  89. require.Equal(t, ErrInvalidArgument, a.AddUser("validuser", "pass", "invalid-role"))
  90. }
  91. func TestManager_AddUser_Timing(t *testing.T) {
  92. a := newTestManagerFromFile(t, filepath.Join(t.TempDir(), "user.db"), "", PermissionDenyAll, DefaultUserPasswordBcryptCost, DefaultUserStatsQueueWriterInterval)
  93. start := time.Now().UnixMilli()
  94. require.Nil(t, a.AddUser("user", "pass", RoleAdmin))
  95. require.GreaterOrEqual(t, time.Now().UnixMilli()-start, minBcryptTimingMillis)
  96. }
  97. func TestManager_AddUser_And_Query(t *testing.T) {
  98. a := newTestManagerFromFile(t, filepath.Join(t.TempDir(), "user.db"), "", PermissionDenyAll, DefaultUserPasswordBcryptCost, DefaultUserStatsQueueWriterInterval)
  99. require.Nil(t, a.AddUser("user", "pass", RoleAdmin))
  100. require.Nil(t, a.ChangeBilling("user", &Billing{
  101. StripeCustomerID: "acct_123",
  102. StripeSubscriptionID: "sub_123",
  103. StripeSubscriptionStatus: stripe.SubscriptionStatusActive,
  104. StripeSubscriptionInterval: stripe.PriceRecurringIntervalMonth,
  105. StripeSubscriptionPaidUntil: time.Now().Add(time.Hour),
  106. StripeSubscriptionCancelAt: time.Unix(0, 0),
  107. }))
  108. u, err := a.User("user")
  109. require.Nil(t, err)
  110. require.Equal(t, "user", u.Name)
  111. u2, err := a.UserByID(u.ID)
  112. require.Nil(t, err)
  113. require.Equal(t, u.Name, u2.Name)
  114. u3, err := a.UserByStripeCustomer("acct_123")
  115. require.Nil(t, err)
  116. require.Equal(t, u.ID, u3.ID)
  117. }
  118. func TestManager_Authenticate_Timing(t *testing.T) {
  119. a := newTestManagerFromFile(t, filepath.Join(t.TempDir(), "user.db"), "", PermissionDenyAll, DefaultUserPasswordBcryptCost, DefaultUserStatsQueueWriterInterval)
  120. require.Nil(t, a.AddUser("user", "pass", RoleAdmin))
  121. // Timing a correct attempt
  122. start := time.Now().UnixMilli()
  123. _, err := a.Authenticate("user", "pass")
  124. require.Nil(t, err)
  125. require.GreaterOrEqual(t, time.Now().UnixMilli()-start, minBcryptTimingMillis)
  126. // Timing an incorrect attempt
  127. start = time.Now().UnixMilli()
  128. _, err = a.Authenticate("user", "INCORRECT")
  129. require.Equal(t, ErrUnauthenticated, err)
  130. require.GreaterOrEqual(t, time.Now().UnixMilli()-start, minBcryptTimingMillis)
  131. // Timing a non-existing user attempt
  132. start = time.Now().UnixMilli()
  133. _, err = a.Authenticate("DOES-NOT-EXIST", "hithere")
  134. require.Equal(t, ErrUnauthenticated, err)
  135. require.GreaterOrEqual(t, time.Now().UnixMilli()-start, minBcryptTimingMillis)
  136. }
  137. func TestManager_MarkUserRemoved_RemoveDeletedUsers(t *testing.T) {
  138. a := newTestManager(t, PermissionDenyAll)
  139. // Create user, add reservations and token
  140. require.Nil(t, a.AddUser("user", "pass", RoleAdmin))
  141. require.Nil(t, a.AddReservation("user", "mytopic", PermissionRead))
  142. u, err := a.User("user")
  143. require.Nil(t, err)
  144. require.False(t, u.Deleted)
  145. token, err := a.CreateToken(u.ID, "", time.Now().Add(time.Hour), netip.IPv4Unspecified())
  146. require.Nil(t, err)
  147. u, err = a.Authenticate("user", "pass")
  148. require.Nil(t, err)
  149. _, err = a.AuthenticateToken(token.Value)
  150. require.Nil(t, err)
  151. reservations, err := a.Reservations("user")
  152. require.Nil(t, err)
  153. require.Equal(t, 1, len(reservations))
  154. // Mark deleted: cannot auth anymore, and all reservations are gone
  155. require.Nil(t, a.MarkUserRemoved(u))
  156. _, err = a.Authenticate("user", "pass")
  157. require.Equal(t, ErrUnauthenticated, err)
  158. _, err = a.AuthenticateToken(token.Value)
  159. require.Equal(t, ErrUnauthenticated, err)
  160. reservations, err = a.Reservations("user")
  161. require.Nil(t, err)
  162. require.Equal(t, 0, len(reservations))
  163. // Make sure user is still there
  164. u, err = a.User("user")
  165. require.Nil(t, err)
  166. require.True(t, u.Deleted)
  167. _, err = a.db.Exec("UPDATE user SET deleted = ? WHERE id = ?", time.Now().Add(-1*(userHardDeleteAfterDuration+time.Hour)).Unix(), u.ID)
  168. require.Nil(t, err)
  169. require.Nil(t, a.RemoveDeletedUsers())
  170. _, err = a.User("user")
  171. require.Equal(t, ErrUserNotFound, err)
  172. }
  173. func TestManager_UserManagement(t *testing.T) {
  174. a := newTestManager(t, PermissionDenyAll)
  175. require.Nil(t, a.AddUser("phil", "phil", RoleAdmin))
  176. require.Nil(t, a.AddUser("ben", "ben", RoleUser))
  177. require.Nil(t, a.AllowAccess("ben", "mytopic", PermissionReadWrite))
  178. require.Nil(t, a.AllowAccess("ben", "readme", PermissionRead))
  179. require.Nil(t, a.AllowAccess("ben", "writeme", PermissionWrite))
  180. require.Nil(t, a.AllowAccess("ben", "everyonewrite", PermissionDenyAll)) // How unfair!
  181. require.Nil(t, a.AllowAccess(Everyone, "announcements", PermissionRead))
  182. require.Nil(t, a.AllowAccess(Everyone, "everyonewrite", PermissionReadWrite))
  183. // Query user details
  184. phil, err := a.User("phil")
  185. require.Nil(t, err)
  186. require.Equal(t, "phil", phil.Name)
  187. require.True(t, strings.HasPrefix(phil.Hash, "$2a$04$")) // Min cost for testing
  188. require.Equal(t, RoleAdmin, phil.Role)
  189. philGrants, err := a.Grants("phil")
  190. require.Nil(t, err)
  191. require.Equal(t, []Grant{}, philGrants)
  192. ben, err := a.User("ben")
  193. require.Nil(t, err)
  194. require.Equal(t, "ben", ben.Name)
  195. require.True(t, strings.HasPrefix(ben.Hash, "$2a$04$")) // Min cost for testing
  196. require.Equal(t, RoleUser, ben.Role)
  197. benGrants, err := a.Grants("ben")
  198. require.Nil(t, err)
  199. require.Equal(t, []Grant{
  200. {"mytopic", PermissionReadWrite},
  201. {"writeme", PermissionWrite},
  202. {"readme", PermissionRead},
  203. {"everyonewrite", PermissionDenyAll},
  204. }, benGrants)
  205. everyone, err := a.User(Everyone)
  206. require.Nil(t, err)
  207. require.Equal(t, "*", everyone.Name)
  208. require.Equal(t, "", everyone.Hash)
  209. require.Equal(t, RoleAnonymous, everyone.Role)
  210. everyoneGrants, err := a.Grants(Everyone)
  211. require.Nil(t, err)
  212. require.Equal(t, []Grant{
  213. {"everyonewrite", PermissionReadWrite},
  214. {"announcements", PermissionRead},
  215. }, everyoneGrants)
  216. // Ben: Before revoking
  217. require.Nil(t, a.AllowAccess("ben", "mytopic", PermissionReadWrite)) // Overwrite!
  218. require.Nil(t, a.AllowAccess("ben", "readme", PermissionRead))
  219. require.Nil(t, a.AllowAccess("ben", "writeme", PermissionWrite))
  220. require.Nil(t, a.Authorize(ben, "mytopic", PermissionRead))
  221. require.Nil(t, a.Authorize(ben, "mytopic", PermissionWrite))
  222. require.Nil(t, a.Authorize(ben, "readme", PermissionRead))
  223. require.Nil(t, a.Authorize(ben, "writeme", PermissionWrite))
  224. // Revoke access for "ben" to "mytopic", then check again
  225. require.Nil(t, a.ResetAccess("ben", "mytopic"))
  226. require.Equal(t, ErrUnauthorized, a.Authorize(ben, "mytopic", PermissionWrite)) // Revoked
  227. require.Equal(t, ErrUnauthorized, a.Authorize(ben, "mytopic", PermissionRead)) // Revoked
  228. require.Nil(t, a.Authorize(ben, "readme", PermissionRead)) // Unchanged
  229. require.Nil(t, a.Authorize(ben, "writeme", PermissionWrite)) // Unchanged
  230. // Revoke rest of the access
  231. require.Nil(t, a.ResetAccess("ben", ""))
  232. require.Equal(t, ErrUnauthorized, a.Authorize(ben, "readme", PermissionRead)) // Revoked
  233. require.Equal(t, ErrUnauthorized, a.Authorize(ben, "wrtiteme", PermissionWrite)) // Revoked
  234. // User list
  235. users, err := a.Users()
  236. require.Nil(t, err)
  237. require.Equal(t, 3, len(users))
  238. require.Equal(t, "phil", users[0].Name)
  239. require.Equal(t, "ben", users[1].Name)
  240. require.Equal(t, "*", users[2].Name)
  241. // Remove user
  242. require.Nil(t, a.RemoveUser("ben"))
  243. _, err = a.User("ben")
  244. require.Equal(t, ErrUserNotFound, err)
  245. users, err = a.Users()
  246. require.Nil(t, err)
  247. require.Equal(t, 2, len(users))
  248. require.Equal(t, "phil", users[0].Name)
  249. require.Equal(t, "*", users[1].Name)
  250. }
  251. func TestManager_ChangePassword(t *testing.T) {
  252. a := newTestManager(t, PermissionDenyAll)
  253. require.Nil(t, a.AddUser("phil", "phil", RoleAdmin))
  254. _, err := a.Authenticate("phil", "phil")
  255. require.Nil(t, err)
  256. require.Nil(t, a.ChangePassword("phil", "newpass"))
  257. _, err = a.Authenticate("phil", "phil")
  258. require.Equal(t, ErrUnauthenticated, err)
  259. _, err = a.Authenticate("phil", "newpass")
  260. require.Nil(t, err)
  261. }
  262. func TestManager_ChangeRole(t *testing.T) {
  263. a := newTestManager(t, PermissionDenyAll)
  264. require.Nil(t, a.AddUser("ben", "ben", RoleUser))
  265. require.Nil(t, a.AllowAccess("ben", "mytopic", PermissionReadWrite))
  266. require.Nil(t, a.AllowAccess("ben", "readme", PermissionRead))
  267. ben, err := a.User("ben")
  268. require.Nil(t, err)
  269. require.Equal(t, RoleUser, ben.Role)
  270. benGrants, err := a.Grants("ben")
  271. require.Nil(t, err)
  272. require.Equal(t, 2, len(benGrants))
  273. require.Nil(t, a.ChangeRole("ben", RoleAdmin))
  274. ben, err = a.User("ben")
  275. require.Nil(t, err)
  276. require.Equal(t, RoleAdmin, ben.Role)
  277. benGrants, err = a.Grants("ben")
  278. require.Nil(t, err)
  279. require.Equal(t, 0, len(benGrants))
  280. }
  281. func TestManager_Reservations(t *testing.T) {
  282. a := newTestManager(t, PermissionDenyAll)
  283. require.Nil(t, a.AddUser("phil", "phil", RoleUser))
  284. require.Nil(t, a.AddUser("ben", "ben", RoleUser))
  285. require.Nil(t, a.AddReservation("ben", "ztopic", PermissionDenyAll))
  286. require.Nil(t, a.AddReservation("ben", "readme", PermissionRead))
  287. require.Nil(t, a.AllowAccess("ben", "something-else", PermissionRead))
  288. reservations, err := a.Reservations("ben")
  289. require.Nil(t, err)
  290. require.Equal(t, 2, len(reservations))
  291. require.Equal(t, Reservation{
  292. Topic: "readme",
  293. Owner: PermissionReadWrite,
  294. Everyone: PermissionRead,
  295. }, reservations[0])
  296. require.Equal(t, Reservation{
  297. Topic: "ztopic",
  298. Owner: PermissionReadWrite,
  299. Everyone: PermissionDenyAll,
  300. }, reservations[1])
  301. b, err := a.HasReservation("ben", "readme")
  302. require.Nil(t, err)
  303. require.True(t, b)
  304. b, err = a.HasReservation("notben", "readme")
  305. require.Nil(t, err)
  306. require.False(t, b)
  307. b, err = a.HasReservation("ben", "something-else")
  308. require.Nil(t, err)
  309. require.False(t, b)
  310. count, err := a.ReservationsCount("ben")
  311. require.Nil(t, err)
  312. require.Equal(t, int64(2), count)
  313. count, err = a.ReservationsCount("phil")
  314. require.Nil(t, err)
  315. require.Equal(t, int64(0), count)
  316. err = a.AllowReservation("phil", "readme")
  317. require.Equal(t, errTopicOwnedByOthers, err)
  318. err = a.AllowReservation("phil", "not-reserved")
  319. require.Nil(t, err)
  320. // Now remove them again
  321. require.Nil(t, a.RemoveReservations("ben", "ztopic", "readme"))
  322. count, err = a.ReservationsCount("ben")
  323. require.Nil(t, err)
  324. require.Equal(t, int64(0), count)
  325. }
  326. func TestManager_ChangeRoleFromTierUserToAdmin(t *testing.T) {
  327. a := newTestManager(t, PermissionDenyAll)
  328. require.Nil(t, a.AddTier(&Tier{
  329. Code: "pro",
  330. Name: "ntfy Pro",
  331. StripeMonthlyPriceID: "price123",
  332. MessageLimit: 5_000,
  333. MessageExpiryDuration: 3 * 24 * time.Hour,
  334. EmailLimit: 50,
  335. ReservationLimit: 5,
  336. AttachmentFileSizeLimit: 52428800,
  337. AttachmentTotalSizeLimit: 524288000,
  338. AttachmentExpiryDuration: 24 * time.Hour,
  339. }))
  340. require.Nil(t, a.AddUser("ben", "ben", RoleUser))
  341. require.Nil(t, a.ChangeTier("ben", "pro"))
  342. require.Nil(t, a.AddReservation("ben", "mytopic", PermissionDenyAll))
  343. ben, err := a.User("ben")
  344. require.Nil(t, err)
  345. require.Equal(t, RoleUser, ben.Role)
  346. require.Equal(t, "pro", ben.Tier.Code)
  347. require.Equal(t, int64(5000), ben.Tier.MessageLimit)
  348. require.Equal(t, 3*24*time.Hour, ben.Tier.MessageExpiryDuration)
  349. require.Equal(t, int64(50), ben.Tier.EmailLimit)
  350. require.Equal(t, int64(5), ben.Tier.ReservationLimit)
  351. require.Equal(t, int64(52428800), ben.Tier.AttachmentFileSizeLimit)
  352. require.Equal(t, int64(524288000), ben.Tier.AttachmentTotalSizeLimit)
  353. require.Equal(t, 24*time.Hour, ben.Tier.AttachmentExpiryDuration)
  354. benGrants, err := a.Grants("ben")
  355. require.Nil(t, err)
  356. require.Equal(t, 1, len(benGrants))
  357. require.Equal(t, PermissionReadWrite, benGrants[0].Allow)
  358. everyoneGrants, err := a.Grants(Everyone)
  359. require.Nil(t, err)
  360. require.Equal(t, 1, len(everyoneGrants))
  361. require.Equal(t, PermissionDenyAll, everyoneGrants[0].Allow)
  362. benReservations, err := a.Reservations("ben")
  363. require.Nil(t, err)
  364. require.Equal(t, 1, len(benReservations))
  365. require.Equal(t, "mytopic", benReservations[0].Topic)
  366. require.Equal(t, PermissionReadWrite, benReservations[0].Owner)
  367. require.Equal(t, PermissionDenyAll, benReservations[0].Everyone)
  368. // Switch to admin, this should remove all grants and owned ACL entries
  369. require.Nil(t, a.ChangeRole("ben", RoleAdmin))
  370. benGrants, err = a.Grants("ben")
  371. require.Nil(t, err)
  372. require.Equal(t, 0, len(benGrants))
  373. everyoneGrants, err = a.Grants(Everyone)
  374. require.Nil(t, err)
  375. require.Equal(t, 0, len(everyoneGrants))
  376. }
  377. func TestManager_Token_Valid(t *testing.T) {
  378. a := newTestManager(t, PermissionDenyAll)
  379. require.Nil(t, a.AddUser("ben", "ben", RoleUser))
  380. u, err := a.User("ben")
  381. require.Nil(t, err)
  382. // Create token for user
  383. token, err := a.CreateToken(u.ID, "some label", time.Now().Add(72*time.Hour), netip.IPv4Unspecified())
  384. require.Nil(t, err)
  385. require.NotEmpty(t, token.Value)
  386. require.Equal(t, "some label", token.Label)
  387. require.True(t, time.Now().Add(71*time.Hour).Unix() < token.Expires.Unix())
  388. u2, err := a.AuthenticateToken(token.Value)
  389. require.Nil(t, err)
  390. require.Equal(t, u.Name, u2.Name)
  391. require.Equal(t, token.Value, u2.Token)
  392. token2, err := a.Token(u.ID, token.Value)
  393. require.Nil(t, err)
  394. require.Equal(t, token.Value, token2.Value)
  395. require.Equal(t, "some label", token2.Label)
  396. tokens, err := a.Tokens(u.ID)
  397. require.Nil(t, err)
  398. require.Equal(t, 1, len(tokens))
  399. require.Equal(t, "some label", tokens[0].Label)
  400. tokens, err = a.Tokens("u_notauser")
  401. require.Nil(t, err)
  402. require.Equal(t, 0, len(tokens))
  403. // Remove token and auth again
  404. require.Nil(t, a.RemoveToken(u2.ID, u2.Token))
  405. u3, err := a.AuthenticateToken(token.Value)
  406. require.Equal(t, ErrUnauthenticated, err)
  407. require.Nil(t, u3)
  408. tokens, err = a.Tokens(u.ID)
  409. require.Nil(t, err)
  410. require.Equal(t, 0, len(tokens))
  411. }
  412. func TestManager_Token_Invalid(t *testing.T) {
  413. a := newTestManager(t, PermissionDenyAll)
  414. require.Nil(t, a.AddUser("ben", "ben", RoleUser))
  415. u, err := a.AuthenticateToken(strings.Repeat("x", 32)) // 32 == token length
  416. require.Nil(t, u)
  417. require.Equal(t, ErrUnauthenticated, err)
  418. u, err = a.AuthenticateToken("not long enough anyway")
  419. require.Nil(t, u)
  420. require.Equal(t, ErrUnauthenticated, err)
  421. }
  422. func TestManager_Token_NotFound(t *testing.T) {
  423. a := newTestManager(t, PermissionDenyAll)
  424. _, err := a.Token("u_bla", "notfound")
  425. require.Equal(t, ErrTokenNotFound, err)
  426. }
  427. func TestManager_Token_Expire(t *testing.T) {
  428. a := newTestManager(t, PermissionDenyAll)
  429. require.Nil(t, a.AddUser("ben", "ben", RoleUser))
  430. u, err := a.User("ben")
  431. require.Nil(t, err)
  432. // Create tokens for user
  433. token1, err := a.CreateToken(u.ID, "", time.Now().Add(72*time.Hour), netip.IPv4Unspecified())
  434. require.Nil(t, err)
  435. require.NotEmpty(t, token1.Value)
  436. require.True(t, time.Now().Add(71*time.Hour).Unix() < token1.Expires.Unix())
  437. token2, err := a.CreateToken(u.ID, "", time.Now().Add(72*time.Hour), netip.IPv4Unspecified())
  438. require.Nil(t, err)
  439. require.NotEmpty(t, token2.Value)
  440. require.NotEqual(t, token1.Value, token2.Value)
  441. require.True(t, time.Now().Add(71*time.Hour).Unix() < token2.Expires.Unix())
  442. // See that tokens work
  443. _, err = a.AuthenticateToken(token1.Value)
  444. require.Nil(t, err)
  445. _, err = a.AuthenticateToken(token2.Value)
  446. require.Nil(t, err)
  447. // Modify token expiration in database
  448. _, err = a.db.Exec("UPDATE user_token SET expires = 1 WHERE token = ?", token1.Value)
  449. require.Nil(t, err)
  450. // Now token1 shouldn't work anymore
  451. _, err = a.AuthenticateToken(token1.Value)
  452. require.Equal(t, ErrUnauthenticated, err)
  453. result, err := a.db.Query("SELECT * from user_token WHERE token = ?", token1.Value)
  454. require.Nil(t, err)
  455. require.True(t, result.Next()) // Still a matching row
  456. require.Nil(t, result.Close())
  457. // Expire tokens and check database rows
  458. require.Nil(t, a.RemoveExpiredTokens())
  459. result, err = a.db.Query("SELECT * from user_token WHERE token = ?", token1.Value)
  460. require.Nil(t, err)
  461. require.False(t, result.Next()) // No matching row!
  462. require.Nil(t, result.Close())
  463. }
  464. func TestManager_Token_Extend(t *testing.T) {
  465. a := newTestManager(t, PermissionDenyAll)
  466. require.Nil(t, a.AddUser("ben", "ben", RoleUser))
  467. // Try to extend token for user without token
  468. u, err := a.User("ben")
  469. require.Nil(t, err)
  470. _, err = a.ChangeToken(u.ID, u.Token, util.String("some label"), util.Time(time.Now().Add(time.Hour)))
  471. require.Equal(t, errNoTokenProvided, err)
  472. // Create token for user
  473. token, err := a.CreateToken(u.ID, "", time.Now().Add(72*time.Hour), netip.IPv4Unspecified())
  474. require.Nil(t, err)
  475. require.NotEmpty(t, token.Value)
  476. userWithToken, err := a.AuthenticateToken(token.Value)
  477. require.Nil(t, err)
  478. extendedToken, err := a.ChangeToken(userWithToken.ID, userWithToken.Token, util.String("changed label"), util.Time(time.Now().Add(100*time.Hour)))
  479. require.Nil(t, err)
  480. require.Equal(t, token.Value, extendedToken.Value)
  481. require.Equal(t, "changed label", extendedToken.Label)
  482. require.True(t, token.Expires.Unix() < extendedToken.Expires.Unix())
  483. require.True(t, time.Now().Add(99*time.Hour).Unix() < extendedToken.Expires.Unix())
  484. }
  485. func TestManager_Token_MaxCount_AutoDelete(t *testing.T) {
  486. a := newTestManager(t, PermissionDenyAll)
  487. require.Nil(t, a.AddUser("ben", "ben", RoleUser))
  488. // Try to extend token for user without token
  489. u, err := a.User("ben")
  490. require.Nil(t, err)
  491. // Tokens
  492. baseTime := time.Now().Add(24 * time.Hour)
  493. tokens := make([]string, 0)
  494. for i := 0; i < 22; i++ {
  495. token, err := a.CreateToken(u.ID, "", time.Now().Add(72*time.Hour), netip.IPv4Unspecified())
  496. require.Nil(t, err)
  497. require.NotEmpty(t, token.Value)
  498. tokens = append(tokens, token.Value)
  499. // Manually modify expiry date to avoid sorting issues (this is a hack)
  500. _, err = a.db.Exec(`UPDATE user_token SET expires=? WHERE token=?`, baseTime.Add(time.Duration(i)*time.Minute).Unix(), token.Value)
  501. require.Nil(t, err)
  502. }
  503. _, err = a.AuthenticateToken(tokens[0])
  504. require.Equal(t, ErrUnauthenticated, err)
  505. _, err = a.AuthenticateToken(tokens[1])
  506. require.Equal(t, ErrUnauthenticated, err)
  507. for i := 2; i < 22; i++ {
  508. userWithToken, err := a.AuthenticateToken(tokens[i])
  509. require.Nil(t, err, "token[%d]=%s failed", i, tokens[i])
  510. require.Equal(t, "ben", userWithToken.Name)
  511. require.Equal(t, tokens[i], userWithToken.Token)
  512. }
  513. var count int
  514. rows, err := a.db.Query(`SELECT COUNT(*) FROM user_token`)
  515. require.Nil(t, err)
  516. require.True(t, rows.Next())
  517. require.Nil(t, rows.Scan(&count))
  518. require.Equal(t, 20, count)
  519. }
  520. func TestManager_EnqueueStats_ResetStats(t *testing.T) {
  521. a, err := NewManager(filepath.Join(t.TempDir(), "db"), "", PermissionReadWrite, bcrypt.MinCost, 1500*time.Millisecond)
  522. require.Nil(t, err)
  523. require.Nil(t, a.AddUser("ben", "ben", RoleUser))
  524. // Baseline: No messages or emails
  525. u, err := a.User("ben")
  526. require.Nil(t, err)
  527. require.Equal(t, int64(0), u.Stats.Messages)
  528. require.Equal(t, int64(0), u.Stats.Emails)
  529. a.EnqueueUserStats(u.ID, &Stats{
  530. Messages: 11,
  531. Emails: 2,
  532. })
  533. // Still no change, because it's queued asynchronously
  534. u, err = a.User("ben")
  535. require.Nil(t, err)
  536. require.Equal(t, int64(0), u.Stats.Messages)
  537. require.Equal(t, int64(0), u.Stats.Emails)
  538. // After 2 seconds they should be persisted
  539. time.Sleep(2 * time.Second)
  540. u, err = a.User("ben")
  541. require.Nil(t, err)
  542. require.Equal(t, int64(11), u.Stats.Messages)
  543. require.Equal(t, int64(2), u.Stats.Emails)
  544. // Now reset stats (enqueued stats will be thrown out)
  545. a.EnqueueUserStats(u.ID, &Stats{
  546. Messages: 99,
  547. Emails: 23,
  548. })
  549. require.Nil(t, a.ResetStats())
  550. u, err = a.User("ben")
  551. require.Nil(t, err)
  552. require.Equal(t, int64(0), u.Stats.Messages)
  553. require.Equal(t, int64(0), u.Stats.Emails)
  554. }
  555. func TestManager_EnqueueTokenUpdate(t *testing.T) {
  556. a, err := NewManager(filepath.Join(t.TempDir(), "db"), "", PermissionReadWrite, bcrypt.MinCost, 500*time.Millisecond)
  557. require.Nil(t, err)
  558. require.Nil(t, a.AddUser("ben", "ben", RoleUser))
  559. // Create user and token
  560. u, err := a.User("ben")
  561. require.Nil(t, err)
  562. token, err := a.CreateToken(u.ID, "", time.Now().Add(time.Hour), netip.IPv4Unspecified())
  563. require.Nil(t, err)
  564. // Queue token update
  565. a.EnqueueTokenUpdate(token.Value, &TokenUpdate{
  566. LastAccess: time.Unix(111, 0).UTC(),
  567. LastOrigin: netip.MustParseAddr("1.2.3.3"),
  568. })
  569. // Token has not changed yet.
  570. token2, err := a.Token(u.ID, token.Value)
  571. require.Nil(t, err)
  572. require.Equal(t, token.LastAccess.Unix(), token2.LastAccess.Unix())
  573. require.Equal(t, token.LastOrigin, token2.LastOrigin)
  574. // After a second or so they should be persisted
  575. time.Sleep(time.Second)
  576. token3, err := a.Token(u.ID, token.Value)
  577. require.Nil(t, err)
  578. require.Equal(t, time.Unix(111, 0).UTC().Unix(), token3.LastAccess.Unix())
  579. require.Equal(t, netip.MustParseAddr("1.2.3.3"), token3.LastOrigin)
  580. }
  581. func TestManager_ChangeSettings(t *testing.T) {
  582. a, err := NewManager(filepath.Join(t.TempDir(), "db"), "", PermissionReadWrite, bcrypt.MinCost, 1500*time.Millisecond)
  583. require.Nil(t, err)
  584. require.Nil(t, a.AddUser("ben", "ben", RoleUser))
  585. // No settings
  586. u, err := a.User("ben")
  587. require.Nil(t, err)
  588. require.Nil(t, u.Prefs.Subscriptions)
  589. require.Nil(t, u.Prefs.Notification)
  590. require.Nil(t, u.Prefs.Language)
  591. // Save with new settings
  592. prefs := &Prefs{
  593. Language: util.String("de"),
  594. Notification: &NotificationPrefs{
  595. Sound: util.String("ding"),
  596. MinPriority: util.Int(2),
  597. },
  598. Subscriptions: []*Subscription{
  599. {
  600. BaseURL: "https://ntfy.sh",
  601. Topic: "mytopic",
  602. DisplayName: util.String("My Topic"),
  603. },
  604. },
  605. }
  606. require.Nil(t, a.ChangeSettings(u.ID, prefs))
  607. // Read again
  608. u, err = a.User("ben")
  609. require.Nil(t, err)
  610. require.Equal(t, util.String("de"), u.Prefs.Language)
  611. require.Equal(t, util.String("ding"), u.Prefs.Notification.Sound)
  612. require.Equal(t, util.Int(2), u.Prefs.Notification.MinPriority)
  613. require.Nil(t, u.Prefs.Notification.DeleteAfter)
  614. require.Equal(t, "https://ntfy.sh", u.Prefs.Subscriptions[0].BaseURL)
  615. require.Equal(t, "mytopic", u.Prefs.Subscriptions[0].Topic)
  616. require.Equal(t, util.String("My Topic"), u.Prefs.Subscriptions[0].DisplayName)
  617. }
  618. func TestManager_Tier_Create_Update_List_Delete(t *testing.T) {
  619. a := newTestManager(t, PermissionDenyAll)
  620. // Create tier and user
  621. require.Nil(t, a.AddTier(&Tier{
  622. Code: "supporter",
  623. Name: "Supporter",
  624. MessageLimit: 1,
  625. MessageExpiryDuration: time.Second,
  626. EmailLimit: 1,
  627. ReservationLimit: 1,
  628. AttachmentFileSizeLimit: 1,
  629. AttachmentTotalSizeLimit: 1,
  630. AttachmentExpiryDuration: time.Second,
  631. AttachmentBandwidthLimit: 1,
  632. StripeMonthlyPriceID: "price_1",
  633. }))
  634. require.Nil(t, a.AddTier(&Tier{
  635. Code: "pro",
  636. Name: "Pro",
  637. MessageLimit: 123,
  638. MessageExpiryDuration: 86400 * time.Second,
  639. EmailLimit: 32,
  640. ReservationLimit: 2,
  641. AttachmentFileSizeLimit: 1231231,
  642. AttachmentTotalSizeLimit: 123123,
  643. AttachmentExpiryDuration: 10800 * time.Second,
  644. AttachmentBandwidthLimit: 21474836480,
  645. StripeMonthlyPriceID: "price_2",
  646. }))
  647. require.Nil(t, a.AddUser("phil", "phil", RoleUser))
  648. require.Nil(t, a.ChangeTier("phil", "pro"))
  649. ti, err := a.Tier("pro")
  650. require.Nil(t, err)
  651. u, err := a.User("phil")
  652. require.Nil(t, err)
  653. // These are populated by different SQL queries
  654. require.Equal(t, ti, u.Tier)
  655. // Fields
  656. require.True(t, strings.HasPrefix(ti.ID, "ti_"))
  657. require.Equal(t, "pro", ti.Code)
  658. require.Equal(t, "Pro", ti.Name)
  659. require.Equal(t, int64(123), ti.MessageLimit)
  660. require.Equal(t, 86400*time.Second, ti.MessageExpiryDuration)
  661. require.Equal(t, int64(32), ti.EmailLimit)
  662. require.Equal(t, int64(2), ti.ReservationLimit)
  663. require.Equal(t, int64(1231231), ti.AttachmentFileSizeLimit)
  664. require.Equal(t, int64(123123), ti.AttachmentTotalSizeLimit)
  665. require.Equal(t, 10800*time.Second, ti.AttachmentExpiryDuration)
  666. require.Equal(t, int64(21474836480), ti.AttachmentBandwidthLimit)
  667. require.Equal(t, "price_2", ti.StripeMonthlyPriceID)
  668. // Update tier
  669. ti.EmailLimit = 999999
  670. require.Nil(t, a.UpdateTier(ti))
  671. // List tiers
  672. tiers, err := a.Tiers()
  673. require.Nil(t, err)
  674. require.Equal(t, 2, len(tiers))
  675. ti = tiers[0]
  676. require.Equal(t, "supporter", ti.Code)
  677. require.Equal(t, "Supporter", ti.Name)
  678. require.Equal(t, int64(1), ti.MessageLimit)
  679. require.Equal(t, time.Second, ti.MessageExpiryDuration)
  680. require.Equal(t, int64(1), ti.EmailLimit)
  681. require.Equal(t, int64(1), ti.ReservationLimit)
  682. require.Equal(t, int64(1), ti.AttachmentFileSizeLimit)
  683. require.Equal(t, int64(1), ti.AttachmentTotalSizeLimit)
  684. require.Equal(t, time.Second, ti.AttachmentExpiryDuration)
  685. require.Equal(t, int64(1), ti.AttachmentBandwidthLimit)
  686. require.Equal(t, "price_1", ti.StripeMonthlyPriceID)
  687. ti = tiers[1]
  688. require.Equal(t, "pro", ti.Code)
  689. require.Equal(t, "Pro", ti.Name)
  690. require.Equal(t, int64(123), ti.MessageLimit)
  691. require.Equal(t, 86400*time.Second, ti.MessageExpiryDuration)
  692. require.Equal(t, int64(999999), ti.EmailLimit) // Updatedd!
  693. require.Equal(t, int64(2), ti.ReservationLimit)
  694. require.Equal(t, int64(1231231), ti.AttachmentFileSizeLimit)
  695. require.Equal(t, int64(123123), ti.AttachmentTotalSizeLimit)
  696. require.Equal(t, 10800*time.Second, ti.AttachmentExpiryDuration)
  697. require.Equal(t, int64(21474836480), ti.AttachmentBandwidthLimit)
  698. require.Equal(t, "price_2", ti.StripeMonthlyPriceID)
  699. ti, err = a.TierByStripePrice("price_1")
  700. require.Nil(t, err)
  701. require.Equal(t, "supporter", ti.Code)
  702. require.Equal(t, "Supporter", ti.Name)
  703. require.Equal(t, int64(1), ti.MessageLimit)
  704. require.Equal(t, time.Second, ti.MessageExpiryDuration)
  705. require.Equal(t, int64(1), ti.EmailLimit)
  706. require.Equal(t, int64(1), ti.ReservationLimit)
  707. require.Equal(t, int64(1), ti.AttachmentFileSizeLimit)
  708. require.Equal(t, int64(1), ti.AttachmentTotalSizeLimit)
  709. require.Equal(t, time.Second, ti.AttachmentExpiryDuration)
  710. require.Equal(t, int64(1), ti.AttachmentBandwidthLimit)
  711. require.Equal(t, "price_1", ti.StripeMonthlyPriceID)
  712. // Cannot remove tier, since user has this tier
  713. require.Error(t, a.RemoveTier("pro"))
  714. // CAN remove this tier
  715. require.Nil(t, a.RemoveTier("supporter"))
  716. tiers, err = a.Tiers()
  717. require.Nil(t, err)
  718. require.Equal(t, 1, len(tiers))
  719. require.Equal(t, "pro", tiers[0].Code)
  720. require.Equal(t, "pro", tiers[0].Code)
  721. }
  722. func TestAccount_Tier_Create_With_ID(t *testing.T) {
  723. a := newTestManager(t, PermissionDenyAll)
  724. require.Nil(t, a.AddTier(&Tier{
  725. ID: "ti_123",
  726. Code: "pro",
  727. }))
  728. ti, err := a.Tier("pro")
  729. require.Nil(t, err)
  730. require.Equal(t, "ti_123", ti.ID)
  731. }
  732. func TestManager_Tier_Change_And_Reset(t *testing.T) {
  733. a := newTestManager(t, PermissionDenyAll)
  734. // Create tier and user
  735. require.Nil(t, a.AddTier(&Tier{
  736. Code: "supporter",
  737. Name: "Supporter",
  738. ReservationLimit: 3,
  739. }))
  740. require.Nil(t, a.AddTier(&Tier{
  741. Code: "pro",
  742. Name: "Pro",
  743. ReservationLimit: 4,
  744. }))
  745. require.Nil(t, a.AddUser("phil", "phil", RoleUser))
  746. require.Nil(t, a.ChangeTier("phil", "pro"))
  747. // Add 10 reservations (pro tier allows that)
  748. for i := 0; i < 4; i++ {
  749. require.Nil(t, a.AddReservation("phil", fmt.Sprintf("topic%d", i), PermissionWrite))
  750. }
  751. // Downgrading will not work (too many reservations)
  752. require.Equal(t, ErrTooManyReservations, a.ChangeTier("phil", "supporter"))
  753. // Downgrade after removing a reservation
  754. require.Nil(t, a.RemoveReservations("phil", "topic0"))
  755. require.Nil(t, a.ChangeTier("phil", "supporter"))
  756. // Resetting will not work (too many reservations)
  757. require.Equal(t, ErrTooManyReservations, a.ResetTier("phil"))
  758. // Resetting after removing all reservations
  759. require.Nil(t, a.RemoveReservations("phil", "topic1", "topic2", "topic3"))
  760. require.Nil(t, a.ResetTier("phil"))
  761. }
  762. func TestSqliteCache_Migration_From1(t *testing.T) {
  763. filename := filepath.Join(t.TempDir(), "user.db")
  764. db, err := sql.Open("sqlite3", filename)
  765. require.Nil(t, err)
  766. // Create "version 1" schema
  767. _, err = db.Exec(`
  768. BEGIN;
  769. CREATE TABLE IF NOT EXISTS user (
  770. user TEXT NOT NULL PRIMARY KEY,
  771. pass TEXT NOT NULL,
  772. role TEXT NOT NULL
  773. );
  774. CREATE TABLE IF NOT EXISTS access (
  775. user TEXT NOT NULL,
  776. topic TEXT NOT NULL,
  777. read INT NOT NULL,
  778. write INT NOT NULL,
  779. PRIMARY KEY (topic, user)
  780. );
  781. CREATE TABLE IF NOT EXISTS schemaVersion (
  782. id INT PRIMARY KEY,
  783. version INT NOT NULL
  784. );
  785. INSERT INTO schemaVersion (id, version) VALUES (1, 1);
  786. COMMIT;
  787. `)
  788. require.Nil(t, err)
  789. // Insert a bunch of users and ACL entries
  790. _, err = db.Exec(`
  791. BEGIN;
  792. INSERT INTO user (user, pass, role) VALUES ('ben', '$2a$10$EEp6gBheOsqEFsXlo523E.gBVoeg1ytphXiEvTPlNzkenBlHZBPQy', 'user');
  793. INSERT INTO user (user, pass, role) VALUES ('phil', '$2a$10$YLiO8U21sX1uhZamTLJXHuxgVC0Z/GKISibrKCLohPgtG7yIxSk4C', 'admin');
  794. INSERT INTO access (user, topic, read, write) VALUES ('ben', 'stats', 1, 1);
  795. INSERT INTO access (user, topic, read, write) VALUES ('ben', 'secret', 1, 0);
  796. INSERT INTO access (user, topic, read, write) VALUES ('*', 'stats', 1, 0);
  797. COMMIT;
  798. `)
  799. require.Nil(t, err)
  800. // Create manager to trigger migration
  801. a := newTestManagerFromFile(t, filename, "", PermissionDenyAll, bcrypt.MinCost, DefaultUserStatsQueueWriterInterval)
  802. checkSchemaVersion(t, a.db)
  803. users, err := a.Users()
  804. require.Nil(t, err)
  805. require.Equal(t, 3, len(users))
  806. phil, ben, everyone := users[0], users[1], users[2]
  807. philGrants, err := a.Grants("phil")
  808. require.Nil(t, err)
  809. benGrants, err := a.Grants("ben")
  810. require.Nil(t, err)
  811. everyoneGrants, err := a.Grants(Everyone)
  812. require.Nil(t, err)
  813. require.True(t, strings.HasPrefix(phil.ID, "u_"))
  814. require.Equal(t, "phil", phil.Name)
  815. require.Equal(t, RoleAdmin, phil.Role)
  816. require.Equal(t, syncTopicLength, len(phil.SyncTopic))
  817. require.Equal(t, 0, len(philGrants))
  818. require.True(t, strings.HasPrefix(ben.ID, "u_"))
  819. require.NotEqual(t, phil.ID, ben.ID)
  820. require.Equal(t, "ben", ben.Name)
  821. require.Equal(t, RoleUser, ben.Role)
  822. require.Equal(t, syncTopicLength, len(ben.SyncTopic))
  823. require.NotEqual(t, ben.SyncTopic, phil.SyncTopic)
  824. require.Equal(t, 2, len(benGrants))
  825. require.Equal(t, "stats", benGrants[0].TopicPattern)
  826. require.Equal(t, PermissionReadWrite, benGrants[0].Allow)
  827. require.Equal(t, "secret", benGrants[1].TopicPattern)
  828. require.Equal(t, PermissionRead, benGrants[1].Allow)
  829. require.Equal(t, "u_everyone", everyone.ID)
  830. require.Equal(t, Everyone, everyone.Name)
  831. require.Equal(t, RoleAnonymous, everyone.Role)
  832. require.Equal(t, 1, len(everyoneGrants))
  833. require.Equal(t, "stats", everyoneGrants[0].TopicPattern)
  834. require.Equal(t, PermissionRead, everyoneGrants[0].Allow)
  835. }
  836. func checkSchemaVersion(t *testing.T, db *sql.DB) {
  837. rows, err := db.Query(`SELECT version FROM schemaVersion`)
  838. require.Nil(t, err)
  839. require.True(t, rows.Next())
  840. var schemaVersion int
  841. require.Nil(t, rows.Scan(&schemaVersion))
  842. require.Equal(t, currentSchemaVersion, schemaVersion)
  843. require.Nil(t, rows.Close())
  844. }
  845. func newTestManager(t *testing.T, defaultAccess Permission) *Manager {
  846. return newTestManagerFromFile(t, filepath.Join(t.TempDir(), "user.db"), "", defaultAccess, bcrypt.MinCost, DefaultUserStatsQueueWriterInterval)
  847. }
  848. func newTestManagerFromFile(t *testing.T, filename, startupQueries string, defaultAccess Permission, bcryptCost int, statsWriterInterval time.Duration) *Manager {
  849. a, err := NewManager(filename, startupQueries, defaultAccess, bcryptCost, statsWriterInterval)
  850. require.Nil(t, err)
  851. return a
  852. }