mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
fix: Suspended users cannot authenticate (#1849)
* fix: Suspended users cannot authenticate - Merge roles and apikey extract httpmw - Add member account to make dev - feat: UI Shows suspended error logging into suspended account - change 'active' route to 'activate'
This commit is contained in:
+21
-1
@@ -175,7 +175,27 @@ func ExtractAPIKey(db database.Store, oauth *OAuth2Configs) func(http.Handler) h
|
||||
}
|
||||
}
|
||||
|
||||
ctx := context.WithValue(r.Context(), apiKeyContextKey{}, key)
|
||||
// If the key is valid, we also fetch the user roles and status.
|
||||
// The roles are used for RBAC authorize checks, and the status
|
||||
// is to block 'suspended' users from accessing the platform.
|
||||
roles, err := db.GetAllUserRoles(r.Context(), key.UserID)
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusUnauthorized, httpapi.Response{
|
||||
Message: "roles not found",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if roles.Status != database.UserStatusActive {
|
||||
httpapi.Write(rw, http.StatusUnauthorized, httpapi.Response{
|
||||
Message: fmt.Sprintf("user is not active (status = %q), contact an admin to reactivate your account", roles.Status),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
ctx := r.Context()
|
||||
ctx = context.WithValue(ctx, apiKeyContextKey{}, key)
|
||||
ctx = context.WithValue(ctx, userRolesKey{}, roles)
|
||||
next.ServeHTTP(rw, r.WithContext(ctx))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/stretchr/testify/require"
|
||||
"golang.org/x/oauth2"
|
||||
|
||||
@@ -128,6 +129,7 @@ func TestAPIKey(t *testing.T) {
|
||||
id, secret = randomAPIKeyParts()
|
||||
r = httptest.NewRequest("GET", "/", nil)
|
||||
rw = httptest.NewRecorder()
|
||||
user = createUser(r.Context(), t, db)
|
||||
)
|
||||
r.AddCookie(&http.Cookie{
|
||||
Name: httpmw.SessionTokenKey,
|
||||
@@ -139,6 +141,7 @@ func TestAPIKey(t *testing.T) {
|
||||
_, err := db.InsertAPIKey(r.Context(), database.InsertAPIKeyParams{
|
||||
ID: id,
|
||||
HashedSecret: hashed[:],
|
||||
UserID: user.ID,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
httpmw.ExtractAPIKey(db, nil)(successHandler).ServeHTTP(rw, r)
|
||||
@@ -155,6 +158,7 @@ func TestAPIKey(t *testing.T) {
|
||||
hashed = sha256.Sum256([]byte(secret))
|
||||
r = httptest.NewRequest("GET", "/", nil)
|
||||
rw = httptest.NewRecorder()
|
||||
user = createUser(r.Context(), t, db)
|
||||
)
|
||||
r.AddCookie(&http.Cookie{
|
||||
Name: httpmw.SessionTokenKey,
|
||||
@@ -164,6 +168,7 @@ func TestAPIKey(t *testing.T) {
|
||||
_, err := db.InsertAPIKey(r.Context(), database.InsertAPIKeyParams{
|
||||
ID: id,
|
||||
HashedSecret: hashed[:],
|
||||
UserID: user.ID,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
httpmw.ExtractAPIKey(db, nil)(successHandler).ServeHTTP(rw, r)
|
||||
@@ -180,6 +185,7 @@ func TestAPIKey(t *testing.T) {
|
||||
hashed = sha256.Sum256([]byte(secret))
|
||||
r = httptest.NewRequest("GET", "/", nil)
|
||||
rw = httptest.NewRecorder()
|
||||
user = createUser(r.Context(), t, db)
|
||||
)
|
||||
r.AddCookie(&http.Cookie{
|
||||
Name: httpmw.SessionTokenKey,
|
||||
@@ -190,6 +196,7 @@ func TestAPIKey(t *testing.T) {
|
||||
ID: id,
|
||||
HashedSecret: hashed[:],
|
||||
ExpiresAt: database.Now().AddDate(0, 0, 1),
|
||||
UserID: user.ID,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
httpmw.ExtractAPIKey(db, nil)(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
||||
@@ -217,6 +224,7 @@ func TestAPIKey(t *testing.T) {
|
||||
hashed = sha256.Sum256([]byte(secret))
|
||||
r = httptest.NewRequest("GET", "/", nil)
|
||||
rw = httptest.NewRecorder()
|
||||
user = createUser(r.Context(), t, db)
|
||||
)
|
||||
q := r.URL.Query()
|
||||
q.Add(httpmw.SessionTokenKey, fmt.Sprintf("%s-%s", id, secret))
|
||||
@@ -226,6 +234,7 @@ func TestAPIKey(t *testing.T) {
|
||||
ID: id,
|
||||
HashedSecret: hashed[:],
|
||||
ExpiresAt: database.Now().AddDate(0, 0, 1),
|
||||
UserID: user.ID,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
httpmw.ExtractAPIKey(db, nil)(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
||||
@@ -248,6 +257,7 @@ func TestAPIKey(t *testing.T) {
|
||||
hashed = sha256.Sum256([]byte(secret))
|
||||
r = httptest.NewRequest("GET", "/", nil)
|
||||
rw = httptest.NewRecorder()
|
||||
user = createUser(r.Context(), t, db)
|
||||
)
|
||||
r.AddCookie(&http.Cookie{
|
||||
Name: httpmw.SessionTokenKey,
|
||||
@@ -259,6 +269,7 @@ func TestAPIKey(t *testing.T) {
|
||||
HashedSecret: hashed[:],
|
||||
LastUsed: database.Now().AddDate(0, 0, -1),
|
||||
ExpiresAt: database.Now().AddDate(0, 0, 1),
|
||||
UserID: user.ID,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
httpmw.ExtractAPIKey(db, nil)(successHandler).ServeHTTP(rw, r)
|
||||
@@ -281,6 +292,7 @@ func TestAPIKey(t *testing.T) {
|
||||
hashed = sha256.Sum256([]byte(secret))
|
||||
r = httptest.NewRequest("GET", "/", nil)
|
||||
rw = httptest.NewRecorder()
|
||||
user = createUser(r.Context(), t, db)
|
||||
)
|
||||
r.AddCookie(&http.Cookie{
|
||||
Name: httpmw.SessionTokenKey,
|
||||
@@ -292,6 +304,7 @@ func TestAPIKey(t *testing.T) {
|
||||
HashedSecret: hashed[:],
|
||||
LastUsed: database.Now(),
|
||||
ExpiresAt: database.Now().Add(time.Minute),
|
||||
UserID: user.ID,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
httpmw.ExtractAPIKey(db, nil)(successHandler).ServeHTTP(rw, r)
|
||||
@@ -314,6 +327,7 @@ func TestAPIKey(t *testing.T) {
|
||||
hashed = sha256.Sum256([]byte(secret))
|
||||
r = httptest.NewRequest("GET", "/", nil)
|
||||
rw = httptest.NewRecorder()
|
||||
user = createUser(r.Context(), t, db)
|
||||
)
|
||||
r.AddCookie(&http.Cookie{
|
||||
Name: httpmw.SessionTokenKey,
|
||||
@@ -326,6 +340,7 @@ func TestAPIKey(t *testing.T) {
|
||||
LoginType: database.LoginTypeGithub,
|
||||
LastUsed: database.Now(),
|
||||
ExpiresAt: database.Now().AddDate(0, 0, 1),
|
||||
UserID: user.ID,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
httpmw.ExtractAPIKey(db, nil)(successHandler).ServeHTTP(rw, r)
|
||||
@@ -348,6 +363,7 @@ func TestAPIKey(t *testing.T) {
|
||||
hashed = sha256.Sum256([]byte(secret))
|
||||
r = httptest.NewRequest("GET", "/", nil)
|
||||
rw = httptest.NewRecorder()
|
||||
user = createUser(r.Context(), t, db)
|
||||
)
|
||||
r.AddCookie(&http.Cookie{
|
||||
Name: httpmw.SessionTokenKey,
|
||||
@@ -360,6 +376,7 @@ func TestAPIKey(t *testing.T) {
|
||||
LoginType: database.LoginTypeGithub,
|
||||
LastUsed: database.Now(),
|
||||
OAuthExpiry: database.Now().AddDate(0, 0, -1),
|
||||
UserID: user.ID,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
token := &oauth2.Token{
|
||||
@@ -387,6 +404,20 @@ func TestAPIKey(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func createUser(ctx context.Context, t *testing.T, db database.Store) database.User {
|
||||
user, err := db.InsertUser(ctx, database.InsertUserParams{
|
||||
ID: uuid.New(),
|
||||
Email: "email@coder.com",
|
||||
Username: "username",
|
||||
HashedPassword: []byte{},
|
||||
CreatedAt: time.Now(),
|
||||
UpdatedAt: time.Now(),
|
||||
RBACRoles: []string{},
|
||||
})
|
||||
require.NoError(t, err, "create user")
|
||||
return user
|
||||
}
|
||||
|
||||
type oauth2Config struct {
|
||||
tokenSource oauth2TokenSource
|
||||
}
|
||||
|
||||
@@ -84,7 +84,6 @@ func TestExtractUserRoles(t *testing.T) {
|
||||
)
|
||||
rtr.Use(
|
||||
httpmw.ExtractAPIKey(db, &httpmw.OAuth2Configs{}),
|
||||
httpmw.ExtractUserRoles(db),
|
||||
)
|
||||
rtr.Get("/", func(_ http.ResponseWriter, r *http.Request) {
|
||||
roles := httpmw.UserRoles(r)
|
||||
|
||||
Reference in New Issue
Block a user