@@ -26,9 +26,11 @@ import (
2626"github.com/coder/coder/v2/coderd/audit"
2727"github.com/coder/coder/v2/coderd/coderdtest"
2828"github.com/coder/coder/v2/coderd/database"
29+ "github.com/coder/coder/v2/coderd/database/db2sdk"
2930"github.com/coder/coder/v2/coderd/database/dbauthz"
3031"github.com/coder/coder/v2/coderd/database/dbfake"
3132"github.com/coder/coder/v2/coderd/database/dbgen"
33+ "github.com/coder/coder/v2/coderd/database/dbtestutil"
3234"github.com/coder/coder/v2/coderd/database/dbtime"
3335"github.com/coder/coder/v2/coderd/rbac"
3436"github.com/coder/coder/v2/coderd/util/ptr"
@@ -1515,6 +1517,73 @@ func TestUsersFilter(t *testing.T) {
15151517users = append (users ,user )
15161518}
15171519
1520+ // Add users with different creation dates for testing date filters
1521+ for i := 0 ;i < 3 ;i ++ {
1522+ // nolint:gocritic // Using system context is necessary to seed data in tests
1523+ user1 ,err := api .Database .InsertUser (dbauthz .AsSystemRestricted (ctx ), database.InsertUserParams {
1524+ ID :uuid .New (),
1525+ Email :fmt .Sprintf ("before%d@coder.com" ,i ),
1526+ Username :fmt .Sprintf ("before%d" ,i ),
1527+ LoginType :database .LoginTypeNone ,
1528+ Status :string (codersdk .UserStatusActive ),
1529+ RBACRoles : []string {codersdk .RoleMember },
1530+ CreatedAt :dbtime .Time (time .Date (2022 ,12 ,15 + i ,12 ,0 ,0 ,0 ,time .UTC )),
1531+ })
1532+ require .NoError (t ,err )
1533+
1534+ // The expected timestamps must be parsed from strings to compare equal during `ElementsMatch`
1535+ sdkUser1 := db2sdk .User (user1 ,nil )
1536+ sdkUser1 .CreatedAt ,err = time .Parse (time .RFC3339 ,sdkUser1 .CreatedAt .Format (time .RFC3339 ))
1537+ require .NoError (t ,err )
1538+ sdkUser1 .UpdatedAt ,err = time .Parse (time .RFC3339 ,sdkUser1 .UpdatedAt .Format (time .RFC3339 ))
1539+ require .NoError (t ,err )
1540+ sdkUser1 .LastSeenAt ,err = time .Parse (time .RFC3339 ,sdkUser1 .LastSeenAt .Format (time .RFC3339 ))
1541+ require .NoError (t ,err )
1542+ users = append (users ,sdkUser1 )
1543+
1544+ // nolint:gocritic //Using system context is necessary to seed data in tests
1545+ user2 ,err := api .Database .InsertUser (dbauthz .AsSystemRestricted (ctx ), database.InsertUserParams {
1546+ ID :uuid .New (),
1547+ Email :fmt .Sprintf ("during%d@coder.com" ,i ),
1548+ Username :fmt .Sprintf ("during%d" ,i ),
1549+ LoginType :database .LoginTypeNone ,
1550+ Status :string (codersdk .UserStatusActive ),
1551+ RBACRoles : []string {codersdk .RoleOwner },
1552+ CreatedAt :dbtime .Time (time .Date (2023 ,1 ,15 + i ,12 ,0 ,0 ,0 ,time .UTC )),
1553+ })
1554+ require .NoError (t ,err )
1555+
1556+ sdkUser2 := db2sdk .User (user2 ,nil )
1557+ sdkUser2 .CreatedAt ,err = time .Parse (time .RFC3339 ,sdkUser2 .CreatedAt .Format (time .RFC3339 ))
1558+ require .NoError (t ,err )
1559+ sdkUser2 .UpdatedAt ,err = time .Parse (time .RFC3339 ,sdkUser2 .UpdatedAt .Format (time .RFC3339 ))
1560+ require .NoError (t ,err )
1561+ sdkUser2 .LastSeenAt ,err = time .Parse (time .RFC3339 ,sdkUser2 .LastSeenAt .Format (time .RFC3339 ))
1562+ require .NoError (t ,err )
1563+ users = append (users ,sdkUser2 )
1564+
1565+ // nolint:gocritic // Using system context is necessary to seed data in tests
1566+ user3 ,err := api .Database .InsertUser (dbauthz .AsSystemRestricted (ctx ), database.InsertUserParams {
1567+ ID :uuid .New (),
1568+ Email :fmt .Sprintf ("after%d@coder.com" ,i ),
1569+ Username :fmt .Sprintf ("after%d" ,i ),
1570+ LoginType :database .LoginTypeNone ,
1571+ Status :string (codersdk .UserStatusActive ),
1572+ RBACRoles : []string {codersdk .RoleOwner },
1573+ CreatedAt :dbtime .Time (time .Date (2023 ,2 ,15 + i ,12 ,0 ,0 ,0 ,time .UTC )),
1574+ })
1575+ require .NoError (t ,err )
1576+
1577+ sdkUser3 := db2sdk .User (user3 ,nil )
1578+ sdkUser3 .CreatedAt ,err = time .Parse (time .RFC3339 ,sdkUser3 .CreatedAt .Format (time .RFC3339 ))
1579+ require .NoError (t ,err )
1580+ sdkUser3 .UpdatedAt ,err = time .Parse (time .RFC3339 ,sdkUser3 .UpdatedAt .Format (time .RFC3339 ))
1581+ require .NoError (t ,err )
1582+ sdkUser3 .LastSeenAt ,err = time .Parse (time .RFC3339 ,sdkUser3 .LastSeenAt .Format (time .RFC3339 ))
1583+ require .NoError (t ,err )
1584+ users = append (users ,sdkUser3 )
1585+ }
1586+
15181587// --- Setup done ---
15191588testCases := []struct {
15201589Name string
@@ -1657,6 +1726,37 @@ func TestUsersFilter(t *testing.T) {
16571726return u .LastSeenAt .Before (end )&& u .LastSeenAt .After (start )
16581727},
16591728},
1729+ {
1730+ Name :"CreatedAtBefore" ,
1731+ Filter : codersdk.UsersRequest {
1732+ SearchQuery :`created_before:"2023-01-31T23:59:59Z"` ,
1733+ },
1734+ FilterF :func (_ codersdk.UsersRequest ,u codersdk.User )bool {
1735+ end := time .Date (2023 ,1 ,31 ,23 ,59 ,59 ,0 ,time .UTC )
1736+ return u .CreatedAt .Before (end )
1737+ },
1738+ },
1739+ {
1740+ Name :"CreatedAtAfter" ,
1741+ Filter : codersdk.UsersRequest {
1742+ SearchQuery :`created_after:"2023-01-01T00:00:00Z"` ,
1743+ },
1744+ FilterF :func (_ codersdk.UsersRequest ,u codersdk.User )bool {
1745+ start := time .Date (2023 ,1 ,1 ,0 ,0 ,0 ,0 ,time .UTC )
1746+ return u .CreatedAt .After (start )
1747+ },
1748+ },
1749+ {
1750+ Name :"CreatedAtRange" ,
1751+ Filter : codersdk.UsersRequest {
1752+ SearchQuery :`created_after:"2023-01-01T00:00:00Z" created_before:"2023-01-31T23:59:59Z"` ,
1753+ },
1754+ FilterF :func (_ codersdk.UsersRequest ,u codersdk.User )bool {
1755+ start := time .Date (2023 ,1 ,1 ,0 ,0 ,0 ,0 ,time .UTC )
1756+ end := time .Date (2023 ,1 ,31 ,23 ,59 ,59 ,0 ,time .UTC )
1757+ return u .CreatedAt .After (start )&& u .CreatedAt .Before (end )
1758+ },
1759+ },
16601760}
16611761
16621762for _ ,c := range testCases {
@@ -1677,6 +1777,16 @@ func TestUsersFilter(t *testing.T) {
16771777exp = append (exp ,made )
16781778}
16791779}
1780+
1781+ // TODO: This can be removed with dbmem
1782+ if ! dbtestutil .WillUsePostgres () {
1783+ for i := range matched .Users {
1784+ if len (matched .Users [i ].OrganizationIDs )== 0 {
1785+ matched .Users [i ].OrganizationIDs = nil
1786+ }
1787+ }
1788+ }
1789+
16801790require .ElementsMatch (t ,exp ,matched .Users ,"expected users returned" )
16811791})
16821792}