manager_test.go 36 KB

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