@@ -22,6 +22,7 @@ import (
2222"github.com/prometheus/client_golang/prometheus"
2323"github.com/stretchr/testify/assert"
2424"github.com/stretchr/testify/require"
25+ "go.uber.org/atomic"
2526"golang.org/x/oauth2"
2627"golang.org/x/xerrors"
2728
@@ -254,37 +255,64 @@ func TestUserOAuth2Github(t *testing.T) {
254255})
255256t .Run ("BlockSignups" ,func (t * testing.T ) {
256257t .Parallel ()
258+
259+ db ,ps := dbtestutil .NewDB (t )
260+
261+ id := atomic .NewInt64 (100 )
262+ login := atomic .NewString ("testuser" )
263+ email := atomic .NewString ("testuser@coder.com" )
264+
257265client := coderdtest .New (t ,& coderdtest.Options {
266+ Database :db ,
267+ Pubsub :ps ,
258268GithubOAuth2Config :& coderd.GithubOAuth2Config {
259269OAuth2Config :& testutil.OAuth2Config {},
260270AllowOrganizations : []string {"coder" },
261- ListOrganizationMemberships :func (ctx context.Context ,client * http.Client ) ([]* github.Membership ,error ) {
271+ ListOrganizationMemberships :func (_ context.Context ,_ * http.Client ) ([]* github.Membership ,error ) {
262272return []* github.Membership {{
263273State :& stateActive ,
264274Organization :& github.Organization {
265275Login :github .String ("coder" ),
266276},
267277}},nil
268278},
269- AuthenticatedUser :func (ctx context.Context ,client * http.Client ) (* github.User ,error ) {
279+ AuthenticatedUser :func (_ context.Context ,_ * http.Client ) (* github.User ,error ) {
280+ id := id .Load ()
281+ login := login .Load ()
270282return & github.User {
271- ID :github . Int64 ( 100 ) ,
272- Login :github . String ( "testuser" ) ,
283+ ID :& id ,
284+ Login :& login ,
273285Name :github .String ("The Right Honorable Sir Test McUser" ),
274286},nil
275287},
276- ListEmails :func (ctx context.Context ,client * http.Client ) ([]* github.UserEmail ,error ) {
288+ ListEmails :func (_ context.Context ,_ * http.Client ) ([]* github.UserEmail ,error ) {
289+ email := email .Load ()
277290return []* github.UserEmail {{
278- Email :github . String ( "testuser@coder.com" ) ,
291+ Email :& email ,
279292Verified :github .Bool (true ),
280293Primary :github .Bool (true ),
281294}},nil
282295},
283296},
284297})
285298
299+ // The first user in a deployment with signups disabled will be allowed to sign up,
300+ // but all the other users will not.
286301resp := oauth2Callback (t ,client )
302+ require .Equal (t ,http .StatusTemporaryRedirect ,resp .StatusCode )
303+
304+ ctx := testutil .Context (t ,testutil .WaitLong )
305+
306+ // nolint:gocritic // Unit test
307+ count ,err := db .GetUserCount (dbauthz .AsSystemRestricted (ctx ))
308+ require .NoError (t ,err )
309+ require .Equal (t ,int64 (1 ),count )
310+
311+ id .Store (101 )
312+ email .Store ("someotheruser@coder.com" )
313+ login .Store ("someotheruser" )
287314
315+ resp = oauth2Callback (t ,client )
288316require .Equal (t ,http .StatusForbidden ,resp .StatusCode )
289317})
290318t .Run ("MultiLoginNotAllowed" ,func (t * testing.T ) {
@@ -986,6 +1014,7 @@ func TestUserOIDC(t *testing.T) {
9861014AssertResponse func (t testing.TB ,resp * http.Response )
9871015IgnoreEmailVerified bool
9881016IgnoreUserInfo bool
1017+ PrecreateFirstUser bool
9891018}{
9901019{
9911020Name :"NoSub" ,
@@ -1122,7 +1151,17 @@ func TestUserOIDC(t *testing.T) {
11221151"email_verified" :true ,
11231152"sub" :uuid .NewString (),
11241153},
1125- StatusCode :http .StatusForbidden ,
1154+ StatusCode :http .StatusForbidden ,
1155+ PrecreateFirstUser :true ,
1156+ },
1157+ {
1158+ Name :"FirstSignup" ,
1159+ IDTokenClaims : jwt.MapClaims {
1160+ "email" :"kyle@kwc.io" ,
1161+ "email_verified" :true ,
1162+ "sub" :uuid .NewString (),
1163+ },
1164+ StatusCode :http .StatusOK ,
11261165},
11271166{
11281167Name :"UsernameFromEmail" ,
@@ -1401,15 +1440,22 @@ func TestUserOIDC(t *testing.T) {
14011440})
14021441numLogs := len (auditor .AuditLogs ())
14031442
1443+ ctx := testutil .Context (t ,testutil .WaitShort )
1444+ if tc .PrecreateFirstUser {
1445+ owner .CreateFirstUser (ctx , codersdk.CreateFirstUserRequest {
1446+ Email :"precreated@coder.com" ,
1447+ Username :"precreated" ,
1448+ Password :"SomeSecurePassword!" ,
1449+ })
1450+ }
1451+
14041452client ,resp := fake .AttemptLogin (t ,owner ,tc .IDTokenClaims )
14051453numLogs ++ // add an audit log for login
14061454require .Equal (t ,tc .StatusCode ,resp .StatusCode )
14071455if tc .AssertResponse != nil {
14081456tc .AssertResponse (t ,resp )
14091457}
14101458
1411- ctx := testutil .Context (t ,testutil .WaitShort )
1412-
14131459if tc .AssertUser != nil {
14141460user ,err := client .User (ctx ,"me" )
14151461require .NoError (t ,err )