mirror of
https://github.com/fleetdm/fleet
synced 2026-04-21 21:47:20 +00:00
Resolves #37192 Separating generic endpoint_utils middleware logic from domain-specific business logic. New bounded contexts would share the generic logic and implement their own domain-specific logic. The two approaches used in this PR are: - Use common `platform` types - Use interfaces In the next PR we will move `endpointer_utils`, `authzcheck` and `ratelimit` into `platform` directory. # Checklist for submitter - [x] Added changes file ## Testing - [x] Added/updated tests - [x] QA'd all new/changed functionality manually <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Restructured internal error handling and context management to support bounded context architecture. * Improved error context collection and telemetry observability through a provider-based mechanism. * Decoupled licensing and authentication concerns into interfaces for better modularity. * **Chores** * Updated internal package dependencies to align with new architectural boundaries. <sub>✏️ Tip: You can customize this high-level summary in your review settings.</sub> <!-- end of auto-generated comment: release notes by coderabbit.ai -->
82 lines
2.1 KiB
Go
82 lines
2.1 KiB
Go
package service
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/fleetdm/fleet/v4/server/authz"
|
|
"github.com/fleetdm/fleet/v4/server/contexts/ctxerr"
|
|
"github.com/fleetdm/fleet/v4/server/contexts/license"
|
|
"github.com/fleetdm/fleet/v4/server/fleet"
|
|
"github.com/fleetdm/fleet/v4/server/ptr"
|
|
)
|
|
|
|
func (svc *Service) CreateInitialUser(ctx context.Context, p fleet.UserPayload) (*fleet.User, error) {
|
|
// skipauth: Only the initial user creation should be allowed to skip
|
|
// authorization (because there is not yet a user context to check against).
|
|
svc.authz.SkipAuthorization(ctx)
|
|
|
|
setupRequired, err := svc.SetupRequired(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if !setupRequired {
|
|
return nil, ctxerr.New(ctx, "a user already exists")
|
|
}
|
|
|
|
// Initial user should be global admin with no explicit teams
|
|
p.GlobalRole = ptr.String(fleet.RoleAdmin)
|
|
p.Teams = nil
|
|
|
|
return svc.NewUser(ctx, p)
|
|
}
|
|
|
|
func (svc *Service) NewUser(ctx context.Context, p fleet.UserPayload) (*fleet.User, error) {
|
|
licChecker, _ := license.FromContext(ctx)
|
|
lic, _ := licChecker.(*fleet.LicenseInfo)
|
|
if lic == nil {
|
|
return nil, ctxerr.New(ctx, "license not found")
|
|
}
|
|
if err := fleet.ValidateUserRoles(true, p, *lic); err != nil {
|
|
return nil, ctxerr.Wrap(ctx, err, "validate role")
|
|
}
|
|
if !lic.IsPremium() {
|
|
p.MFAEnabled = ptr.Bool(false)
|
|
}
|
|
|
|
user, err := p.User(svc.config.Auth.SaltKeySize, svc.config.Auth.BcryptCost)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
user, err = svc.ds.NewUser(ctx, user)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
adminUser := authz.UserFromContext(ctx)
|
|
if adminUser == nil {
|
|
// In case of invites the user created herself.
|
|
adminUser = user
|
|
}
|
|
if err := svc.NewActivity(
|
|
ctx,
|
|
adminUser,
|
|
fleet.ActivityTypeCreatedUser{
|
|
UserID: user.ID,
|
|
UserName: user.Name,
|
|
UserEmail: user.Email,
|
|
},
|
|
); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := fleet.LogRoleChangeActivities(ctx, svc, adminUser, nil, nil, user); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return user, nil
|
|
}
|
|
|
|
func (svc *Service) UserUnauthorized(ctx context.Context, id uint) (*fleet.User, error) {
|
|
// Explicitly no authorization check. Should only be used by middleware.
|
|
return svc.ds.UserByID(ctx, id)
|
|
}
|