@@ -1658,7 +1658,16 @@ func TestOIDCSkipIssuer(t *testing.T) {
1658
1658
func TestUserForgotPassword (t * testing.T ) {
1659
1659
t .Parallel ()
1660
1660
1661
- t .Run ("Can change their password" ,func (t * testing.T ) {
1661
+ verifyOneTimePasscodeNotification := func (t * testing.T ,notif * testutil.Notification ,userID uuid.UUID ) {
1662
+ require .Equal (t ,notifications .TemplateUserRequestedOneTimePasscode ,notif .TemplateID )
1663
+ require .Equal (t ,userID ,notif .UserID )
1664
+ require .Equal (t ,1 ,len (notif .Targets ))
1665
+ require .Equal (t ,userID ,notif .Targets [0 ])
1666
+ }
1667
+
1668
+ t .Run ("CanChangeTheirPassword" ,func (t * testing.T ) {
1669
+ const newPassword = "SomeNewSecurePassword!"
1670
+
1662
1671
t .Parallel ()
1663
1672
1664
1673
notifyEnq := & testutil.FakeNotificationsEnqueuer {}
@@ -1681,19 +1690,124 @@ func TestUserForgotPassword(t *testing.T) {
1681
1690
require .Equal (t ,2 ,len (notifyEnq .Sent ))
1682
1691
1683
1692
notif := notifyEnq .Sent [1 ]
1684
- require .Equal (t ,notifications .TemplateUserRequestedOneTimePasscode ,notif .TemplateID )
1685
- require .Equal (t ,anotherUser .ID ,notif .UserID )
1686
- require .Equal (t ,1 ,len (notif .Targets ))
1687
- require .Equal (t ,anotherUser .ID ,notif .Targets [0 ])
1693
+ verifyOneTimePasscodeNotification (t ,notif ,anotherUser .ID )
1688
1694
1689
1695
oneTimePasscode := notif .Labels ["one_time_passcode" ]
1690
1696
1691
1697
err = anotherClient .ChangePasswordWithOneTimePasscode (ctx , codersdk.ChangePasswordWithOneTimePasscodeRequest {
1692
1698
Email :anotherUser .Email ,
1693
1699
OneTimePasscode :oneTimePasscode ,
1700
+ Password :newPassword ,
1701
+ })
1702
+ require .NoError (t ,err )
1703
+
1704
+ _ ,err = anotherClient .LoginWithPassword (ctx , codersdk.LoginWithPasswordRequest {
1705
+ Email :anotherUser .Email ,
1706
+ Password :newPassword ,
1707
+ })
1708
+ require .NoError (t ,err )
1709
+ })
1710
+
1711
+ t .Run ("CannotChangePasswordWithInvalidOneTimePasscode" ,func (t * testing.T ) {
1712
+ t .Parallel ()
1713
+
1714
+ notifyEnq := & testutil.FakeNotificationsEnqueuer {}
1715
+
1716
+ client := coderdtest .New (t ,& coderdtest.Options {
1717
+ NotificationsEnqueuer :notifyEnq ,
1718
+ })
1719
+ user := coderdtest .CreateFirstUser (t ,client )
1720
+
1721
+ ctx ,cancel := context .WithTimeout (context .Background (),testutil .WaitLong )
1722
+ defer cancel ()
1723
+
1724
+ anotherClient ,anotherUser := coderdtest .CreateAnotherUser (t ,client ,user .OrganizationID )
1725
+
1726
+ err := anotherClient .RequestOneTimePasscode (ctx , codersdk.RequestOneTimePasscodeRequest {
1727
+ Email :anotherUser .Email ,
1728
+ })
1729
+ require .NoError (t ,err )
1730
+
1731
+ require .Equal (t ,2 ,len (notifyEnq .Sent ))
1732
+
1733
+ notif := notifyEnq .Sent [1 ]
1734
+ verifyOneTimePasscodeNotification (t ,notif ,anotherUser .ID )
1735
+
1736
+ err = anotherClient .ChangePasswordWithOneTimePasscode (ctx , codersdk.ChangePasswordWithOneTimePasscodeRequest {
1737
+ Email :anotherUser .Email ,
1738
+ OneTimePasscode :uuid .New ().String (),// Use a different UUID to the one expected
1694
1739
Password :"SomeNewSecurePassword!" ,
1695
1740
})
1741
+ require .Error (t ,err )
1742
+
1743
+ var apiErr * codersdk.Error
1744
+ require .ErrorAs (t ,err ,& apiErr )
1745
+ require .Equal (t ,http .StatusBadRequest ,apiErr .StatusCode ())
1746
+ })
1747
+
1748
+ t .Run ("CannotChangePasswordWithWeakPassword" ,func (t * testing.T ) {
1749
+ t .Parallel ()
1750
+
1751
+ notifyEnq := & testutil.FakeNotificationsEnqueuer {}
1752
+
1753
+ client := coderdtest .New (t ,& coderdtest.Options {
1754
+ NotificationsEnqueuer :notifyEnq ,
1755
+ })
1756
+ user := coderdtest .CreateFirstUser (t ,client )
1757
+
1758
+ ctx ,cancel := context .WithTimeout (context .Background (),testutil .WaitLong )
1759
+ defer cancel ()
1760
+
1761
+ anotherClient ,anotherUser := coderdtest .CreateAnotherUser (t ,client ,user .OrganizationID )
1762
+
1763
+ err := anotherClient .RequestOneTimePasscode (ctx , codersdk.RequestOneTimePasscodeRequest {
1764
+ Email :anotherUser .Email ,
1765
+ })
1696
1766
require .NoError (t ,err )
1767
+
1768
+ require .Equal (t ,2 ,len (notifyEnq .Sent ))
1769
+
1770
+ notif := notifyEnq .Sent [1 ]
1771
+ verifyOneTimePasscodeNotification (t ,notif ,anotherUser .ID )
1772
+
1773
+ oneTimePasscode := notif .Labels ["one_time_passcode" ]
1774
+
1775
+ err = anotherClient .ChangePasswordWithOneTimePasscode (ctx , codersdk.ChangePasswordWithOneTimePasscodeRequest {
1776
+ Email :anotherUser .Email ,
1777
+ OneTimePasscode :oneTimePasscode ,
1778
+ Password :"notstrong" ,
1779
+ })
1780
+ require .Error (t ,err )
1781
+
1782
+ var apiErr * codersdk.Error
1783
+ require .ErrorAs (t ,err ,& apiErr )
1784
+ require .Equal (t ,http .StatusBadRequest ,apiErr .StatusCode ())
1785
+ })
1786
+
1787
+ t .Run ("NoNotificationIsSentIfEmailInvalid" ,func (t * testing.T ) {
1788
+ t .Parallel ()
1789
+
1790
+ notifyEnq := & testutil.FakeNotificationsEnqueuer {}
1791
+
1792
+ client := coderdtest .New (t ,& coderdtest.Options {
1793
+ NotificationsEnqueuer :notifyEnq ,
1794
+ })
1795
+ user := coderdtest .CreateFirstUser (t ,client )
1796
+
1797
+ ctx ,cancel := context .WithTimeout (context .Background (),testutil .WaitLong )
1798
+ defer cancel ()
1799
+
1800
+ anotherClient ,_ := coderdtest .CreateAnotherUser (t ,client ,user .OrganizationID )
1801
+
1802
+ err := anotherClient .RequestOneTimePasscode (ctx , codersdk.RequestOneTimePasscodeRequest {
1803
+ Email :"not-a-valid-email@coder.com" ,
1804
+ })
1805
+ require .NoError (t ,err )
1806
+
1807
+ require .Equal (t ,1 ,len (notifyEnq .Sent ))
1808
+
1809
+ notif := notifyEnq .Sent [0 ]
1810
+ require .NotEqual (t ,notifications .TemplateUserRequestedOneTimePasscode ,notif .TemplateID )
1697
1811
})
1698
1812
}
1699
1813