2022-06-28 07:32:25 -05:00
|
|
|
package user
|
|
|
|
|
2022-07-19 09:01:05 -05:00
|
|
|
import (
|
2022-07-20 07:50:06 -05:00
|
|
|
"errors"
|
2022-08-02 09:58:05 -05:00
|
|
|
"fmt"
|
|
|
|
"strings"
|
2022-07-19 09:01:05 -05:00
|
|
|
"time"
|
2022-08-10 04:56:48 -05:00
|
|
|
|
|
|
|
"github.com/grafana/grafana/pkg/services/org"
|
2022-07-19 09:01:05 -05:00
|
|
|
)
|
2022-06-28 07:32:25 -05:00
|
|
|
|
|
|
|
type HelpFlags1 uint64
|
|
|
|
|
2022-08-10 04:56:48 -05:00
|
|
|
func (f HelpFlags1) HasFlag(flag HelpFlags1) bool { return f&flag != 0 }
|
|
|
|
func (f *HelpFlags1) AddFlag(flag HelpFlags1) { *f |= flag }
|
|
|
|
|
|
|
|
const (
|
|
|
|
HelpFlagGettingStartedPanelDismissed HelpFlags1 = 1 << iota
|
|
|
|
HelpFlagDashboardHelp1
|
|
|
|
)
|
|
|
|
|
2022-07-20 07:50:06 -05:00
|
|
|
// Typed errors
|
|
|
|
var (
|
|
|
|
ErrCaseInsensitive = errors.New("case insensitive conflict")
|
|
|
|
ErrUserNotFound = errors.New("user not found")
|
|
|
|
ErrUserAlreadyExists = errors.New("user already exists")
|
|
|
|
ErrLastGrafanaAdmin = errors.New("cannot remove last grafana admin")
|
|
|
|
ErrProtectedUser = errors.New("cannot adopt protected user")
|
|
|
|
)
|
|
|
|
|
2022-06-28 07:32:25 -05:00
|
|
|
type User struct {
|
|
|
|
ID int64 `xorm:"pk autoincr 'id'"`
|
|
|
|
Version int
|
|
|
|
Email string
|
|
|
|
Name string
|
|
|
|
Login string
|
|
|
|
Password string
|
|
|
|
Salt string
|
|
|
|
Rands string
|
|
|
|
Company string
|
|
|
|
EmailVerified bool
|
|
|
|
Theme string
|
|
|
|
HelpFlags1 HelpFlags1
|
|
|
|
IsDisabled bool
|
|
|
|
|
|
|
|
IsAdmin bool
|
|
|
|
IsServiceAccount bool
|
|
|
|
OrgID int64 `xorm:"org_id"`
|
|
|
|
|
|
|
|
Created time.Time
|
|
|
|
Updated time.Time
|
|
|
|
LastSeenAt time.Time
|
|
|
|
}
|
|
|
|
|
|
|
|
type CreateUserCommand struct {
|
|
|
|
Email string
|
|
|
|
Login string
|
|
|
|
Name string
|
|
|
|
Company string
|
|
|
|
OrgID int64
|
|
|
|
OrgName string
|
|
|
|
Password string
|
|
|
|
EmailVerified bool
|
|
|
|
IsAdmin bool
|
|
|
|
IsDisabled bool
|
|
|
|
SkipOrgSetup bool
|
|
|
|
DefaultOrgRole string
|
|
|
|
IsServiceAccount bool
|
|
|
|
}
|
|
|
|
|
2022-08-04 06:22:43 -05:00
|
|
|
type GetUserByLoginQuery struct {
|
|
|
|
LoginOrEmail string
|
|
|
|
}
|
|
|
|
|
2022-08-04 06:47:30 -05:00
|
|
|
type GetUserByEmailQuery struct {
|
|
|
|
Email string
|
|
|
|
}
|
|
|
|
|
2022-08-04 07:22:44 -05:00
|
|
|
type UpdateUserCommand struct {
|
|
|
|
Name string `json:"name"`
|
|
|
|
Email string `json:"email"`
|
|
|
|
Login string `json:"login"`
|
|
|
|
Theme string `json:"theme"`
|
|
|
|
|
|
|
|
UserID int64 `json:"-"`
|
|
|
|
}
|
|
|
|
|
2022-08-04 08:05:05 -05:00
|
|
|
type ChangeUserPasswordCommand struct {
|
|
|
|
OldPassword string `json:"oldPassword"`
|
|
|
|
NewPassword string `json:"newPassword"`
|
|
|
|
|
|
|
|
UserID int64 `json:"-"`
|
|
|
|
}
|
|
|
|
|
2022-08-04 08:44:14 -05:00
|
|
|
type UpdateUserLastSeenAtCommand struct {
|
|
|
|
UserID int64
|
|
|
|
}
|
|
|
|
|
2022-08-11 06:28:55 -05:00
|
|
|
type SetUsingOrgCommand struct {
|
2022-07-19 09:01:05 -05:00
|
|
|
UserID int64
|
2022-08-11 06:28:55 -05:00
|
|
|
OrgID int64
|
2022-07-19 09:01:05 -05:00
|
|
|
}
|
2022-08-02 09:58:05 -05:00
|
|
|
|
2022-08-11 06:28:55 -05:00
|
|
|
type GetSignedInUserQuery struct {
|
|
|
|
UserID int64
|
|
|
|
Login string
|
|
|
|
Email string
|
|
|
|
OrgID int64
|
2022-08-02 09:58:05 -05:00
|
|
|
}
|
|
|
|
|
2022-08-10 04:56:48 -05:00
|
|
|
type SignedInUser struct {
|
2022-08-11 06:28:55 -05:00
|
|
|
UserID int64 `xorm:"user_id"`
|
|
|
|
OrgID int64 `xorm:"org_id"`
|
2022-08-10 04:56:48 -05:00
|
|
|
OrgName string
|
|
|
|
OrgRole org.RoleType
|
|
|
|
ExternalAuthModule string
|
2022-08-11 06:28:55 -05:00
|
|
|
ExternalAuthID string
|
2022-08-10 04:56:48 -05:00
|
|
|
Login string
|
|
|
|
Name string
|
|
|
|
Email string
|
2022-08-11 06:28:55 -05:00
|
|
|
ApiKeyID int64 `xorm:"api_key_id"`
|
2022-08-10 04:56:48 -05:00
|
|
|
OrgCount int
|
|
|
|
IsGrafanaAdmin bool
|
|
|
|
IsAnonymous bool
|
|
|
|
IsDisabled bool
|
|
|
|
HelpFlags1 HelpFlags1
|
|
|
|
LastSeenAt time.Time
|
|
|
|
Teams []int64
|
|
|
|
// Permissions grouped by orgID and actions
|
|
|
|
Permissions map[int64]map[string][]string `json:"-"`
|
|
|
|
}
|
|
|
|
|
2022-08-11 06:28:55 -05:00
|
|
|
func (u *User) NameOrFallback() string {
|
|
|
|
if u.Name != "" {
|
|
|
|
return u.Name
|
|
|
|
}
|
|
|
|
if u.Login != "" {
|
|
|
|
return u.Login
|
|
|
|
}
|
|
|
|
return u.Email
|
|
|
|
}
|
|
|
|
|
|
|
|
type DeleteUserCommand struct {
|
|
|
|
UserID int64
|
|
|
|
}
|
|
|
|
|
|
|
|
type GetUserByIDQuery struct {
|
|
|
|
ID int64
|
|
|
|
}
|
|
|
|
|
|
|
|
type ErrCaseInsensitiveLoginConflict struct {
|
|
|
|
Users []User
|
|
|
|
}
|
|
|
|
|
2022-08-10 04:56:48 -05:00
|
|
|
type UserDisplayDTO struct {
|
|
|
|
Id int64 `json:"id,omitempty"`
|
|
|
|
Name string `json:"name,omitempty"`
|
|
|
|
Login string `json:"login,omitempty"`
|
|
|
|
AvatarUrl string `json:"avatarUrl"`
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------
|
|
|
|
// DTO & Projections
|
|
|
|
|
|
|
|
func (u *SignedInUser) ShouldUpdateLastSeenAt() bool {
|
2022-08-11 06:28:55 -05:00
|
|
|
return u.UserID > 0 && time.Since(u.LastSeenAt) > time.Minute*5
|
2022-08-10 04:56:48 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
func (u *SignedInUser) NameOrFallback() string {
|
|
|
|
if u.Name != "" {
|
|
|
|
return u.Name
|
|
|
|
}
|
|
|
|
if u.Login != "" {
|
|
|
|
return u.Login
|
|
|
|
}
|
|
|
|
return u.Email
|
|
|
|
}
|
|
|
|
|
|
|
|
func (u *SignedInUser) ToUserDisplayDTO() *UserDisplayDTO {
|
|
|
|
return &UserDisplayDTO{
|
2022-08-11 06:28:55 -05:00
|
|
|
Id: u.UserID,
|
2022-08-10 04:56:48 -05:00
|
|
|
Login: u.Login,
|
|
|
|
Name: u.Name,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
func (u *SignedInUser) HasRole(role org.RoleType) bool {
|
|
|
|
if u.IsGrafanaAdmin {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
return u.OrgRole.Includes(role)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (u *SignedInUser) IsRealUser() bool {
|
2022-08-11 06:28:55 -05:00
|
|
|
return u.UserID != 0
|
2022-08-10 04:56:48 -05:00
|
|
|
}
|
|
|
|
|
2022-08-02 09:58:05 -05:00
|
|
|
func (e *ErrCaseInsensitiveLoginConflict) Unwrap() error {
|
|
|
|
return ErrCaseInsensitive
|
|
|
|
}
|
|
|
|
|
|
|
|
func (e *ErrCaseInsensitiveLoginConflict) Error() string {
|
|
|
|
n := len(e.Users)
|
|
|
|
|
|
|
|
userStrings := make([]string, 0, n)
|
|
|
|
for _, v := range e.Users {
|
|
|
|
userStrings = append(userStrings, fmt.Sprintf("%s (email:%s, id:%d)", v.Login, v.Email, v.ID))
|
|
|
|
}
|
|
|
|
|
|
|
|
return fmt.Sprintf(
|
|
|
|
"Found a conflict in user login information. %d users already exist with either the same login or email: [%s].",
|
|
|
|
n, strings.Join(userStrings, ", "))
|
|
|
|
}
|