1package models
2
3import (
4	"errors"
5	"time"
6)
7
8// Typed errors
9var (
10	ErrUserNotFound      = errors.New("user not found")
11	ErrUserAlreadyExists = errors.New("user already exists")
12	ErrLastGrafanaAdmin  = errors.New("cannot remove last grafana admin")
13	ErrProtectedUser     = errors.New("cannot adopt protected user")
14)
15
16type Password string
17
18func (p Password) IsWeak() bool {
19	return len(p) <= 4
20}
21
22type User struct {
23	Id            int64
24	Version       int
25	Email         string
26	Name          string
27	Login         string
28	Password      string
29	Salt          string
30	Rands         string
31	Company       string
32	EmailVerified bool
33	Theme         string
34	HelpFlags1    HelpFlags1
35	IsDisabled    bool
36
37	IsAdmin          bool
38	IsServiceAccount bool
39	OrgId            int64
40
41	Created    time.Time
42	Updated    time.Time
43	LastSeenAt time.Time
44}
45
46func (u *User) NameOrFallback() string {
47	if u.Name != "" {
48		return u.Name
49	}
50	if u.Login != "" {
51		return u.Login
52	}
53	return u.Email
54}
55
56// ---------------------
57// COMMANDS
58
59type CreateUserCommand struct {
60	Email            string
61	Login            string
62	Name             string
63	Company          string
64	OrgId            int64
65	OrgName          string
66	Password         string
67	EmailVerified    bool
68	IsAdmin          bool
69	IsDisabled       bool
70	SkipOrgSetup     bool
71	DefaultOrgRole   string
72	IsServiceAccount bool
73
74	Result User
75}
76
77type UpdateUserCommand struct {
78	Name  string `json:"name"`
79	Email string `json:"email"`
80	Login string `json:"login"`
81	Theme string `json:"theme"`
82
83	UserId int64 `json:"-"`
84}
85
86type ChangeUserPasswordCommand struct {
87	OldPassword string `json:"oldPassword"`
88	NewPassword string `json:"newPassword"`
89
90	UserId int64 `json:"-"`
91}
92
93type DisableUserCommand struct {
94	UserId     int64
95	IsDisabled bool
96}
97
98type BatchDisableUsersCommand struct {
99	UserIds    []int64
100	IsDisabled bool
101}
102
103type DeleteUserCommand struct {
104	UserId int64
105}
106
107type SetUsingOrgCommand struct {
108	UserId int64
109	OrgId  int64
110}
111
112// ----------------------
113// QUERIES
114
115type GetUserByLoginQuery struct {
116	LoginOrEmail string
117	Result       *User
118}
119
120type GetUserByEmailQuery struct {
121	Email  string
122	Result *User
123}
124
125type GetUserByIdQuery struct {
126	Id     int64
127	Result *User
128}
129
130type GetSignedInUserQuery struct {
131	UserId int64
132	Login  string
133	Email  string
134	OrgId  int64
135	Result *SignedInUser
136}
137
138type GetUserProfileQuery struct {
139	UserId int64
140	Result UserProfileDTO
141}
142
143type SearchUsersQuery struct {
144	OrgId      int64
145	Query      string
146	Page       int
147	Limit      int
148	AuthModule string
149	Filters    []Filter
150
151	IsDisabled *bool
152
153	Result SearchUserQueryResult
154}
155
156type SearchUserQueryResult struct {
157	TotalCount int64               `json:"totalCount"`
158	Users      []*UserSearchHitDTO `json:"users"`
159	Page       int                 `json:"page"`
160	PerPage    int                 `json:"perPage"`
161}
162
163type GetUserOrgListQuery struct {
164	UserId int64
165	Result []*UserOrgDTO
166}
167
168// ------------------------
169// DTO & Projections
170
171type SignedInUser struct {
172	UserId         int64
173	OrgId          int64
174	OrgName        string
175	OrgRole        RoleType
176	Login          string
177	Name           string
178	Email          string
179	ApiKeyId       int64
180	OrgCount       int
181	IsGrafanaAdmin bool
182	IsAnonymous    bool
183	HelpFlags1     HelpFlags1
184	LastSeenAt     time.Time
185	Teams          []int64
186}
187
188func (u *SignedInUser) ShouldUpdateLastSeenAt() bool {
189	return u.UserId > 0 && time.Since(u.LastSeenAt) > time.Minute*5
190}
191
192func (u *SignedInUser) NameOrFallback() string {
193	if u.Name != "" {
194		return u.Name
195	}
196	if u.Login != "" {
197		return u.Login
198	}
199	return u.Email
200}
201
202func (u *SignedInUser) ToUserDisplayDTO() *UserDisplayDTO {
203	return &UserDisplayDTO{
204		Id:    u.UserId,
205		Login: u.Login,
206		Name:  u.Name,
207	}
208}
209
210type UpdateUserLastSeenAtCommand struct {
211	UserId int64
212}
213
214func (u *SignedInUser) HasRole(role RoleType) bool {
215	if u.IsGrafanaAdmin {
216		return true
217	}
218
219	return u.OrgRole.Includes(role)
220}
221
222func (u *SignedInUser) IsRealUser() bool {
223	return u.UserId != 0
224}
225
226type UserProfileDTO struct {
227	Id             int64     `json:"id"`
228	Email          string    `json:"email"`
229	Name           string    `json:"name"`
230	Login          string    `json:"login"`
231	Theme          string    `json:"theme"`
232	OrgId          int64     `json:"orgId"`
233	IsGrafanaAdmin bool      `json:"isGrafanaAdmin"`
234	IsDisabled     bool      `json:"isDisabled"`
235	IsExternal     bool      `json:"isExternal"`
236	AuthLabels     []string  `json:"authLabels"`
237	UpdatedAt      time.Time `json:"updatedAt"`
238	CreatedAt      time.Time `json:"createdAt"`
239	AvatarUrl      string    `json:"avatarUrl"`
240}
241
242type UserSearchHitDTO struct {
243	Id            int64                `json:"id"`
244	Name          string               `json:"name"`
245	Login         string               `json:"login"`
246	Email         string               `json:"email"`
247	AvatarUrl     string               `json:"avatarUrl"`
248	IsAdmin       bool                 `json:"isAdmin"`
249	IsDisabled    bool                 `json:"isDisabled"`
250	LastSeenAt    time.Time            `json:"lastSeenAt"`
251	LastSeenAtAge string               `json:"lastSeenAtAge"`
252	AuthLabels    []string             `json:"authLabels"`
253	AuthModule    AuthModuleConversion `json:"-"`
254}
255
256type UserDisplayDTO struct {
257	Id        int64  `json:"id,omitempty"`
258	Name      string `json:"name,omitempty"`
259	Login     string `json:"login,omitempty"`
260	AvatarUrl string `json:"avatarUrl"`
261}
262
263type UserIdDTO struct {
264	Id      int64  `json:"id"`
265	Message string `json:"message"`
266}
267
268// implement Conversion interface to define custom field mapping (xorm feature)
269type AuthModuleConversion []string
270
271func (auth *AuthModuleConversion) FromDB(data []byte) error {
272	auth_module := string(data)
273	*auth = []string{auth_module}
274	return nil
275}
276
277// Just a stub, we don't want to write to database
278func (auth *AuthModuleConversion) ToDB() ([]byte, error) {
279	return []byte{}, nil
280}
281