mirror of
https://github.com/SigNoz/signoz.git
synced 2026-03-26 22:20:24 +00:00
* feat: introduce user_role table * fix: golint and register migrations * fix: user types and order of update user * feat: add migration to drop role column from users table * fix: raw queries pointing to role column in users table * chore: remove storable user struct and minor other changes * chore: remove refs of calling vars as storable users * chore: user 0th role instead of highest * chore: address pr comments * chore: rename userrolestore to user_role_store * chore: return userroles with user in getter where possible * chore: move user module as user setter * chore: arrange getter and setter methods * fix: nil pointer for update user in integration test due to half payload being passed * chore: update openapi specs * fix: nil errors without making frontend changes * fix: empty array check everywhere for user roles array and minor other changes * fix: imports * fix: rebase changes * chore: renaming functions * chore: simplified getorcreateuser user setter method and call sites * fix: golint * fix: remove redundant authz migration, remove fk enforcement for drop migration * fix: add new event for user activation
185 lines
5.7 KiB
Go
185 lines
5.7 KiB
Go
package impluser
|
|
|
|
import (
|
|
"context"
|
|
"slices"
|
|
|
|
"github.com/SigNoz/signoz/pkg/errors"
|
|
"github.com/SigNoz/signoz/pkg/flagger"
|
|
"github.com/SigNoz/signoz/pkg/modules/user"
|
|
"github.com/SigNoz/signoz/pkg/types"
|
|
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
|
"github.com/SigNoz/signoz/pkg/types/featuretypes"
|
|
"github.com/SigNoz/signoz/pkg/valuer"
|
|
)
|
|
|
|
type getter struct {
|
|
store types.UserStore
|
|
userRoleStore authtypes.UserRoleStore
|
|
flagger flagger.Flagger
|
|
}
|
|
|
|
func NewGetter(store types.UserStore, userRoleStore authtypes.UserRoleStore, flagger flagger.Flagger) user.Getter {
|
|
return &getter{store: store, userRoleStore: userRoleStore, flagger: flagger}
|
|
}
|
|
|
|
func (module *getter) GetRootUserByOrgID(ctx context.Context, orgID valuer.UUID) (*types.User, []*authtypes.UserRole, error) {
|
|
rootUser, err := module.store.GetRootUserByOrgID(ctx, orgID)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
userRoles, err := module.userRoleStore.GetUserRolesByUserID(ctx, rootUser.ID)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
return rootUser, userRoles, nil
|
|
}
|
|
|
|
func (module *getter) ListByOrgID(ctx context.Context, orgID valuer.UUID) ([]*types.DeprecatedUser, error) {
|
|
users, err := module.store.ListUsersByOrgID(ctx, orgID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// filter root users if feature flag `hide_root_users` is true
|
|
evalCtx := featuretypes.NewFlaggerEvaluationContext(orgID)
|
|
hideRootUsers := module.flagger.BooleanOrEmpty(ctx, flagger.FeatureHideRootUser, evalCtx)
|
|
|
|
if hideRootUsers {
|
|
users = slices.DeleteFunc(users, func(user *types.User) bool { return user.IsRoot })
|
|
}
|
|
|
|
userIDs := make([]valuer.UUID, len(users))
|
|
for idx, user := range users {
|
|
userIDs[idx] = user.ID
|
|
}
|
|
|
|
userRoles, err := module.userRoleStore.ListUserRolesByOrgIDAndUserIDs(ctx, orgID, userIDs)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Build userID → role name mapping directly from the joined Role
|
|
userIDToRoleNames := make(map[valuer.UUID][]string)
|
|
for _, ur := range userRoles {
|
|
if ur.Role != nil {
|
|
userIDToRoleNames[ur.UserID] = append(userIDToRoleNames[ur.UserID], ur.Role.Name)
|
|
}
|
|
}
|
|
|
|
deprecatedUsers := make([]*types.DeprecatedUser, 0, len(users))
|
|
for _, user := range users {
|
|
roleNames := userIDToRoleNames[user.ID]
|
|
|
|
if len(roleNames) == 0 {
|
|
return nil, errors.Newf(errors.TypeUnexpected, authtypes.ErrCodeUserRolesNotFound, "no user roles entries found for user: %s", user.ID.String())
|
|
}
|
|
|
|
role := authtypes.SigNozManagedRoleToExistingLegacyRole[roleNames[0]]
|
|
deprecatedUsers = append(deprecatedUsers, types.NewDeprecatedUserFromUserAndRole(user, role))
|
|
}
|
|
|
|
return deprecatedUsers, nil
|
|
}
|
|
|
|
func (module *getter) GetDeprecatedUserByOrgIDAndID(ctx context.Context, orgID valuer.UUID, id valuer.UUID) (*types.DeprecatedUser, error) {
|
|
user, err := module.store.GetByOrgIDAndID(ctx, orgID, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
userRoles, err := module.GetUserRoles(ctx, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if len(userRoles) == 0 {
|
|
return nil, errors.New(errors.TypeUnexpected, authtypes.ErrCodeUserRolesNotFound, "no user roles entries found")
|
|
}
|
|
|
|
role := authtypes.SigNozManagedRoleToExistingLegacyRole[userRoles[0].Role.Name]
|
|
|
|
return types.NewDeprecatedUserFromUserAndRole(user, role), nil
|
|
}
|
|
|
|
func (module *getter) Get(ctx context.Context, id valuer.UUID) (*types.DeprecatedUser, error) {
|
|
user, err := module.store.GetUser(ctx, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
userRoles, err := module.GetUserRoles(ctx, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if len(userRoles) == 0 {
|
|
return nil, errors.New(errors.TypeUnexpected, authtypes.ErrCodeUserRolesNotFound, "no user roles entries found")
|
|
}
|
|
|
|
role := authtypes.SigNozManagedRoleToExistingLegacyRole[userRoles[0].Role.Name]
|
|
|
|
return types.NewDeprecatedUserFromUserAndRole(user, role), nil
|
|
}
|
|
|
|
func (module *getter) ListUsersByEmailAndOrgIDs(ctx context.Context, email valuer.Email, orgIDs []valuer.UUID) ([]*types.User, error) {
|
|
return module.store.ListUsersByEmailAndOrgIDs(ctx, email, orgIDs)
|
|
}
|
|
|
|
func (module *getter) CountByOrgID(ctx context.Context, orgID valuer.UUID) (int64, error) {
|
|
count, err := module.store.CountByOrgID(ctx, orgID)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
return count, nil
|
|
}
|
|
|
|
func (module *getter) CountByOrgIDAndStatuses(ctx context.Context, orgID valuer.UUID, statuses []string) (map[valuer.String]int64, error) {
|
|
counts, err := module.store.CountByOrgIDAndStatuses(ctx, orgID, statuses)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return counts, nil
|
|
}
|
|
|
|
func (module *getter) GetFactorPasswordByUserID(ctx context.Context, userID valuer.UUID) (*types.FactorPassword, error) {
|
|
factorPassword, err := module.store.GetPasswordByUserID(ctx, userID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return factorPassword, nil
|
|
}
|
|
|
|
// this function restricts that only one non-deleted user email can exist for an org ID, if found more, it throws an error
|
|
func (module *getter) GetNonDeletedUserByEmailAndOrgID(ctx context.Context, email valuer.Email, orgID valuer.UUID) (*types.User, error) {
|
|
existingUsers, err := module.store.GetNonDeletedUsersByEmailAndOrgID(ctx, email, orgID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if len(existingUsers) > 1 {
|
|
return nil, errors.Newf(errors.TypeInternal, errors.CodeInternal, "Multiple non-deleted users found for email %s in org_id: %s", email.StringValue(), orgID.StringValue())
|
|
}
|
|
|
|
if len(existingUsers) == 1 {
|
|
return existingUsers[0], nil
|
|
}
|
|
|
|
return nil, errors.Newf(errors.TypeNotFound, errors.CodeNotFound, "No non-deleted user found with email %s in org_id: %s", email.StringValue(), orgID.StringValue())
|
|
|
|
}
|
|
|
|
func (module *getter) GetUserRoles(ctx context.Context, userID valuer.UUID) ([]*authtypes.UserRole, error) {
|
|
userRoles, err := module.userRoleStore.GetUserRolesByUserID(ctx, userID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return userRoles, nil
|
|
}
|