users: add OAUTH_DEFAULT_USER_ROLE and make USER_EMAIL user admin (#2516)

This commit is contained in:
Sven van Ginkel
2026-10-13 08:37:04 -04:00
committed by GitHub
parent 1da59e3771
commit 13ea8106eb
3 changed files with 46 additions and 5 deletions
+2 -1
View File
@@ -44,13 +44,14 @@ func init() {
superUser.SetRandomPassword()
}
// if user details are provided, we create a regular user as well
// if user details are provided, we create an admin user as well
if didProvideUserDetails {
usersCollection, _ := app.FindCollectionByNameOrId("users")
user := core.NewRecord(usersCollection)
user.SetEmail(email)
user.SetPassword(password)
user.SetVerified(true)
user.Set("role", "admin")
err := app.Save(user)
if err != nil {
return err
+33 -3
View File
@@ -33,8 +33,22 @@ func TestOAuthUserRole(t *testing.T) {
auth.Providers[provider] = func() auth.Provider { return &roleTestProvider{} }
t.Cleanup(func() { delete(auth.Providers, provider) })
for _, createData := range []string{`{}`, `{"role":"admin"}`, `{"role":"readonly"}`} {
t.Run(createData, func(t *testing.T) {
for _, tc := range []struct {
createData, defaultRole, want string
}{
{`{}`, "", "user"},
{`{"role":"admin"}`, "", "user"},
{`{"role":"readonly"}`, "", "user"},
{`{}`, "readonly", "readonly"},
{`{"role":"admin"}`, "readonly", "readonly"},
{`{}`, "user", "user"},
// admin and unknown values must never be granted through self-registration
{`{}`, "admin", "user"},
{`{"role":"readonly"}`, "bogus", "user"},
} {
t.Run(tc.createData+"/default="+tc.defaultRole, func(t *testing.T) {
t.Setenv("OAUTH_DEFAULT_USER_ROLE", tc.defaultRole)
createData := tc.createData
h, err := beszelTests.NewTestHub(t.TempDir())
require.NoError(t, err)
defer h.Cleanup()
@@ -62,7 +76,7 @@ func TestOAuthUserRole(t *testing.T) {
login()
user, err := h.FindAuthRecordByEmail("users", "oauth@example.com")
require.NoError(t, err)
require.Equal(t, "user", user.GetString("role"))
require.Equal(t, tc.want, user.GetString("role"))
// A later OAuth login must preserve a role assigned by an administrator.
user.Set("role", "admin")
@@ -75,7 +89,23 @@ func TestOAuthUserRole(t *testing.T) {
}
}
func TestEnvBootstrapUserIsAdmin(t *testing.T) {
t.Setenv("USER_EMAIL", "bootstrap@example.com")
t.Setenv("USER_PASSWORD", "password12345")
t.Setenv("OAUTH_DEFAULT_USER_ROLE", "readonly")
h, err := beszelTests.NewTestHub(t.TempDir())
require.NoError(t, err)
defer h.Cleanup()
h.StartHub()
user, err := h.FindAuthRecordByEmail("users", "bootstrap@example.com")
require.NoError(t, err)
require.Equal(t, "admin", user.GetString("role"))
}
func TestInternalUserRole(t *testing.T) {
// OAUTH_DEFAULT_USER_ROLE must not affect users created outside OAuth.
t.Setenv("OAUTH_DEFAULT_USER_ROLE", "readonly")
for _, role := range []string{"", "user", "admin", "readonly"} {
t.Run("role="+role, func(t *testing.T) {
h, err := beszelTests.NewTestHub(t.TempDir())
+11 -1
View File
@@ -6,6 +6,7 @@ import (
"log"
"net/http"
"github.com/henrygd/beszel/internal/hub/utils"
"github.com/henrygd/beszel/internal/migrations"
"github.com/pocketbase/dbx"
@@ -24,13 +25,22 @@ func NewUserManager(app core.App) *UserManager {
}
}
// oauthDefaultRole returns the role for new OAuth users from OAUTH_DEFAULT_USER_ROLE.
// Only "user" and "readonly" are accepted; anything else (including "admin") falls back to "user".
func oauthDefaultRole() string {
if role, _ := utils.GetEnv("OAUTH_DEFAULT_USER_ROLE"); role == "readonly" {
return role
}
return "user"
}
// InitializeOAuthUserRole prevents self-registration from assigning a privileged role.
func (um *UserManager) InitializeOAuthUserRole(e *core.RecordAuthWithOAuth2RequestEvent) error {
if e.IsNewRecord {
if e.CreateData == nil {
e.CreateData = make(map[string]any)
}
e.CreateData["role"] = "user"
e.CreateData["role"] = oauthDefaultRole()
}
return e.Next()
}