mirror of
https://github.com/grafana/grafana.git
synced 2025-02-12 08:35:43 -06:00
701f6d5436
* UserService: update callers to use the UserService instead of calling sqlstore directly There is one major change hiding in this PR. UserService.Delete originally called a number of services to delete user-related records. I moved everything except the actual call to the user table, and moved those into the API. This was done to avoid dependencies cycles; many of our services depend on the user service, so the user service itself should have as few dependencies as possible.
342 lines
9.0 KiB
Go
342 lines
9.0 KiB
Go
package userimpl
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"time"
|
|
|
|
"github.com/grafana/grafana/pkg/models"
|
|
"github.com/grafana/grafana/pkg/services/org"
|
|
"github.com/grafana/grafana/pkg/services/sqlstore"
|
|
"github.com/grafana/grafana/pkg/services/sqlstore/db"
|
|
"github.com/grafana/grafana/pkg/services/user"
|
|
"github.com/grafana/grafana/pkg/setting"
|
|
"github.com/grafana/grafana/pkg/util"
|
|
)
|
|
|
|
type Service struct {
|
|
store store
|
|
orgService org.Service
|
|
// TODO remove sqlstore
|
|
sqlStore *sqlstore.SQLStore
|
|
cfg *setting.Cfg
|
|
}
|
|
|
|
func ProvideService(
|
|
db db.DB,
|
|
orgService org.Service,
|
|
cfg *setting.Cfg,
|
|
ss *sqlstore.SQLStore,
|
|
) user.Service {
|
|
store := ProvideStore(db, cfg)
|
|
return &Service{
|
|
store: &store,
|
|
orgService: orgService,
|
|
cfg: cfg,
|
|
sqlStore: ss,
|
|
}
|
|
}
|
|
|
|
func (s *Service) Create(ctx context.Context, cmd *user.CreateUserCommand) (*user.User, error) {
|
|
cmdOrg := org.GetOrgIDForNewUserCommand{
|
|
Email: cmd.Email,
|
|
Login: cmd.Login,
|
|
OrgID: cmd.OrgID,
|
|
OrgName: cmd.OrgName,
|
|
SkipOrgSetup: cmd.SkipOrgSetup,
|
|
}
|
|
orgID, err := s.orgService.GetIDForNewUser(ctx, cmdOrg)
|
|
cmd.OrgID = orgID
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if cmd.Email == "" {
|
|
cmd.Email = cmd.Login
|
|
}
|
|
usr := &user.User{
|
|
Login: cmd.Login,
|
|
Email: cmd.Email,
|
|
}
|
|
usr, err = s.store.Get(ctx, usr)
|
|
if err != nil && !errors.Is(err, user.ErrUserNotFound) {
|
|
return usr, err
|
|
}
|
|
|
|
// create user
|
|
usr = &user.User{
|
|
Email: cmd.Email,
|
|
Name: cmd.Name,
|
|
Login: cmd.Login,
|
|
Company: cmd.Company,
|
|
IsAdmin: cmd.IsAdmin,
|
|
IsDisabled: cmd.IsDisabled,
|
|
OrgID: cmd.OrgID,
|
|
EmailVerified: cmd.EmailVerified,
|
|
Created: time.Now(),
|
|
Updated: time.Now(),
|
|
LastSeenAt: time.Now().AddDate(-10, 0, 0),
|
|
IsServiceAccount: cmd.IsServiceAccount,
|
|
}
|
|
|
|
salt, err := util.GetRandomString(10)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
usr.Salt = salt
|
|
rands, err := util.GetRandomString(10)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
usr.Rands = rands
|
|
|
|
if len(cmd.Password) > 0 {
|
|
encodedPassword, err := util.EncodePassword(cmd.Password, usr.Salt)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
usr.Password = encodedPassword
|
|
}
|
|
|
|
userID, err := s.store.Insert(ctx, usr)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// create org user link
|
|
if !cmd.SkipOrgSetup {
|
|
orgUser := org.OrgUser{
|
|
OrgID: orgID,
|
|
UserID: usr.ID,
|
|
Role: org.RoleAdmin,
|
|
Created: time.Now(),
|
|
Updated: time.Now(),
|
|
}
|
|
|
|
if setting.AutoAssignOrg && !usr.IsAdmin {
|
|
if len(cmd.DefaultOrgRole) > 0 {
|
|
orgUser.Role = org.RoleType(cmd.DefaultOrgRole)
|
|
} else {
|
|
orgUser.Role = org.RoleType(setting.AutoAssignOrgRole)
|
|
}
|
|
}
|
|
_, err = s.orgService.InsertOrgUser(ctx, &orgUser)
|
|
if err != nil {
|
|
err := s.store.Delete(ctx, userID)
|
|
return usr, err
|
|
}
|
|
}
|
|
|
|
return usr, nil
|
|
}
|
|
|
|
func (s *Service) Delete(ctx context.Context, cmd *user.DeleteUserCommand) error {
|
|
_, err := s.store.GetNotServiceAccount(ctx, cmd.UserID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
// delete from all the stores
|
|
return s.store.Delete(ctx, cmd.UserID)
|
|
}
|
|
|
|
func (s *Service) GetByID(ctx context.Context, query *user.GetUserByIDQuery) (*user.User, error) {
|
|
user, err := s.store.GetByID(ctx, query.ID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if s.cfg.CaseInsensitiveLogin {
|
|
if err := s.store.CaseInsensitiveLoginConflict(ctx, user.Login, user.Email); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
return user, nil
|
|
}
|
|
|
|
// TODO: remove wrapper around sqlstore
|
|
func (s *Service) GetByLogin(ctx context.Context, query *user.GetUserByLoginQuery) (*user.User, error) {
|
|
q := models.GetUserByLoginQuery{LoginOrEmail: query.LoginOrEmail}
|
|
err := s.sqlStore.GetUserByLogin(ctx, &q)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return q.Result, nil
|
|
}
|
|
|
|
// TODO: remove wrapper around sqlstore
|
|
func (s *Service) GetByEmail(ctx context.Context, query *user.GetUserByEmailQuery) (*user.User, error) {
|
|
q := models.GetUserByEmailQuery{Email: query.Email}
|
|
err := s.sqlStore.GetUserByEmail(ctx, &q)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return q.Result, nil
|
|
}
|
|
|
|
// TODO: remove wrapper around sqlstore
|
|
func (s *Service) Update(ctx context.Context, cmd *user.UpdateUserCommand) error {
|
|
q := &models.UpdateUserCommand{
|
|
Name: cmd.Name,
|
|
Email: cmd.Email,
|
|
Login: cmd.Login,
|
|
Theme: cmd.Theme,
|
|
UserId: cmd.UserID,
|
|
}
|
|
return s.sqlStore.UpdateUser(ctx, q)
|
|
}
|
|
|
|
// TODO: remove wrapper around sqlstore
|
|
func (s *Service) ChangePassword(ctx context.Context, cmd *user.ChangeUserPasswordCommand) error {
|
|
q := &models.ChangeUserPasswordCommand{
|
|
UserId: cmd.UserID,
|
|
NewPassword: cmd.NewPassword,
|
|
OldPassword: cmd.OldPassword,
|
|
}
|
|
return s.sqlStore.ChangeUserPassword(ctx, q)
|
|
}
|
|
|
|
// TODO: remove wrapper around sqlstore
|
|
func (s *Service) UpdateLastSeenAt(ctx context.Context, cmd *user.UpdateUserLastSeenAtCommand) error {
|
|
q := &models.UpdateUserLastSeenAtCommand{
|
|
UserId: cmd.UserID,
|
|
}
|
|
return s.sqlStore.UpdateUserLastSeenAt(ctx, q)
|
|
}
|
|
|
|
// TODO: remove wrapper around sqlstore
|
|
func (s *Service) SetUsingOrg(ctx context.Context, cmd *user.SetUsingOrgCommand) error {
|
|
q := &models.SetUsingOrgCommand{
|
|
UserId: cmd.UserID,
|
|
OrgId: cmd.OrgID,
|
|
}
|
|
return s.sqlStore.SetUsingOrg(ctx, q)
|
|
}
|
|
|
|
// TODO: remove wrapper around sqlstore
|
|
func (s *Service) GetSignedInUserWithCacheCtx(ctx context.Context, query *user.GetSignedInUserQuery) (*user.SignedInUser, error) {
|
|
q := &models.GetSignedInUserQuery{
|
|
UserId: query.UserID,
|
|
Login: query.Login,
|
|
Email: query.Email,
|
|
OrgId: query.OrgID,
|
|
}
|
|
err := s.sqlStore.GetSignedInUserWithCacheCtx(ctx, q)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return q.Result, nil
|
|
}
|
|
|
|
// TODO: remove wrapper around sqlstore
|
|
func (s *Service) GetSignedInUser(ctx context.Context, query *user.GetSignedInUserQuery) (*user.SignedInUser, error) {
|
|
q := &models.GetSignedInUserQuery{
|
|
UserId: query.UserID,
|
|
Login: query.Login,
|
|
Email: query.Email,
|
|
OrgId: query.OrgID,
|
|
}
|
|
err := s.sqlStore.GetSignedInUser(ctx, q)
|
|
return q.Result, err
|
|
}
|
|
|
|
// TODO: remove wrapper around sqlstore
|
|
func (s *Service) Search(ctx context.Context, query *user.SearchUsersQuery) (*user.SearchUserQueryResult, error) {
|
|
var usrSeschHitDTOs []*user.UserSearchHitDTO
|
|
q := &models.SearchUsersQuery{
|
|
SignedInUser: query.SignedInUser,
|
|
Query: query.Query,
|
|
OrgId: query.OrgID,
|
|
Page: query.Page,
|
|
Limit: query.Limit,
|
|
AuthModule: query.AuthModule,
|
|
Filters: query.Filters,
|
|
IsDisabled: query.IsDisabled,
|
|
}
|
|
err := s.sqlStore.SearchUsers(ctx, q)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for _, usrSearch := range q.Result.Users {
|
|
usrSeschHitDTOs = append(usrSeschHitDTOs, &user.UserSearchHitDTO{
|
|
ID: usrSearch.Id,
|
|
Login: usrSearch.Login,
|
|
Email: usrSearch.Email,
|
|
Name: usrSearch.Name,
|
|
AvatarUrl: usrSearch.AvatarUrl,
|
|
IsDisabled: usrSearch.IsDisabled,
|
|
IsAdmin: usrSearch.IsAdmin,
|
|
LastSeenAt: usrSearch.LastSeenAt,
|
|
LastSeenAtAge: usrSearch.LastSeenAtAge,
|
|
AuthLabels: usrSearch.AuthLabels,
|
|
AuthModule: user.AuthModuleConversion(usrSearch.AuthModule),
|
|
})
|
|
}
|
|
|
|
res := &user.SearchUserQueryResult{
|
|
Users: usrSeschHitDTOs,
|
|
TotalCount: q.Result.TotalCount,
|
|
Page: q.Result.Page,
|
|
PerPage: q.Result.PerPage,
|
|
}
|
|
return res, nil
|
|
}
|
|
|
|
// TODO: remove wrapper around sqlstore
|
|
func (s *Service) Disable(ctx context.Context, cmd *user.DisableUserCommand) error {
|
|
q := &models.DisableUserCommand{
|
|
UserId: cmd.UserID,
|
|
IsDisabled: cmd.IsDisabled,
|
|
}
|
|
return s.sqlStore.DisableUser(ctx, q)
|
|
}
|
|
|
|
// TODO: remove wrapper around sqlstore
|
|
func (s *Service) BatchDisableUsers(ctx context.Context, cmd *user.BatchDisableUsersCommand) error {
|
|
c := &models.BatchDisableUsersCommand{
|
|
UserIds: cmd.UserIDs,
|
|
IsDisabled: cmd.IsDisabled,
|
|
}
|
|
return s.sqlStore.BatchDisableUsers(ctx, c)
|
|
}
|
|
|
|
// TODO: remove wrapper around sqlstore
|
|
func (s *Service) UpdatePermissions(userID int64, isAdmin bool) error {
|
|
return s.sqlStore.UpdateUserPermissions(userID, isAdmin)
|
|
}
|
|
|
|
// TODO: remove wrapper around sqlstore
|
|
func (s *Service) SetUserHelpFlag(ctx context.Context, cmd *user.SetUserHelpFlagCommand) error {
|
|
c := &models.SetUserHelpFlagCommand{
|
|
UserId: cmd.UserID,
|
|
HelpFlags1: cmd.HelpFlags1,
|
|
}
|
|
return s.sqlStore.SetUserHelpFlag(ctx, c)
|
|
}
|
|
|
|
// TODO: remove wrapper around sqlstore
|
|
func (s *Service) GetUserProfile(ctx context.Context, query *user.GetUserProfileQuery) (user.UserProfileDTO, error) {
|
|
q := &models.GetUserProfileQuery{
|
|
UserId: query.UserID,
|
|
}
|
|
err := s.sqlStore.GetUserProfile(ctx, q)
|
|
if err != nil {
|
|
return user.UserProfileDTO{}, err
|
|
}
|
|
result := user.UserProfileDTO{
|
|
ID: q.Result.Id,
|
|
Email: q.Result.Email,
|
|
Name: q.Result.Name,
|
|
Login: q.Result.Login,
|
|
Theme: q.Result.Theme,
|
|
OrgID: q.Result.OrgId,
|
|
IsGrafanaAdmin: q.Result.IsGrafanaAdmin,
|
|
IsDisabled: q.Result.IsDisabled,
|
|
IsExternal: q.Result.IsExternal,
|
|
AuthLabels: q.Result.AuthLabels,
|
|
UpdatedAt: q.Result.UpdatedAt,
|
|
CreatedAt: q.Result.CreatedAt,
|
|
AvatarUrl: q.Result.AvatarUrl,
|
|
AccessControl: q.Result.AccessControl,
|
|
}
|
|
return result, nil
|
|
}
|