Prevent removing idp integration when oauth user is superadmin (#3589)

* feat(go): prevent removing idp integration when oauth user is superadmin.

* feat(go): add suggestion for user;

* feat(go): remove usages of boolean fields on user;

* feat(go): set boolean fields correctly, but don't use;

* fix(go): static issues;

* feat(go): add suggestion for user;
This commit is contained in:
Vishal Dalwadi
2025-08-25 10:28:53 +05:30
committed by GitHub
parent c3498004c1
commit ec6e6c393a
7 changed files with 53 additions and 27 deletions

View File

@@ -4,6 +4,7 @@ import (
"context"
"encoding/json"
"errors"
"fmt"
"github.com/gravitl/netmaker/db"
"github.com/gravitl/netmaker/schema"
"github.com/google/go-cmp/cmp"
@@ -274,6 +275,24 @@ func updateSettings(w http.ResponseWriter, r *http.Request) {
return
}
currSettings := logic.GetServerSettings()
if req.AuthProvider != currSettings.AuthProvider && req.AuthProvider == "" {
superAdmin, err := logic.GetSuperAdmin()
if err != nil {
err = fmt.Errorf("failed to get super admin: %v", err)
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
return
}
if superAdmin.AuthType == models.OAuth {
err := fmt.Errorf(
"cannot remove IdP integration because an OAuth user has the super-admin role; transfer the super-admin role to another user first",
)
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
return
}
}
err := logic.UpsertServerSettings(req)
if err != nil {
logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("failed to update server settings "+err.Error()), "internal"))

View File

@@ -296,7 +296,7 @@ func authenticateUser(response http.ResponseWriter, request *http.Request) {
return
}
if !user.IsSuperAdmin && !logic.IsBasicAuthEnabled() {
if user.PlatformRoleID != models.SuperAdminRole && !logic.IsBasicAuthEnabled() {
logic.ReturnErrorResponse(
response,
request,
@@ -1124,6 +1124,7 @@ func transferSuperAdmin(w http.ResponseWriter, r *http.Request) {
return
}
u.IsSuperAdmin = true
u.PlatformRoleID = models.SuperAdminRole
err = logic.UpsertUser(*u)
if err != nil {
@@ -1131,6 +1132,8 @@ func transferSuperAdmin(w http.ResponseWriter, r *http.Request) {
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
return
}
caller.IsSuperAdmin = false
caller.PlatformRoleID = models.AdminRole
err = logic.UpsertUser(*caller)
if err != nil {

View File

@@ -30,25 +30,12 @@ const (
NetmakerDesktopApp = "netmaker-desktop"
)
var (
superUser = models.User{}
)
func ClearSuperUserCache() {
superUser = models.User{}
}
var IsOAuthConfigured = func() bool { return false }
var ResetAuthProvider = func() {}
var ResetIDPSyncHook = func() {}
// HasSuperAdmin - checks if server has an superadmin/owner
func HasSuperAdmin() (bool, error) {
if superUser.IsSuperAdmin {
return true, nil
}
collection, err := database.FetchRecords(database.USERS_TABLE_NAME)
if err != nil {
if database.IsEmptyRecord(err) {
@@ -63,7 +50,7 @@ func HasSuperAdmin() (bool, error) {
if err != nil {
continue
}
if user.PlatformRoleID == models.SuperAdminRole || user.IsSuperAdmin {
if user.PlatformRoleID == models.SuperAdminRole {
return true, nil
}
}
@@ -215,6 +202,8 @@ func CreateSuperAdmin(u *models.User) error {
if hassuperadmin {
return errors.New("superadmin user already exists")
}
u.IsSuperAdmin = true
u.IsAdmin = true
u.PlatformRoleID = models.SuperAdminRole
return CreateUser(u)
}
@@ -282,9 +271,7 @@ func UpsertUser(user models.User) error {
slog.Error("error inserting user", "user", user.UserName, "error", err.Error())
return err
}
if user.IsSuperAdmin {
superUser = user
}
return nil
}

View File

@@ -247,7 +247,7 @@ func GetIngressGwUsers(node models.Node) (models.IngressGwUsers, error) {
return gwUsers, err
}
for _, user := range users {
if !user.IsAdmin && !user.IsSuperAdmin {
if user.PlatformRoleID != models.SuperAdminRole && user.PlatformRoleID != models.AdminRole {
gwUsers.Users = append(gwUsers.Users, user)
}
}

View File

@@ -82,7 +82,7 @@ func GetSuperAdmin() (models.ReturnUser, error) {
return models.ReturnUser{}, err
}
for _, user := range users {
if user.IsSuperAdmin || user.PlatformRoleID == models.SuperAdminRole {
if user.PlatformRoleID == models.SuperAdminRole {
return user, nil
}
}

View File

@@ -125,7 +125,15 @@ func assignSuperAdmin() {
return
}
for _, u := range users {
if u.IsAdmin {
var isAdmin bool
if u.PlatformRoleID == models.AdminRole {
isAdmin = true
}
if u.PlatformRoleID == "" && u.IsAdmin {
isAdmin = true
}
if isAdmin {
user, err := logic.GetUser(u.UserName)
if err != nil {
slog.Error("error getting user", "user", u.UserName, "error", err.Error())
@@ -530,11 +538,18 @@ func syncUsers() {
user := user
if user.PlatformRoleID == models.AdminRole && !user.IsAdmin {
user.IsAdmin = true
user.IsSuperAdmin = false
logic.UpsertUser(user)
}
if user.PlatformRoleID == models.SuperAdminRole && !user.IsSuperAdmin {
user.IsSuperAdmin = true
user.IsAdmin = true
logic.UpsertUser(user)
}
if user.PlatformRoleID == models.PlatformUser || user.PlatformRoleID == models.ServiceUser {
user.IsSuperAdmin = false
user.IsAdmin = false
logic.UpsertUser(user)
}
if user.PlatformRoleID.String() != "" {
logic.MigrateUserRoleAndGroups(user)
@@ -552,9 +567,12 @@ func syncUsers() {
if len(user.UserGroups) == 0 {
user.UserGroups = make(map[models.UserGroupID]struct{})
}
// We reach here only if the platform role id has not been set.
//
// Thus, we use the boolean fields to assign the role.
if user.IsSuperAdmin {
user.PlatformRoleID = models.SuperAdminRole
} else if user.IsAdmin {
user.PlatformRoleID = models.AdminRole
} else {

View File

@@ -1935,11 +1935,10 @@ func removeIDPIntegration(w http.ResponseWriter, r *http.Request) {
}
if superAdmin.AuthType == models.OAuth {
logic.ReturnErrorResponse(
w,
r,
logic.FormatError(fmt.Errorf("cannot remove idp integration with superadmin oauth user"), "badrequest"),
err := fmt.Errorf(
"cannot remove IdP integration because an OAuth user has the super-admin role; transfer the super-admin role to another user first",
)
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
return
}