Identity: remove GetTypedID (#91745)

pull/91739/head
Karl Persson 11 months ago committed by GitHub
parent 6061fdc8b9
commit bcfb66b416
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 48
      pkg/api/dashboard.go
  2. 6
      pkg/api/datasources.go
  3. 14
      pkg/api/folder.go
  4. 6
      pkg/api/index.go
  5. 5
      pkg/api/login.go
  6. 5
      pkg/api/org.go
  7. 9
      pkg/api/org_invite.go
  8. 24
      pkg/api/preferences.go
  9. 6
      pkg/api/render.go
  10. 6
      pkg/api/signup.go
  11. 20
      pkg/api/user.go
  12. 12
      pkg/api/user_token.go
  13. 1
      pkg/apimachinery/identity/error.go
  14. 33
      pkg/apimachinery/identity/requester.go
  15. 6
      pkg/apimachinery/identity/static.go
  16. 8
      pkg/apimachinery/identity/typed_id.go
  17. 3
      pkg/services/accesscontrol/acimpl/accesscontrol.go
  18. 15
      pkg/services/accesscontrol/acimpl/service.go
  19. 4
      pkg/services/accesscontrol/middleware.go
  20. 17
      pkg/services/auth/idimpl/service.go
  21. 8
      pkg/services/authn/clients/oauth.go
  22. 2
      pkg/services/authn/clients/oauth_test.go
  23. 16
      pkg/services/authn/identity.go
  24. 10
      pkg/services/contexthandler/contexthandler.go
  25. 8
      pkg/services/dashboardimport/service/service.go
  26. 4
      pkg/services/dashboardimport/service/service_test.go
  27. 40
      pkg/services/dashboards/service/dashboard_service.go
  28. 20
      pkg/services/dashboards/service/dashboard_service_integration_test.go
  29. 8
      pkg/services/dashboardsnapshots/database/database.go
  30. 9
      pkg/services/dashboardsnapshots/service.go
  31. 40
      pkg/services/folder/folderimpl/folder.go
  32. 10
      pkg/services/guardian/accesscontrol_guardian.go
  33. 29
      pkg/services/libraryelements/database.go
  34. 9
      pkg/services/live/live.go
  35. 8
      pkg/services/live/runstream/manager_test.go
  36. 2
      pkg/services/navtree/navtreeimpl/navtree.go
  37. 10
      pkg/services/ngalert/api/api_ruler.go
  38. 8
      pkg/services/ngalert/provisioning/alert_rules.go
  39. 25
      pkg/services/oauthtoken/oauth_token.go
  40. 3
      pkg/services/pluginsintegration/clientmiddleware/user_header_middleware.go
  41. 3
      pkg/services/serviceaccounts/api/api.go
  42. 7
      pkg/services/sqlstore/permissions/dashboard.go
  43. 7
      pkg/services/sqlstore/permissions/dashboard_filter_no_subquery.go
  44. 48
      pkg/services/star/api/api.go
  45. 2
      pkg/services/team/teamapi/team.go
  46. 10
      pkg/services/user/identity.go
  47. 3
      pkg/util/proxyutil/proxyutil.go

@ -43,13 +43,11 @@ func (hs *HTTPServer) isDashboardStarredByUser(c *contextmodel.ReqContext, dashI
return false, nil
}
namespaceID, userIDstr := c.SignedInUser.GetTypedID()
if namespaceID != identity.TypeUser {
if !identity.IsIdentityType(c.SignedInUser.GetID(), identity.TypeUser) {
return false, nil
}
userID, err := identity.IntIdentifier(namespaceID, userIDstr)
userID, err := identity.UserIdentifier(c.SignedInUser.GetID())
if err != nil {
return false, err
}
@ -439,16 +437,13 @@ func (hs *HTTPServer) deleteDashboard(c *contextmodel.ReqContext) response.Respo
return response.Error(http.StatusBadRequest, "Use folders endpoint for deleting folders.", nil)
}
namespaceID, userIDStr := c.SignedInUser.GetTypedID()
// disconnect all library elements for this dashboard
err = hs.LibraryElementService.DisconnectElementsFromDashboard(c.Req.Context(), dash.ID)
if err != nil {
hs.log.Error(
"Failed to disconnect library elements",
"dashboard", dash.ID,
"namespaceID", namespaceID,
"user", userIDStr,
"identity", c.GetID(),
"error", err)
}
@ -515,15 +510,9 @@ func (hs *HTTPServer) postDashboard(c *contextmodel.ReqContext, cmd dashboards.S
ctx := c.Req.Context()
var err error
userID := int64(0)
namespaceID, userIDstr := c.SignedInUser.GetTypedID()
if namespaceID != identity.TypeUser && namespaceID != identity.TypeServiceAccount {
hs.log.Debug("User does not belong to a user or service account namespace", "namespaceID", namespaceID, "userID", userIDstr)
} else {
userID, err = identity.IntIdentifier(namespaceID, userIDstr)
if err != nil {
hs.log.Debug("Error while parsing user ID", "namespaceID", namespaceID, "userID", userIDstr)
}
var userID int64
if id, err := identity.UserIdentifier(c.SignedInUser.GetID()); err == nil {
userID = id
}
cmd.OrgID = c.SignedInUser.GetOrgID()
@ -632,16 +621,9 @@ func (hs *HTTPServer) postDashboard(c *contextmodel.ReqContext, cmd dashboards.S
// 401: unauthorisedError
// 500: internalServerError
func (hs *HTTPServer) GetHomeDashboard(c *contextmodel.ReqContext) response.Response {
userID := int64(0)
var err error
namespaceID, userIDstr := c.SignedInUser.GetTypedID()
if namespaceID != identity.TypeUser && namespaceID != identity.TypeServiceAccount {
hs.log.Debug("User does not belong to a user or service account namespace", "namespaceID", namespaceID, "userID", userIDstr)
} else {
userID, err = identity.IntIdentifier(namespaceID, userIDstr)
if err != nil {
hs.log.Debug("Error while parsing user ID", "namespaceID", namespaceID, "userID", userIDstr)
}
var userID int64
if id, err := identity.UserIdentifier(c.SignedInUser.GetID()); err == nil {
userID = id
}
prefsQuery := pref.GetPreferenceWithDefaultsQuery{OrgID: c.SignedInUser.GetOrgID(), UserID: userID, Teams: c.SignedInUser.GetTeams()}
@ -1085,15 +1067,9 @@ func (hs *HTTPServer) RestoreDashboardVersion(c *contextmodel.ReqContext) respon
return response.Error(http.StatusNotFound, "Dashboard version not found", nil)
}
userID := int64(0)
namespaceID, userIDstr := c.SignedInUser.GetTypedID()
if namespaceID != identity.TypeUser && namespaceID != identity.TypeServiceAccount {
hs.log.Warn("User does not belong to a user or service account namespace", "namespaceID", namespaceID, "userID", userIDstr)
} else {
userID, err = identity.IntIdentifier(namespaceID, userIDstr)
if err != nil {
hs.log.Warn("Error while parsing user ID", "namespaceID", namespaceID, "userID", userIDstr)
}
var userID int64
if id, err := identity.UserIdentifier(c.SignedInUser.GetID()); err == nil {
userID = id
}
saveCmd := dashboards.SaveDashboardCommand{}

@ -442,11 +442,7 @@ func (hs *HTTPServer) AddDataSource(c *contextmodel.ReqContext) response.Respons
return response.Error(http.StatusBadRequest, "bad request data", err)
}
userID, err := identity.UserIdentifier(c.SignedInUser.GetTypedID())
if err != nil {
return response.Error(http.StatusInternalServerError,
"Failed to add datasource", err)
}
userID, _ := identity.UserIdentifier(c.SignedInUser.GetID())
datasourcesLogger.Debug("Received command to add data source", "url", cmd.URL)
cmd.OrgID = c.SignedInUser.GetOrgID()

@ -191,15 +191,13 @@ func (hs *HTTPServer) setDefaultFolderPermissions(ctx context.Context, orgID int
if !hs.Cfg.RBAC.PermissionsOnCreation("folder") {
return nil
}
var permissions []accesscontrol.SetResourcePermissionCommand
var userID int64
namespace, id := user.GetTypedID()
if namespace == identity.TypeUser {
var errID error
userID, errID = identity.IntIdentifier(namespace, id)
if errID != nil {
return errID
if identity.IsIdentityType(user.GetID(), identity.TypeUser) {
userID, err := identity.UserIdentifier(user.GetID())
if err != nil {
return err
}
permissions = append(permissions, accesscontrol.SetResourcePermissionCommand{

@ -31,7 +31,7 @@ func (hs *HTTPServer) setIndexViewData(c *contextmodel.ReqContext) (*dtos.IndexV
return nil, err
}
userID, _ := identity.UserIdentifier(c.SignedInUser.GetTypedID())
userID, _ := identity.UserIdentifier(c.SignedInUser.GetID())
prefsQuery := pref.GetPreferenceWithDefaultsQuery{UserID: userID, OrgID: c.SignedInUser.GetOrgID(), Teams: c.Teams}
prefs, err := hs.preferenceService.GetWithDefaults(c.Req.Context(), &prefsQuery)
@ -169,10 +169,8 @@ func (hs *HTTPServer) setIndexViewData(c *contextmodel.ReqContext) (*dtos.IndexV
}
func (hs *HTTPServer) buildUserAnalyticsSettings(c *contextmodel.ReqContext) dtos.AnalyticsSettings {
namespace, _ := c.SignedInUser.GetTypedID()
// Anonymous users do not have an email or auth info
if namespace != identity.TypeUser {
if !identity.IsIdentityType(c.SignedInUser.GetID(), identity.TypeUser) {
return dtos.AnalyticsSettings{Identifier: "@" + hs.Cfg.AppURL}
}

@ -257,8 +257,7 @@ func (hs *HTTPServer) Logout(c *contextmodel.ReqContext) {
return
}
_, id := c.SignedInUser.GetTypedID()
hs.log.Info("Successful Logout", "userID", id)
hs.log.Info("Successful Logout", "id", c.SignedInUser.GetID())
c.Redirect(redirect.URL)
}
@ -305,7 +304,7 @@ func (hs *HTTPServer) redirectURLWithErrorCookie(c *contextmodel.ReqContext, err
var userID int64
if c.SignedInUser != nil && !c.SignedInUser.IsNil() {
var errID error
userID, errID = identity.UserIdentifier(c.SignedInUser.GetTypedID())
userID, errID = identity.UserIdentifier(c.SignedInUser.GetID())
if errID != nil {
hs.log.Error("failed to retrieve user ID", "error", errID)
}

@ -132,12 +132,11 @@ func (hs *HTTPServer) CreateOrg(c *contextmodel.ReqContext) response.Response {
return response.Error(http.StatusBadRequest, "bad request data", err)
}
namespace, identifier := c.SignedInUser.GetTypedID()
if namespace != identity.TypeUser {
if !identity.IsIdentityType(c.SignedInUser.GetID(), identity.TypeUser) {
return response.Error(http.StatusForbidden, "Only users can create organizations", nil)
}
userID, err := identity.IntIdentifier(namespace, identifier)
userID, err := identity.UserIdentifier(c.SignedInUser.GetID())
if err != nil {
return response.Error(http.StatusInternalServerError, "Failed to parse user id", err)
}

@ -101,14 +101,9 @@ func (hs *HTTPServer) AddOrgInvite(c *contextmodel.ReqContext) response.Response
cmd.Name = inviteDto.Name
cmd.Status = tempuser.TmpUserInvitePending
namespace, identifier := c.SignedInUser.GetTypedID()
var userID int64
if namespace == identity.TypeUser || namespace == identity.TypeServiceAccount {
var err error
userID, err = strconv.ParseInt(identifier, 10, 64)
if err != nil {
return response.Error(http.StatusInternalServerError, "Unrecognized user", err)
}
if id, err := identity.UserIdentifier(c.SignedInUser.GetID()); err == nil {
userID = id
}
cmd.InvitedByUserID = userID

@ -22,9 +22,9 @@ func (hs *HTTPServer) SetHomeDashboard(c *contextmodel.ReqContext) response.Resp
return response.Error(http.StatusBadRequest, "bad request data", err)
}
userID, errID := identity.UserIdentifier(c.SignedInUser.GetTypedID())
if errID != nil {
return response.Error(http.StatusInternalServerError, "Failed to set home dashboard", errID)
userID, err := identity.UserIdentifier(c.SignedInUser.GetID())
if err != nil {
return response.Error(http.StatusInternalServerError, "Failed to set home dashboard", err)
}
cmd.UserID = userID
@ -64,9 +64,9 @@ func (hs *HTTPServer) SetHomeDashboard(c *contextmodel.ReqContext) response.Resp
// 401: unauthorisedError
// 500: internalServerError
func (hs *HTTPServer) GetUserPreferences(c *contextmodel.ReqContext) response.Response {
userID, errID := identity.UserIdentifier(c.SignedInUser.GetTypedID())
if errID != nil {
return response.Error(http.StatusInternalServerError, "Failed to get user preferences", errID)
userID, err := identity.UserIdentifier(c.SignedInUser.GetID())
if err != nil {
return response.Error(http.StatusInternalServerError, "Failed to update user preferences", err)
}
return prefapi.GetPreferencesFor(c.Req.Context(), hs.DashboardService, hs.preferenceService, c.SignedInUser.GetOrgID(), userID, 0)
@ -89,9 +89,9 @@ func (hs *HTTPServer) UpdateUserPreferences(c *contextmodel.ReqContext) response
return response.Error(http.StatusBadRequest, "bad request data", err)
}
userID, errID := identity.UserIdentifier(c.SignedInUser.GetTypedID())
if errID != nil {
return response.Error(http.StatusInternalServerError, "Failed to update user preferences", errID)
userID, err := identity.UserIdentifier(c.SignedInUser.GetID())
if err != nil {
return response.Error(http.StatusInternalServerError, "Failed to update user preferences", err)
}
return prefapi.UpdatePreferencesFor(c.Req.Context(), hs.DashboardService,
@ -113,9 +113,9 @@ func (hs *HTTPServer) PatchUserPreferences(c *contextmodel.ReqContext) response.
return response.Error(http.StatusBadRequest, "bad request data", err)
}
userID, errID := identity.UserIdentifier(c.SignedInUser.GetTypedID())
if errID != nil {
return response.Error(http.StatusInternalServerError, "Failed to update user preferences", errID)
userID, err := identity.UserIdentifier(c.SignedInUser.GetID())
if err != nil {
return response.Error(http.StatusInternalServerError, "Failed to update user preferences", err)
}
return hs.patchPreferencesFor(c.Req.Context(), c.SignedInUser.GetOrgID(), userID, 0, &dtoCmd)

@ -65,9 +65,9 @@ func (hs *HTTPServer) RenderHandler(c *contextmodel.ReqContext) {
headers["Accept-Language"] = acceptLanguageHeader
}
userID, errID := identity.UserIdentifier(c.SignedInUser.GetTypedID())
if errID != nil {
hs.log.Error("Failed to parse user id", "err", errID)
userID, err := identity.UserIdentifier(c.SignedInUser.GetID())
if err != nil {
hs.log.Debug("Failed to parse user id", "err", err)
}
encoding := queryReader.Get("encoding", "")

@ -47,9 +47,9 @@ func (hs *HTTPServer) SignUp(c *contextmodel.ReqContext) response.Response {
return response.Error(http.StatusUnprocessableEntity, "User with same email address already exists", nil)
}
userID, errID := identity.UserIdentifier(c.SignedInUser.GetTypedID())
if errID != nil {
hs.log.Error("Failed to parse user id", "err", errID)
userID, err := identity.UserIdentifier(c.SignedInUser.GetID())
if err != nil {
hs.log.Debug("Failed to parse user id", "err", err)
}
cmd := tempuser.CreateTempUserCommand{}

@ -31,8 +31,7 @@ import (
// 404: notFoundError
// 500: internalServerError
func (hs *HTTPServer) GetSignedInUser(c *contextmodel.ReqContext) response.Response {
namespace, identifier := c.SignedInUser.GetTypedID()
if namespace != identity.TypeUser {
if !identity.IsIdentityType(c.GetID(), identity.TypeUser) {
return response.JSON(http.StatusOK, user.UserProfileDTO{
IsGrafanaAdmin: c.SignedInUser.GetIsGrafanaAdmin(),
OrgID: c.SignedInUser.GetOrgID(),
@ -43,7 +42,7 @@ func (hs *HTTPServer) GetSignedInUser(c *contextmodel.ReqContext) response.Respo
})
}
userID, err := identity.IntIdentifier(namespace, identifier)
userID, err := identity.UserIdentifier(c.GetID())
if err != nil {
return response.Error(http.StatusInternalServerError, "Failed to parse user id", err)
}
@ -278,8 +277,7 @@ func (hs *HTTPServer) handleUpdateUser(ctx context.Context, cmd user.UpdateUserC
}
func (hs *HTTPServer) StartEmailVerificaton(c *contextmodel.ReqContext) response.Response {
namespace, id := c.SignedInUser.GetTypedID()
if !identity.IsIdentityType(namespace, identity.TypeUser) {
if !identity.IsIdentityType(c.SignedInUser.GetID(), identity.TypeUser) {
return response.Error(http.StatusBadRequest, "Only users can verify their email", nil)
}
@ -288,7 +286,7 @@ func (hs *HTTPServer) StartEmailVerificaton(c *contextmodel.ReqContext) response
return response.Respond(http.StatusNotModified, nil)
}
userID, err := strconv.ParseInt(id, 10, 64)
userID, err := identity.UserIdentifier(c.SignedInUser.GetID())
if err != nil {
return response.Error(http.StatusInternalServerError, "Got invalid user id", err)
}
@ -506,13 +504,12 @@ func (hs *HTTPServer) ChangeActiveOrgAndRedirectToHome(c *contextmodel.ReqContex
return
}
namespace, identifier := c.SignedInUser.GetTypedID()
if namespace != identity.TypeUser {
if !identity.IsIdentityType(c.SignedInUser.GetID(), identity.TypeUser) {
c.JsonApiErr(http.StatusForbidden, "Endpoint only available for users", nil)
return
}
userID, err := identity.IntIdentifier(namespace, identifier)
userID, err := identity.UserIdentifier(c.SignedInUser.GetID())
if err != nil {
c.JsonApiErr(http.StatusInternalServerError, "Failed to parse user id", err)
return
@ -632,12 +629,11 @@ func (hs *HTTPServer) ClearHelpFlags(c *contextmodel.ReqContext) response.Respon
}
func getUserID(c *contextmodel.ReqContext) (int64, *response.NormalResponse) {
namespace, identifier := c.SignedInUser.GetTypedID()
if namespace != identity.TypeUser {
if !identity.IsIdentityType(c.SignedInUser.GetID(), identity.TypeUser) {
return 0, response.Error(http.StatusForbidden, "Endpoint only available for users", nil)
}
userID, err := identity.IntIdentifier(namespace, identifier)
userID, err := identity.UserIdentifier(c.SignedInUser.GetID())
if err != nil {
return 0, response.Error(http.StatusInternalServerError, "Failed to parse user id", err)
}

@ -32,12 +32,11 @@ import (
// 403: forbiddenError
// 500: internalServerError
func (hs *HTTPServer) GetUserAuthTokens(c *contextmodel.ReqContext) response.Response {
namespace, identifier := c.SignedInUser.GetTypedID()
if namespace != identity.TypeUser {
return response.Error(http.StatusForbidden, "entity not allowed to revoke tokens", nil)
if !identity.IsIdentityType(c.SignedInUser.GetID(), identity.TypeUser) {
return response.Error(http.StatusForbidden, "entity not allowed to get tokens", nil)
}
userID, err := identity.IntIdentifier(namespace, identifier)
userID, err := identity.UserIdentifier(c.SignedInUser.GetID())
if err != nil {
return response.Error(http.StatusInternalServerError, "failed to parse user id", err)
}
@ -63,12 +62,11 @@ func (hs *HTTPServer) RevokeUserAuthToken(c *contextmodel.ReqContext) response.R
return response.Error(http.StatusBadRequest, "bad request data", err)
}
namespace, identifier := c.SignedInUser.GetTypedID()
if namespace != identity.TypeUser {
if !identity.IsIdentityType(c.SignedInUser.GetID(), identity.TypeUser) {
return response.Error(http.StatusForbidden, "entity not allowed to revoke tokens", nil)
}
userID, err := identity.IntIdentifier(namespace, identifier)
userID, err := identity.UserIdentifier(c.SignedInUser.GetID())
if err != nil {
return response.Error(http.StatusInternalServerError, "failed to parse user id", err)
}

@ -7,6 +7,7 @@ import (
)
var (
ErrInvalidIDType = errutil.BadRequest("auth.identity.invalid-id-type")
ErrInvalidTypedID = errutil.BadRequest("auth.identity.invalid-typed-id")
ErrNotIntIdentifier = errors.New("identifier is not an int64")
ErrIdentifierNotInitialized = errors.New("identifier is not initialized")

@ -17,15 +17,9 @@ type Requester interface {
GetRawIdentifier() string
// Deprecated: use GetUID instead
GetInternalID() (int64, error)
// GetID returns namespaced internalID for the entity
// Deprecated: use GetUID instead
GetID() TypedID
// GetTypedID returns the namespace and ID of the active entity.
// The namespace is one of the constants defined in pkg/apimachinery/identity.
// Deprecated: use GetID instead
GetTypedID() (kind IdentityType, identifier string)
// GetDisplayName returns the display name of the active entity.
// The display name is the name if it is set, otherwise the login or email.
GetDisplayName() string
@ -82,14 +76,14 @@ type Requester interface {
GetIDClaims() *authnlib.Claims[authnlib.IDTokenClaims]
}
// IntIdentifier converts a string identifier to an int64.
// IntIdentifier converts a typeID to an int64.
// Applicable for users, service accounts, api keys and renderer service.
// Errors if the identifier is not initialized or if namespace is not recognized.
func IntIdentifier(kind IdentityType, identifier string) (int64, error) {
if IsIdentityType(kind, TypeUser, TypeAPIKey, TypeServiceAccount, TypeRenderService) {
id, err := strconv.ParseInt(identifier, 10, 64)
// Errors if the identifier is not initialized or if type is not recognized.
func IntIdentifier(typedID TypedID) (int64, error) {
if IsIdentityType(typedID, TypeUser, TypeAPIKey, TypeServiceAccount, TypeRenderService) {
id, err := strconv.ParseInt(typedID.ID(), 10, 64)
if err != nil {
return 0, fmt.Errorf("unrecognized format for valid type %s: %w", kind, err)
return 0, fmt.Errorf("unrecognized format for valid type %s: %w", typedID.Type(), err)
}
if id < 1 {
@ -102,19 +96,18 @@ func IntIdentifier(kind IdentityType, identifier string) (int64, error) {
return 0, ErrNotIntIdentifier
}
// UserIdentifier converts a string identifier to an int64.
// UserIdentifier converts a typeID to an int64.
// Errors if the identifier is not initialized or if namespace is not recognized.
// Returns 0 if the namespace is not user or service account
func UserIdentifier(kind IdentityType, identifier string) (int64, error) {
userID, err := IntIdentifier(kind, identifier)
// Returns 0 if the type is not user or service account
func UserIdentifier(typedID TypedID) (int64, error) {
userID, err := IntIdentifier(typedID)
if err != nil {
// FIXME: return this error once entity namespaces are handled by stores
return 0, nil
return 0, err
}
if IsIdentityType(kind, TypeUser, TypeServiceAccount) {
if IsIdentityType(typedID, TypeUser, TypeServiceAccount) {
return userID, nil
}
return 0, nil
return 0, ErrInvalidIDType
}

@ -149,12 +149,6 @@ func (u *StaticRequester) GetID() TypedID {
return NewTypedIDString(u.Type, fmt.Sprintf("%d", u.UserID))
}
// GetTypedID returns the namespace and ID of the active entity
// The namespace is one of the constants defined in pkg/apimachinery/identity
func (u *StaticRequester) GetTypedID() (IdentityType, string) {
return u.Type, fmt.Sprintf("%d", u.UserID)
}
func (u *StaticRequester) GetAuthID() string {
return u.AuthID
}

@ -42,10 +42,10 @@ func ParseType(str string) (IdentityType, error) {
}
}
// IsIdentityType returns true if type matches any expected identity type
func IsIdentityType(typ IdentityType, expected ...IdentityType) bool {
// IsIdentityType returns true if typedID matches any expected identity type
func IsIdentityType(typedID TypedID, expected ...IdentityType) bool {
for _, e := range expected {
if typ == e {
if typedID.Type() == e {
return true
}
}
@ -128,7 +128,7 @@ func (ni TypedID) Type() IdentityType {
}
func (ni TypedID) IsType(expected ...IdentityType) bool {
return IsIdentityType(ni.t, expected...)
return IsIdentityType(ni, expected...)
}
func (ni TypedID) String() string {

@ -192,6 +192,5 @@ func (a *AccessControl) RegisterScopeAttributeResolver(prefix string, resolver a
}
func (a *AccessControl) debug(ctx context.Context, ident identity.Requester, msg string, eval accesscontrol.Evaluator) {
namespace, id := ident.GetTypedID()
a.log.FromContext(ctx).Debug(msg, "namespace", namespace, "id", id, "orgID", ident.GetOrgID(), "permissions", eval.GoString())
a.log.FromContext(ctx).Debug(msg, "id", ident.GetID(), "orgID", ident.GetOrgID(), "permissions", eval.GoString())
}

@ -128,7 +128,7 @@ func (s *Service) GetUserPermissions(ctx context.Context, user identity.Requeste
return s.getCachedUserPermissions(ctx, user, options)
}
func (s *Service) getUserPermissions(ctx context.Context, user identity.Requester, options accesscontrol.Options) ([]accesscontrol.Permission, error) {
func (s *Service) getUserPermissions(ctx context.Context, user identity.Requester, _ accesscontrol.Options) ([]accesscontrol.Permission, error) {
ctx, span := s.tracer.Start(ctx, "authz.getUserPermissions")
defer span.End()
@ -143,10 +143,9 @@ func (s *Service) getUserPermissions(ctx context.Context, user identity.Requeste
permissions = append(permissions, SharedWithMeFolderPermission)
}
userID, err := identity.UserIdentifier(user.GetTypedID())
if err != nil {
return nil, err
}
// we don't care about the error here, if this fails we get 0 and no
// permission assigned to user will be returned, only for org role.
userID, _ := identity.UserIdentifier(user.GetID())
dbPermissions, err := s.store.GetUserPermissions(ctx, accesscontrol.GetUserPermissionsQuery{
OrgID: user.GetOrgID(),
@ -211,12 +210,10 @@ func (s *Service) getUserDirectPermissions(ctx context.Context, user identity.Re
ctx, span := s.tracer.Start(ctx, "authz.getUserDirectPermissions")
defer span.End()
namespace, identifier := user.GetTypedID()
var userID int64
if namespace == identity.TypeUser || namespace == identity.TypeServiceAccount {
if identity.IsIdentityType(user.GetID(), identity.TypeUser, identity.TypeServiceAccount) {
var err error
userID, err = strconv.ParseInt(identifier, 10, 64)
userID, err = identity.UserIdentifier(user.GetID())
if err != nil {
return nil, err
}

@ -80,11 +80,9 @@ func deny(c *contextmodel.ReqContext, evaluator Evaluator, err error) {
if err != nil {
c.Logger.Error("Error from access control system", "error", err, "accessErrorID", id)
} else {
namespace, identifier := c.SignedInUser.GetTypedID()
c.Logger.Info(
"Access denied",
"namespace", namespace,
"userID", identifier,
"id", c.SignedInUser.GetID(),
"accessErrorID", id,
"permissions", evaluator.GoString(),
)

@ -70,12 +70,10 @@ func (s *Service) SignIdentity(ctx context.Context, id identity.Requester) (stri
idClaims *auth.IDClaims
}
result, err, _ := s.si.Do(cacheKey, func() (any, error) {
namespace, identifier := id.GetTypedID()
cachedToken, err := s.cache.Get(ctx, cacheKey)
if err == nil {
s.metrics.tokenSigningFromCacheCounter.Inc()
s.logger.FromContext(ctx).Debug("Cached token found", "namespace", namespace, "id", identifier)
s.logger.FromContext(ctx).Debug("Cached token found", "id", id.GetID())
tokenClaims, err := s.extractTokenClaims(string(cachedToken))
if err != nil {
@ -85,14 +83,14 @@ func (s *Service) SignIdentity(ctx context.Context, id identity.Requester) (stri
}
s.metrics.tokenSigningCounter.Inc()
s.logger.FromContext(ctx).Debug("Sign new id token", "namespace", namespace, "id", identifier)
s.logger.FromContext(ctx).Debug("Sign new id token", "id", id.GetID())
now := time.Now()
claims := &auth.IDClaims{
Claims: &jwt.Claims{
Issuer: s.cfg.AppURL,
Audience: getAudience(id.GetOrgID()),
Subject: getSubject(namespace.String(), identifier),
Subject: id.GetID().String(),
Expiry: jwt.NewNumericDate(now.Add(tokenTTL)),
IssuedAt: jwt.NewNumericDate(now),
},
@ -101,7 +99,7 @@ func (s *Service) SignIdentity(ctx context.Context, id identity.Requester) (stri
},
}
if identity.IsIdentityType(namespace, identity.TypeUser) {
if identity.IsIdentityType(id.GetID(), identity.TypeUser) {
claims.Rest.Email = id.GetEmail()
claims.Rest.EmailVerified = id.IsEmailVerified()
claims.Rest.AuthenticatedBy = id.GetAuthenticatedBy()
@ -145,8 +143,7 @@ func (s *Service) hook(ctx context.Context, identity *authn.Identity, _ *authn.R
token, claims, err := s.SignIdentity(ctx, identity)
if err != nil {
if shouldLogErr(err) {
namespace, id := identity.GetTypedID()
s.logger.FromContext(ctx).Error("Failed to sign id token", "err", err, "namespace", namespace, "id", id)
s.logger.FromContext(ctx).Error("Failed to sign id token", "err", err, "id", identity.GetID())
}
// for now don't return error so we don't break authentication from this hook
return nil
@ -179,10 +176,6 @@ func getAudience(orgID int64) jwt.Audience {
return jwt.Audience{fmt.Sprintf("org:%d", orgID)}
}
func getSubject(namespace, identifier string) string {
return fmt.Sprintf("%s:%s", namespace, identifier)
}
func prefixCacheKey(key string) string {
return fmt.Sprintf("%s-%s", cachePrefix, key)
}

@ -248,10 +248,9 @@ func (c *OAuth) RedirectURL(ctx context.Context, r *authn.Request) (*authn.Redir
func (c *OAuth) Logout(ctx context.Context, user identity.Requester) (*authn.Redirect, bool) {
token := c.oauthService.GetCurrentOAuthToken(ctx, user)
namespace, id := user.GetTypedID()
userID, err := identity.UserIdentifier(namespace, id)
userID, err := identity.UserIdentifier(user.GetID())
if err != nil {
c.log.FromContext(ctx).Error("Failed to parse user id", "namespace", namespace, "id", id, "error", err)
c.log.FromContext(ctx).Error("Failed to parse user id", "id", user.GetID(), "error", err)
return nil, false
}
@ -260,8 +259,7 @@ func (c *OAuth) Logout(ctx context.Context, user identity.Requester) (*authn.Red
AuthId: user.GetAuthID(),
AuthModule: user.GetAuthenticatedBy(),
}); err != nil {
namespace, id := user.GetTypedID()
c.log.FromContext(ctx).Error("Failed to invalidate tokens", "namespace", namespace, "id", id, "error", err)
c.log.FromContext(ctx).Error("Failed to invalidate tokens", "id", user.GetID(), "error", err)
}
oauthCfg := c.socialService.GetOAuthInfoProvider(c.providerName)

@ -485,7 +485,7 @@ func TestOAuth_Logout(t *testing.T) {
}
c := ProvideOAuth(authn.ClientWithPrefix("azuread"), tt.cfg, mockService, fakeSocialSvc, &setting.OSSImpl{Cfg: tt.cfg}, featuremgmt.WithFeatures())
redirect, ok := c.Logout(context.Background(), &authn.Identity{})
redirect, ok := c.Logout(context.Background(), &authn.Identity{ID: identity.NewTypedIDString(identity.TypeUser, "1")})
assert.Equal(t, tt.expectedOK, ok)
if tt.expectedOK {

@ -115,10 +115,6 @@ func (i *Identity) GetID() identity.TypedID {
return i.ID
}
func (i *Identity) GetTypedID() (namespace identity.IdentityType, identifier string) {
return i.ID.Type(), i.ID.ID()
}
func (i *Identity) GetUID() string {
return i.UID.String()
}
@ -132,14 +128,14 @@ func (i *Identity) GetAuthenticatedBy() string {
}
func (i *Identity) GetCacheKey() string {
namespace, id := i.GetTypedID()
id := i.GetID().ID()
if !i.HasUniqueId() {
// Hack use the org role as id for identities that do not have a unique id
// e.g. anonymous and render key.
id = string(i.GetOrgRole())
}
return fmt.Sprintf("%d-%s-%s", i.GetOrgID(), namespace, id)
return fmt.Sprintf("%d-%s-%s", i.GetOrgID(), i.GetID().Type(), id)
}
func (i *Identity) GetDisplayName() string {
@ -232,10 +228,10 @@ func (i *Identity) HasRole(role org.RoleType) bool {
}
func (i *Identity) HasUniqueId() bool {
namespace, _ := i.GetTypedID()
return namespace == identity.TypeUser ||
namespace == identity.TypeServiceAccount ||
namespace == identity.TypeAPIKey
typ := i.GetID().Type()
return typ == identity.TypeUser ||
typ == identity.TypeServiceAccount ||
typ == identity.TypeAPIKey
}
func (i *Identity) IsAuthenticatedBy(providers ...string) bool {

@ -154,22 +154,22 @@ func (h *ContextHandler) addIDHeaderEndOfRequestFunc(ident identity.Requester) w
return
}
namespace, id := ident.GetTypedID()
id := ident.GetID()
if !identity.IsIdentityType(
namespace,
id,
identity.TypeUser,
identity.TypeServiceAccount,
identity.TypeAPIKey,
) || id == "0" {
) || id.ID() == "0" {
return
}
if _, ok := h.Cfg.IDResponseHeaderNamespaces[namespace.String()]; !ok {
if _, ok := h.Cfg.IDResponseHeaderNamespaces[id.Type().String()]; !ok {
return
}
headerName := fmt.Sprintf("%s-Identity-Id", h.Cfg.IDResponseHeaderPrefix)
w.Header().Add(headerName, fmt.Sprintf("%s:%s", namespace, id))
w.Header().Add(headerName, id.String())
}
}

@ -109,11 +109,9 @@ func (s *ImportDashboardService) ImportDashboard(ctx context.Context, req *dashb
req.FolderUid = folder.UID
}
namespace, identifier := req.User.GetTypedID()
userID := int64(0)
if namespace == identity.TypeUser || namespace == identity.TypeServiceAccount {
userID, _ = identity.IntIdentifier(namespace, identifier)
var userID int64
if id, err := identity.UserIdentifier(req.User.GetID()); err == nil {
userID = id
}
saveCmd := dashboards.SaveDashboardCommand{

@ -83,7 +83,7 @@ func TestImportDashboardService(t *testing.T) {
require.NotNil(t, resp)
require.Equal(t, "UDdpyzz7z", resp.UID)
userID, err := identity.IntIdentifier(importDashboardArg.User.GetTypedID())
userID, err := identity.IntIdentifier(importDashboardArg.User.GetID())
require.NoError(t, err)
require.NotNil(t, importDashboardArg)
@ -149,7 +149,7 @@ func TestImportDashboardService(t *testing.T) {
require.NotNil(t, resp)
require.Equal(t, "UDdpyzz7z", resp.UID)
userID, err := identity.IntIdentifier(importDashboardArg.User.GetTypedID())
userID, err := identity.IntIdentifier(importDashboardArg.User.GetID())
require.NoError(t, err)
require.NotNil(t, importDashboardArg)

@ -207,9 +207,11 @@ func (dr *DashboardServiceImpl) BuildSaveDashboardCommand(ctx context.Context, d
}
}
userID, err := resolveUserID(dto.User, dr.log)
if err != nil {
return nil, err
var userID int64
if id, err := identity.UserIdentifier(dto.User.GetID()); err == nil {
userID = id
} else {
dr.log.Debug("User does not belong to a user or service account namespace, using 0 as user ID", "id", dto.User.GetID())
}
metrics.MFolderIDsServiceCount.WithLabelValues(metrics.Dashboard).Inc()
@ -232,22 +234,6 @@ func (dr *DashboardServiceImpl) BuildSaveDashboardCommand(ctx context.Context, d
return cmd, nil
}
func resolveUserID(user identity.Requester, log log.Logger) (int64, error) {
userID := int64(0)
namespaceID, identifier := user.GetTypedID()
if namespaceID != identity.TypeUser && namespaceID != identity.TypeServiceAccount {
log.Debug("User does not belong to a user or service account namespace", "namespaceID", namespaceID, "userID", identifier)
} else {
var err error
userID, err = identity.IntIdentifier(namespaceID, identifier)
if err != nil {
log.Debug("failed to parse user ID", "namespaceID", namespaceID, "userID", identifier, "error", err)
}
}
return userID, nil
}
func (dr *DashboardServiceImpl) DeleteOrphanedProvisionedDashboards(ctx context.Context, cmd *dashboards.DeleteOrphanedProvisionedDashboardsCommand) error {
return dr.dashboardStore.DeleteOrphanedProvisionedDashboards(ctx, cmd)
}
@ -503,12 +489,10 @@ func (dr *DashboardServiceImpl) setDefaultPermissions(ctx context.Context, dto *
var permissions []accesscontrol.SetResourcePermissionCommand
if !provisioned {
namespaceID, userIDstr := dto.User.GetTypedID()
userID, err := identity.IntIdentifier(namespaceID, userIDstr)
userID, err := identity.IntIdentifier(dto.User.GetID())
if err != nil {
dr.log.Error("Could not make user admin", "dashboard", dash.Title, "namespaceID", namespaceID, "userID", userID, "error", err)
} else if namespaceID == identity.TypeUser && userID > 0 {
dr.log.Error("Could not make user admin", "dashboard", dash.Title, "id", dto.User.GetID(), "error", err)
} else if identity.IsIdentityType(dto.User.GetID(), identity.TypeUser) {
permissions = append(permissions, accesscontrol.SetResourcePermissionCommand{
UserID: userID, Permission: dashboardaccess.PERMISSION_ADMIN.String(),
})
@ -541,12 +525,10 @@ func (dr *DashboardServiceImpl) setDefaultFolderPermissions(ctx context.Context,
var permissions []accesscontrol.SetResourcePermissionCommand
if !provisioned {
namespaceID, userIDstr := cmd.SignedInUser.GetTypedID()
userID, err := identity.IntIdentifier(namespaceID, userIDstr)
userID, err := identity.IntIdentifier(cmd.SignedInUser.GetID())
if err != nil {
dr.log.Error("Could not make user admin", "folder", cmd.Title, "namespaceID", namespaceID, "userID", userID, "error", err)
} else if namespaceID == identity.TypeUser && userID > 0 {
dr.log.Error("Could not make user admin", "folder", cmd.Title, "id", cmd.SignedInUser.GetID())
} else if identity.IsIdentityType(cmd.SignedInUser.GetID(), identity.TypeUser) {
permissions = append(permissions, accesscontrol.SetResourcePermissionCommand{
UserID: userID, Permission: dashboardaccess.PERMISSION_ADMIN.String(),
})

@ -116,7 +116,7 @@ func TestIntegrationIntegratedDashboardService(t *testing.T) {
err := callSaveWithError(t, cmd, sqlStore)
assert.Equal(t, dashboards.ErrDashboardUpdateAccessDenied, err)
userID, err := identity.IntIdentifier(sc.dashboardGuardianMock.User.GetTypedID())
userID, err := identity.IntIdentifier(sc.dashboardGuardianMock.User.GetID())
require.NoError(t, err)
assert.Equal(t, "", sc.dashboardGuardianMock.DashUID)
@ -139,7 +139,7 @@ func TestIntegrationIntegratedDashboardService(t *testing.T) {
err := callSaveWithError(t, cmd, sc.sqlStore)
require.Equal(t, dashboards.ErrDashboardUpdateAccessDenied, err)
userID, err := identity.IntIdentifier(sc.dashboardGuardianMock.User.GetTypedID())
userID, err := identity.IntIdentifier(sc.dashboardGuardianMock.User.GetID())
require.NoError(t, err)
assert.Equal(t, sc.otherSavedFolder.ID, sc.dashboardGuardianMock.DashID)
@ -162,7 +162,7 @@ func TestIntegrationIntegratedDashboardService(t *testing.T) {
err := callSaveWithError(t, cmd, sc.sqlStore)
require.Equal(t, dashboards.ErrDashboardUpdateAccessDenied, err)
userID, err := identity.IntIdentifier(sc.dashboardGuardianMock.User.GetTypedID())
userID, err := identity.IntIdentifier(sc.dashboardGuardianMock.User.GetID())
require.NoError(t, err)
assert.Equal(t, sc.savedDashInFolder.UID, sc.dashboardGuardianMock.DashUID)
@ -186,7 +186,7 @@ func TestIntegrationIntegratedDashboardService(t *testing.T) {
err := callSaveWithError(t, cmd, sc.sqlStore)
require.Equal(t, dashboards.ErrDashboardUpdateAccessDenied, err)
userID, err := identity.IntIdentifier(sc.dashboardGuardianMock.User.GetTypedID())
userID, err := identity.IntIdentifier(sc.dashboardGuardianMock.User.GetID())
require.NoError(t, err)
assert.Equal(t, sc.savedDashInFolder.UID, sc.dashboardGuardianMock.DashUID)
@ -210,7 +210,7 @@ func TestIntegrationIntegratedDashboardService(t *testing.T) {
err := callSaveWithError(t, cmd, sc.sqlStore)
assert.Equal(t, dashboards.ErrDashboardUpdateAccessDenied, err)
userID, err := identity.IntIdentifier(sc.dashboardGuardianMock.User.GetTypedID())
userID, err := identity.IntIdentifier(sc.dashboardGuardianMock.User.GetID())
require.NoError(t, err)
assert.Equal(t, sc.savedDashInGeneralFolder.UID, sc.dashboardGuardianMock.DashUID)
@ -234,7 +234,7 @@ func TestIntegrationIntegratedDashboardService(t *testing.T) {
err := callSaveWithError(t, cmd, sc.sqlStore)
require.Equal(t, dashboards.ErrDashboardUpdateAccessDenied, err)
userID, err := identity.IntIdentifier(sc.dashboardGuardianMock.User.GetTypedID())
userID, err := identity.IntIdentifier(sc.dashboardGuardianMock.User.GetID())
require.NoError(t, err)
assert.Equal(t, sc.savedDashInFolder.UID, sc.dashboardGuardianMock.DashUID)
@ -258,7 +258,7 @@ func TestIntegrationIntegratedDashboardService(t *testing.T) {
err := callSaveWithError(t, cmd, sc.sqlStore)
require.Equal(t, dashboards.ErrDashboardUpdateAccessDenied, err)
userID, err := identity.IntIdentifier(sc.dashboardGuardianMock.User.GetTypedID())
userID, err := identity.IntIdentifier(sc.dashboardGuardianMock.User.GetID())
require.NoError(t, err)
assert.Equal(t, sc.savedDashInGeneralFolder.UID, sc.dashboardGuardianMock.DashUID)
@ -282,7 +282,7 @@ func TestIntegrationIntegratedDashboardService(t *testing.T) {
err := callSaveWithError(t, cmd, sc.sqlStore)
assert.Equal(t, dashboards.ErrDashboardUpdateAccessDenied, err)
userID, err := identity.IntIdentifier(sc.dashboardGuardianMock.User.GetTypedID())
userID, err := identity.IntIdentifier(sc.dashboardGuardianMock.User.GetID())
require.NoError(t, err)
assert.Equal(t, sc.savedDashInFolder.UID, sc.dashboardGuardianMock.DashUID)
@ -306,7 +306,7 @@ func TestIntegrationIntegratedDashboardService(t *testing.T) {
err := callSaveWithError(t, cmd, sc.sqlStore)
require.Equal(t, dashboards.ErrDashboardUpdateAccessDenied, err)
userID, err := identity.IntIdentifier(sc.dashboardGuardianMock.User.GetTypedID())
userID, err := identity.IntIdentifier(sc.dashboardGuardianMock.User.GetID())
require.NoError(t, err)
assert.Equal(t, sc.savedDashInGeneralFolder.UID, sc.dashboardGuardianMock.DashUID)
@ -330,7 +330,7 @@ func TestIntegrationIntegratedDashboardService(t *testing.T) {
err := callSaveWithError(t, cmd, sc.sqlStore)
require.Equal(t, dashboards.ErrDashboardUpdateAccessDenied, err)
userID, err := identity.IntIdentifier(sc.dashboardGuardianMock.User.GetTypedID())
userID, err := identity.IntIdentifier(sc.dashboardGuardianMock.User.GetID())
require.NoError(t, err)
assert.Equal(t, sc.savedDashInFolder.UID, sc.dashboardGuardianMock.DashUID)

@ -122,12 +122,10 @@ func (d *DashboardSnapshotStore) SearchDashboardSnapshots(ctx context.Context, q
sess.Where("name LIKE ?", query.Name)
}
namespace, id := query.SignedInUser.GetTypedID()
var userID int64
if namespace == identity.TypeServiceAccount || namespace == identity.TypeUser {
if identity.IsIdentityType(query.SignedInUser.GetID(), identity.TypeUser, identity.TypeServiceAccount) {
var err error
userID, err = identity.IntIdentifier(namespace, id)
userID, err = identity.UserIdentifier(query.SignedInUser.GetID())
if err != nil {
return err
}
@ -137,7 +135,7 @@ func (d *DashboardSnapshotStore) SearchDashboardSnapshots(ctx context.Context, q
switch {
case query.SignedInUser.GetOrgRole() == org.RoleAdmin:
sess.Where("org_id = ?", query.SignedInUser.GetOrgID())
case namespace != identity.TypeAnonymous:
case userID != 0:
sess.Where("org_id = ? AND user_id = ?", query.OrgID, userID)
default:
queryResult = snapshots

@ -63,17 +63,10 @@ func CreateDashboardSnapshot(c *contextmodel.ReqContext, cfg dashboardsnapshot.S
cmd.DashboardCreateCommand.Name = "Unnamed snapshot"
}
userID, err := identity.UserIdentifier(user.GetTypedID())
if err != nil {
c.JsonApiErr(http.StatusInternalServerError,
"Failed to create external snapshot", err)
return
}
var snapshotUrl string
cmd.ExternalURL = ""
cmd.OrgID = user.GetOrgID()
cmd.UserID = userID
cmd.UserID, _ = identity.UserIdentifier(user.GetID())
originalDashboardURL, err := createOriginalDashboardURL(&cmd)
if err != nil {
c.JsonApiErr(http.StatusInternalServerError, "Invalid app URL", err)

@ -592,21 +592,17 @@ func (s *Service) Create(ctx context.Context, cmd *folder.CreateFolderCommand) (
user := cmd.SignedInUser
userID := int64(0)
var err error
namespaceID, userIDstr := user.GetTypedID()
if namespaceID != identity.TypeUser && namespaceID != identity.TypeServiceAccount {
s.log.Debug("User does not belong to a user or service account namespace, using 0 as user ID", "namespaceID", namespaceID, "userID", userIDstr)
var userID int64
if id, err := identity.UserIdentifier(cmd.SignedInUser.GetID()); err == nil {
userID = id
} else {
userID, err = identity.IntIdentifier(namespaceID, userIDstr)
if err != nil {
s.log.Debug("failed to parse user ID", "namespaceID", namespaceID, "userID", userIDstr, "error", err)
}
s.log.Warn("User does not belong to a user or service account namespace, using 0 as user ID", "id", cmd.SignedInUser.GetID())
}
if userID == 0 {
userID = -1
}
dashFolder.CreatedBy = userID
dashFolder.UpdatedBy = userID
dashFolder.UpdateSlug()
@ -682,8 +678,6 @@ func (s *Service) Update(ctx context.Context, cmd *folder.UpdateFolderCommand) (
}
if cmd.NewTitle != nil {
namespace, id := cmd.SignedInUser.GetTypedID()
metrics.MFolderIDsServiceCount.WithLabelValues(metrics.Folder).Inc()
if err := s.bus.Publish(ctx, &events.FolderTitleUpdated{
Timestamp: foldr.Updated,
@ -692,7 +686,7 @@ func (s *Service) Update(ctx context.Context, cmd *folder.UpdateFolderCommand) (
UID: dashFolder.UID,
OrgID: cmd.OrgID,
}); err != nil {
s.log.ErrorContext(ctx, "failed to publish FolderTitleUpdated event", "folder", foldr.Title, "user", id, "namespace", namespace, "error", err)
s.log.ErrorContext(ctx, "failed to publish FolderTitleUpdated event", "folder", foldr.Title, "user", cmd.SignedInUser.GetID(), "error", err)
return err
}
}
@ -739,12 +733,10 @@ func (s *Service) legacyUpdate(ctx context.Context, cmd *folder.UpdateFolderComm
}
var userID int64
namespace, id := cmd.SignedInUser.GetTypedID()
if namespace == identity.TypeUser || namespace == identity.TypeServiceAccount {
userID, err = identity.IntIdentifier(namespace, id)
if err != nil {
s.log.ErrorContext(ctx, "failed to parse user ID", "namespace", namespace, "userID", id, "error", err)
}
if id, err := identity.UserIdentifier(cmd.SignedInUser.GetID()); err == nil {
userID = id
} else {
s.log.Warn("User does not belong to a user or service account namespace, using 0 as user ID", "id", cmd.SignedInUser.GetID())
}
prepareForUpdate(dashFolder, cmd.OrgID, userID, cmd)
@ -1163,15 +1155,11 @@ func (s *Service) buildSaveDashboardCommand(ctx context.Context, dto *dashboards
}
}
userID := int64(0)
namespaceID, userIDstr := dto.User.GetTypedID()
if namespaceID != identity.TypeUser && namespaceID != identity.TypeServiceAccount {
s.log.Warn("User does not belong to a user or service account namespace, using 0 as user ID", "namespaceID", namespaceID, "userID", userIDstr)
var userID int64
if id, err := identity.UserIdentifier(dto.User.GetID()); err == nil {
userID = id
} else {
userID, err = identity.IntIdentifier(namespaceID, userIDstr)
if err != nil {
s.log.Warn("failed to parse user ID", "namespaceID", namespaceID, "userID", userIDstr, "error", err)
}
s.log.Warn("User does not belong to a user or service account namespace, using 0 as user ID", "id", dto.User.GetID())
}
metrics.MFolderIDsServiceCount.WithLabelValues(metrics.Folder).Inc()

@ -309,13 +309,12 @@ func (a *accessControlFolderGuardian) CanCreate(folderID int64, isFolder bool) (
func (a *accessControlDashboardGuardian) evaluate(evaluator accesscontrol.Evaluator) (bool, error) {
ok, err := a.ac.Evaluate(a.ctx, a.user, evaluator)
namespaceID, userID := a.user.GetTypedID()
if err != nil {
id := 0
if a.dashboard != nil {
id = int(a.dashboard.ID)
}
a.log.Debug("Failed to evaluate access control to dashboard", "error", err, "namespaceID", namespaceID, "userId", userID, "id", id)
a.log.Debug("Failed to evaluate access control to dashboard", "error", err, "identity", a.user.GetID(), "id", id)
}
if !ok && err == nil {
@ -323,7 +322,7 @@ func (a *accessControlDashboardGuardian) evaluate(evaluator accesscontrol.Evalua
if a.dashboard != nil {
id = int(a.dashboard.ID)
}
a.log.Debug("Access denied to dashboard", "namespaceID", namespaceID, "userId", userID, "id", id, "permissions", evaluator.GoString())
a.log.Debug("Access denied to dashboard", "identity", a.user.GetID(), "id", id, "permissions", evaluator.GoString())
}
return ok, err
@ -331,7 +330,6 @@ func (a *accessControlDashboardGuardian) evaluate(evaluator accesscontrol.Evalua
func (a *accessControlFolderGuardian) evaluate(evaluator accesscontrol.Evaluator) (bool, error) {
ok, err := a.ac.Evaluate(a.ctx, a.user, evaluator)
namespaceID, userID := a.user.GetTypedID()
if err != nil {
uid := ""
orgID := 0
@ -339,7 +337,7 @@ func (a *accessControlFolderGuardian) evaluate(evaluator accesscontrol.Evaluator
uid = a.folder.UID
orgID = int(a.folder.OrgID)
}
a.log.Debug("Failed to evaluate access control to folder", "error", err, "namespaceID", namespaceID, "userId", userID, "orgID", orgID, "uid", uid)
a.log.Debug("Failed to evaluate access control to folder", "error", err, "identity", a.user.GetID(), "orgID", orgID, "uid", uid)
}
if !ok && err == nil {
@ -349,7 +347,7 @@ func (a *accessControlFolderGuardian) evaluate(evaluator accesscontrol.Evaluator
uid = a.folder.UID
orgID = int(a.folder.OrgID)
}
a.log.Debug("Access denied to folder", "namespaceID", namespaceID, "userId", userID, "orgID", orgID, "uid", uid, "permissions", evaluator.GoString())
a.log.Debug("Access denied to folder", "identity", a.user.GetID(), "identity", a.user.GetID(), "orgID", orgID, "uid", uid, "permissions", evaluator.GoString())
}
return ok, err

@ -138,13 +138,9 @@ func (l *LibraryElementService) createLibraryElement(c context.Context, signedIn
}
}
userID := int64(0)
namespaceID, identifier := signedInUser.GetTypedID()
if namespaceID == identity.TypeUser || namespaceID == identity.TypeServiceAccount {
userID, err = identity.IntIdentifier(namespaceID, identifier)
if err != nil {
l.log.Warn("Error while parsing userID", "namespaceID", namespaceID, "userID", identifier)
}
var userID int64
if id, err := identity.UserIdentifier(signedInUser.GetID()); err == nil {
userID = id
}
metrics.MFolderIDsServiceCount.WithLabelValues(metrics.LibraryElements).Inc()
@ -593,13 +589,8 @@ func (l *LibraryElementService) patchLibraryElement(c context.Context, signedInU
}
var userID int64
namespaceID, identifier := signedInUser.GetTypedID()
if namespaceID == identity.TypeUser || namespaceID == identity.TypeServiceAccount {
var errID error
userID, errID = identity.IntIdentifier(namespaceID, identifier)
if errID != nil {
l.log.Warn("Error while parsing userID", "namespaceID", namespaceID, "userID", identifier, "err", errID)
}
if id, err := identity.UserIdentifier(signedInUser.GetID()); err == nil {
userID = id
}
metrics.MFolderIDsServiceCount.WithLabelValues(metrics.LibraryElements).Inc()
@ -800,13 +791,9 @@ func (l *LibraryElementService) connectElementsToDashboardID(c context.Context,
return err
}
namespaceID, identifier := signedInUser.GetTypedID()
userID := int64(0)
if namespaceID == identity.TypeUser || namespaceID == identity.TypeServiceAccount {
userID, err = identity.IntIdentifier(namespaceID, identifier)
if err != nil {
l.log.Warn("Failed to parse user ID from namespace identifier", "namespace", namespaceID, "identifier", identifier, "error", err)
}
var userID int64
if id, err := identity.UserIdentifier(signedInUser.GetID()); err == nil {
userID = id
}
connection := model.LibraryElementConnection{

@ -284,11 +284,9 @@ func ProvideService(plugCtxProvider *plugincontext.Provider, cfg *setting.Cfg, r
g.websocketHandler = func(ctx *contextmodel.ReqContext) {
user := ctx.SignedInUser
_, identifier := user.GetTypedID()
// Centrifuge expects Credentials in context with a current user ID.
cred := &centrifuge.Credentials{
UserID: identifier,
UserID: user.GetID().ID(),
}
newCtx := centrifuge.SetCredentials(ctx.Req.Context(), cred)
newCtx = livecontext.SetContextSignedUser(newCtx, user)
@ -955,8 +953,7 @@ func (g *GrafanaLive) HandleHTTPPublish(ctx *contextmodel.ReqContext) response.R
return response.Error(http.StatusBadRequest, "invalid channel ID", nil)
}
namespaceID, userID := ctx.SignedInUser.GetTypedID()
logger.Debug("Publish API cmd", "namespaceID", namespaceID, "userID", userID, "channel", cmd.Channel)
logger.Debug("Publish API cmd", "identity", ctx.SignedInUser.GetID(), "channel", cmd.Channel)
user := ctx.SignedInUser
channel := cmd.Channel
@ -1013,7 +1010,7 @@ func (g *GrafanaLive) HandleHTTPPublish(ctx *contextmodel.ReqContext) response.R
return response.Error(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError), nil)
}
}
logger.Debug("Publication successful", "namespaceID", namespaceID, "userID", userID, "channel", cmd.Channel)
logger.Debug("Publication successful", "identity", ctx.SignedInUser.GetID(), "channel", cmd.Channel)
return response.JSON(http.StatusOK, dtos.LivePublishResponse{})
}

@ -73,7 +73,7 @@ func TestStreamManager_SubmitStream_Send(t *testing.T) {
}
mockContextGetter.EXPECT().GetPluginContext(context.Background(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(func(ctx context.Context, user identity.Requester, pluginID string, datasourceUID string, skipCache bool) (backend.PluginContext, bool, error) {
userID, err := identity.IntIdentifier(user.GetTypedID())
userID, err := identity.IntIdentifier(user.GetID())
require.NoError(t, err)
require.Equal(t, int64(2), userID)
require.Equal(t, int64(1), user.GetOrgID())
@ -258,7 +258,7 @@ func TestStreamManager_SubmitStream_ErrorRestartsRunStream(t *testing.T) {
}
mockContextGetter.EXPECT().GetPluginContext(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(func(ctx context.Context, user identity.Requester, pluginID string, datasourceUID string, skipCache bool) (backend.PluginContext, bool, error) {
userID, err := identity.IntIdentifier(user.GetTypedID())
userID, err := identity.IntIdentifier(user.GetID())
require.NoError(t, err)
require.Equal(t, int64(2), userID)
require.Equal(t, int64(1), user.GetOrgID())
@ -343,7 +343,7 @@ func TestStreamManager_HandleDatasourceUpdate(t *testing.T) {
}
mockContextGetter.EXPECT().GetPluginContext(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(func(ctx context.Context, user identity.Requester, pluginID string, datasourceUID string, skipCache bool) (backend.PluginContext, bool, error) {
userID, err := identity.IntIdentifier(user.GetTypedID())
userID, err := identity.IntIdentifier(user.GetID())
require.NoError(t, err)
require.Equal(t, int64(2), userID)
@ -412,7 +412,7 @@ func TestStreamManager_HandleDatasourceDelete(t *testing.T) {
}
mockContextGetter.EXPECT().GetPluginContext(context.Background(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(func(ctx context.Context, user identity.Requester, pluginID string, datasourceUID string, skipCache bool) (backend.PluginContext, bool, error) {
userID, err := identity.IntIdentifier(user.GetTypedID())
userID, err := identity.IntIdentifier(user.GetID())
require.NoError(t, err)
require.Equal(t, int64(2), userID)
require.Equal(t, int64(1), user.GetOrgID())

@ -297,7 +297,7 @@ func (s *ServiceImpl) getProfileNode(c *contextmodel.ReqContext) *navtree.NavLin
func (s *ServiceImpl) buildStarredItemsNavLinks(c *contextmodel.ReqContext) ([]*navtree.NavLink, error) {
starredItemsChildNavs := []*navtree.NavLink{}
userID, _ := identity.UserIdentifier(c.SignedInUser.GetTypedID())
userID, _ := identity.UserIdentifier(c.SignedInUser.GetID())
query := star.GetUserStarsQuery{
UserID: userID,
}

@ -76,9 +76,9 @@ func (srv RulerSrv) RouteDeleteAlertRules(c *contextmodel.ReqContext, namespaceU
return toNamespaceErrorResponse(err)
}
userNamespace, id := c.SignedInUser.GetTypedID()
userNamespace, id := c.SignedInUser.GetID().Type(), c.SignedInUser.GetID().ID()
var loggerCtx = []any{
"userId",
"identity",
id,
"userNamespace",
userNamespace,
@ -283,7 +283,7 @@ func (srv RulerSrv) RouteGetRulesConfig(c *contextmodel.ReqContext) response.Res
for groupKey, rules := range configs {
folder, ok := namespaceMap[groupKey.NamespaceUID]
if !ok {
userNamespace, id := c.SignedInUser.GetTypedID()
userNamespace, id := c.SignedInUser.GetID().Type(), c.SignedInUser.GetID().ID()
srv.log.Error("Namespace not visible to the user", "user", id, "userNamespace", userNamespace, "namespace", groupKey.NamespaceUID)
continue
}
@ -359,7 +359,7 @@ func (srv RulerSrv) updateAlertRulesInGroup(c *contextmodel.ReqContext, groupKey
var finalChanges *store.GroupDelta
var dbConfig *ngmodels.AlertConfiguration
err := srv.xactManager.InTransaction(c.Req.Context(), func(tranCtx context.Context) error {
userNamespace, id := c.SignedInUser.GetTypedID()
userNamespace, id := c.SignedInUser.GetID().Type(), c.SignedInUser.GetID().ID()
logger := srv.log.New("namespace_uid", groupKey.NamespaceUID, "group",
groupKey.RuleGroup, "org_id", groupKey.OrgID, "user_id", id, "userNamespace", userNamespace)
groupChanges, err := store.CalculateChanges(tranCtx, srv.store, groupKey, rules)
@ -454,7 +454,7 @@ func (srv RulerSrv) updateAlertRulesInGroup(c *contextmodel.ReqContext, groupKey
}
if len(finalChanges.New) > 0 {
userID, _ := identity.UserIdentifier(c.SignedInUser.GetTypedID())
userID, _ := identity.UserIdentifier(c.SignedInUser.GetID())
limitReached, err := srv.QuotaService.CheckQuotaReached(tranCtx, ngmodels.QuotaTargetSrv, &quota.ScopeParameters{
OrgID: c.SignedInUser.GetOrgID(),
UserID: userID,

@ -659,12 +659,10 @@ func (service *AlertRuleService) DeleteAlertRule(ctx context.Context, user ident
// checkLimitsTransactionCtx checks whether the current transaction (as identified by the ctx) breaches configured alert rule limits.
func (service *AlertRuleService) checkLimitsTransactionCtx(ctx context.Context, user identity.Requester) error {
// default to 0 if there is no user
userID := int64(0)
u, err := identity.UserIdentifier(user.GetTypedID())
if err != nil {
return fmt.Errorf("failed to check alert rule quota: %w", err)
var userID int64
if id, err := identity.UserIdentifier(user.GetID()); err == nil {
userID = id
}
userID = u
limitReached, err := service.quotas.CheckQuotaReached(ctx, models.QuotaTargetSrv, &quota.ScopeParameters{
OrgID: user.GetOrgID(),

@ -94,17 +94,14 @@ func (o *Service) HasOAuthEntry(ctx context.Context, usr identity.Requester) (*l
return nil, false, nil
}
namespace, id := usr.GetTypedID()
if namespace != identity.TypeUser {
// Not a user, therefore no token.
if !identity.IsIdentityType(usr.GetID(), identity.TypeUser) {
return nil, false, nil
}
ctxLogger := logger.FromContext(ctx)
userID, err := identity.IntIdentifier(namespace, id)
userID, err := identity.UserIdentifier(usr.GetID())
if err != nil {
ctxLogger.Error("Failed to convert user id to int", "namespace", namespace, "userID", id, "error", err)
ctxLogger.Error("Failed to convert user id to int", "id", usr.GetID(), "error", err)
return nil, false, err
}
@ -130,24 +127,22 @@ func (o *Service) HasOAuthEntry(ctx context.Context, usr identity.Requester) (*l
// TryTokenRefresh returns an error in case the OAuth token refresh was unsuccessful
// It uses a singleflight.Group to prevent getting the Refresh Token multiple times for a given User
func (o *Service) TryTokenRefresh(ctx context.Context, usr identity.Requester) error {
ctxLogger := logger.FromContext(ctx)
if usr == nil || usr.IsNil() {
logger.Warn("Can only refresh OAuth tokens for existing users", "user", "nil")
ctxLogger.Warn("Can only refresh OAuth tokens for existing users", "user", "nil")
// Not user, no token.
return nil
}
namespace, id := usr.GetTypedID()
if namespace != identity.TypeUser {
// Not a user, therefore no token.
logger.Warn("Can only refresh OAuth tokens for users", "namespace", namespace, "userId", id)
if !identity.IsIdentityType(usr.GetID(), identity.TypeUser) {
ctxLogger.Warn("Can only refresh OAuth tokens for users", "id", usr.GetID())
return nil
}
ctxLogger := logger.FromContext(ctx)
userID, err := identity.IntIdentifier(namespace, id)
userID, err := identity.UserIdentifier(usr.GetID())
if err != nil {
ctxLogger.Warn("Failed to convert user id to int", "namespace", namespace, "userId", id, "error", err)
ctxLogger.Warn("Failed to convert user id to int", "id", usr.GetID(), "error", err)
return nil
}

@ -35,8 +35,7 @@ func (m *UserHeaderMiddleware) applyUserHeader(ctx context.Context, h backend.Fo
}
h.DeleteHTTPHeader(proxyutil.UserHeaderName)
namespace, _ := reqCtx.SignedInUser.GetTypedID()
if namespace != identity.TypeAnonymous {
if !identity.IsIdentityType(reqCtx.SignedInUser.GetID(), identity.TypeAnonymous) {
h.SetHTTPHeader(proxyutil.UserHeaderName, reqCtx.SignedInUser.GetLogin())
}
}

@ -99,8 +99,7 @@ func (api *ServiceAccountsAPI) CreateServiceAccount(c *contextmodel.ReqContext)
}
if api.cfg.RBAC.PermissionsOnCreation("service-account") {
t, _ := c.SignedInUser.GetTypedID()
if t == identity.TypeUser {
if identity.IsIdentityType(c.SignedInUser.GetID(), identity.TypeUser) {
userID, err := c.SignedInUser.GetID().ParseInt()
if err != nil {
return response.Error(http.StatusInternalServerError, "Failed to parse user id", err)

@ -165,10 +165,9 @@ func (f *accessControlDashboardPermissionFilter) buildClauses() {
dashWildcards := accesscontrol.WildcardsFromPrefix(dashboards.ScopeDashboardsPrefix)
folderWildcards := accesscontrol.WildcardsFromPrefix(dashboards.ScopeFoldersPrefix)
userID := int64(0)
namespace, identifier := f.user.GetTypedID()
if namespace == identity.TypeUser || namespace == identity.TypeServiceAccount {
userID, _ = identity.IntIdentifier(namespace, identifier)
var userID int64
if id, err := identity.UserIdentifier(f.user.GetID()); err == nil {
userID = id
}
orgID := f.user.GetOrgID()

@ -33,10 +33,9 @@ func (f *accessControlDashboardPermissionFilterNoFolderSubquery) buildClauses()
dashWildcards := accesscontrol.WildcardsFromPrefix(dashboards.ScopeDashboardsPrefix)
folderWildcards := accesscontrol.WildcardsFromPrefix(dashboards.ScopeFoldersPrefix)
userID := int64(0)
namespace, identifier := f.user.GetTypedID()
if namespace == identity.TypeUser || namespace == identity.TypeServiceAccount {
userID, _ = identity.IntIdentifier(namespace, identifier)
var userID int64
if id, err := identity.UserIdentifier(f.user.GetID()); err == nil {
userID = id
}
orgID := f.user.GetOrgID()

@ -47,14 +47,9 @@ func (api *API) getDashboardHelper(ctx context.Context, orgID int64, id int64, u
}
func (api *API) GetStars(c *contextmodel.ReqContext) response.Response {
namespace, identifier := c.SignedInUser.GetTypedID()
if namespace != identity.TypeUser && namespace != identity.TypeServiceAccount {
return response.Error(http.StatusBadRequest, "Only users and service accounts can star dashboards", nil)
}
userID, err := identity.IntIdentifier(namespace, identifier)
userID, err := identity.UserIdentifier(c.SignedInUser.GetID())
if err != nil {
return response.Error(http.StatusInternalServerError, "Invalid user ID", err)
return response.Error(http.StatusBadRequest, "Only users and service accounts get starred dashboards", nil)
}
query := star.GetUserStarsQuery{
@ -101,17 +96,12 @@ func (api *API) GetStars(c *contextmodel.ReqContext) response.Response {
// 403: forbiddenError
// 500: internalServerError
func (api *API) StarDashboard(c *contextmodel.ReqContext) response.Response {
namespace, identifier := c.SignedInUser.GetTypedID()
if namespace != identity.TypeUser && namespace != identity.TypeServiceAccount {
userID, err := identity.UserIdentifier(c.SignedInUser.GetID())
if err != nil {
return response.Error(http.StatusBadRequest, "Only users and service accounts can star dashboards", nil)
}
userID, err := identity.IntIdentifier(namespace, identifier)
if err != nil {
return response.Error(http.StatusInternalServerError, "Invalid user ID", err)
}
idString := web.Params(c.Req)[":id"]
id, err := strconv.ParseInt(idString, 10, 64)
id, err := strconv.ParseInt(web.Params(c.Req)[":id"], 10, 64)
if err != nil {
return response.Error(http.StatusBadRequest, "Invalid dashboard ID", nil)
}
@ -146,18 +136,12 @@ func (api *API) StarDashboardByUID(c *contextmodel.ReqContext) response.Response
return response.Error(http.StatusBadRequest, "Invalid dashboard UID", nil)
}
namespace, identifier := c.SignedInUser.GetTypedID()
if namespace != identity.TypeUser && namespace != identity.TypeServiceAccount {
return response.Error(http.StatusBadRequest, "Only users and service accounts can star dashboards", nil)
}
userID, err := identity.IntIdentifier(namespace, identifier)
userID, err := identity.UserIdentifier(c.SignedInUser.GetID())
if err != nil {
return response.Error(http.StatusInternalServerError, "Invalid user ID", err)
return response.Error(http.StatusBadRequest, "Only users and service accounts can star dashboards", nil)
}
dash, rsp := api.getDashboardHelper(c.Req.Context(), c.SignedInUser.GetOrgID(), 0, uid)
if rsp != nil {
return rsp
}
@ -193,14 +177,9 @@ func (api *API) UnstarDashboard(c *contextmodel.ReqContext) response.Response {
return response.Error(http.StatusBadRequest, "Invalid dashboard ID", nil)
}
namespace, identifier := c.SignedInUser.GetTypedID()
if namespace != identity.TypeUser && namespace != identity.TypeServiceAccount {
return response.Error(http.StatusBadRequest, "Only users and service accounts can star dashboards", nil)
}
userID, err := identity.IntIdentifier(namespace, identifier)
userID, err := identity.UserIdentifier(c.SignedInUser.GetID())
if err != nil {
return response.Error(http.StatusInternalServerError, "Invalid user ID", err)
return response.Error(http.StatusBadRequest, "Only users and service accounts can star dashboards", nil)
}
cmd := star.UnstarDashboardCommand{UserID: userID, DashboardID: id}
@ -233,14 +212,9 @@ func (api *API) UnstarDashboardByUID(c *contextmodel.ReqContext) response.Respon
return response.Error(http.StatusBadRequest, "Invalid dashboard UID", nil)
}
namespace, identifier := c.SignedInUser.GetTypedID()
if namespace != identity.TypeUser && namespace != identity.TypeServiceAccount {
return response.Error(http.StatusBadRequest, "Only users and service accounts can star dashboards", nil)
}
userID, err := identity.IntIdentifier(namespace, identifier)
userID, err := identity.UserIdentifier(c.SignedInUser.GetID())
if err != nil {
return response.Error(http.StatusInternalServerError, "Invalid user ID", err)
return response.Error(http.StatusBadRequest, "Only users and service accounts can star dashboards", nil)
}
dash, rsp := api.getDashboardHelper(c.Req.Context(), c.SignedInUser.GetOrgID(), 0, uid)

@ -49,7 +49,7 @@ func (tapi *TeamAPI) createTeam(c *contextmodel.ReqContext) response.Response {
// if the request is authenticated using API tokens
// the SignedInUser is an empty struct therefore
// an additional check whether it is an actual user is required
namespace, identifier := c.SignedInUser.GetTypedID()
namespace, identifier := c.SignedInUser.GetID().Type(), c.SignedInUser.GetID().ID()
switch namespace {
case identity.TypeUser:
userID, err := strconv.ParseInt(identifier, 10, 64)

@ -169,7 +169,7 @@ func (u *SignedInUser) GetAllowedKubernetesNamespace() string {
// GetCacheKey returns a unique key for the entity.
// Add an extra prefix to avoid collisions with other caches
func (u *SignedInUser) GetCacheKey() string {
namespace, id := u.GetTypedID()
typ, id := u.GetID().Type(), u.GetID().ID()
if !u.HasUniqueId() {
// Hack use the org role as id for identities that do not have a unique id
// e.g. anonymous and render key.
@ -181,7 +181,7 @@ func (u *SignedInUser) GetCacheKey() string {
id = string(orgRole)
}
return fmt.Sprintf("%d-%s-%s", u.GetOrgID(), namespace, id)
return fmt.Sprintf("%d-%s-%s", u.GetOrgID(), typ, id)
}
// GetIsGrafanaAdmin returns true if the user is a server admin
@ -245,13 +245,11 @@ func (u *SignedInUser) GetOrgRole() identity.RoleType {
// GetID returns namespaced id for the entity
func (u *SignedInUser) GetID() identity.TypedID {
ns, id := u.GetTypedID()
ns, id := u.getTypeAndID()
return identity.NewTypedIDString(ns, id)
}
// GetTypedID returns the namespace and ID of the active entity
// The namespace is one of the constants defined in pkg/apimachinery/identity
func (u *SignedInUser) GetTypedID() (identity.IdentityType, string) {
func (u *SignedInUser) getTypeAndID() (identity.IdentityType, string) {
switch {
case u.ApiKeyID != 0:
return identity.TypeAPIKey, strconv.FormatInt(u.ApiKeyID, 10)

@ -114,8 +114,7 @@ func ApplyUserHeader(sendUserHeader bool, req *http.Request, user identity.Reque
return
}
namespace, _ := user.GetTypedID()
if namespace == identity.TypeUser || namespace == identity.TypeServiceAccount {
if identity.IsIdentityType(user.GetID(), identity.TypeUser) {
req.Header.Set(UserHeaderName, user.GetLogin())
}
}

Loading…
Cancel
Save