[MM-55017] Add API method to get users for Admin Reporting (#25499)
* Add store method to get reporting data * Some store changes * Added app layer * Added API call, some miscellaneous fixes * Fix lint * Fix serialized check * Add API docs * Fix user store tests leaking users * Fix test * PR feedback * Add filtering for role/team/activated user, filter out bot users * Fix mock * Fix test * Oops * Switch to using struct filter * More PR feedback * Fix gen * Fix test * Fix API docs * Fix test * Fix possible SQL injection, some query optimization * Fix migrations * Oops * Add role to API * Fix check * Add Client4 API call for load testing * Fix test * Update server/channels/store/storetest/user_store.go Co-authored-by: Ibrahim Serdar Acikgoz <serdaracikgoz86@gmail.com> * PR feedback --------- Co-authored-by: Mattermost Build <build@mattermost.com> Co-authored-by: Ibrahim Serdar Acikgoz <serdaracikgoz86@gmail.com>
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
7afc14de36
Коммит
109f4643c6
@@ -1918,6 +1918,54 @@ func (c *Client4) EnableUserAccessToken(ctx context.Context, tokenId string) (*R
|
||||
return BuildResponse(r), nil
|
||||
}
|
||||
|
||||
func (c *Client4) GetUsersForReporting(ctx context.Context, options *UserReportOptionsAPI) ([]*UserReport, *Response, error) {
|
||||
values := url.Values{}
|
||||
if options.SortColumn != "" {
|
||||
values.Set("sort_column", options.SortColumn)
|
||||
}
|
||||
if options.PageSize > 0 {
|
||||
values.Set("page_size", strconv.Itoa(options.PageSize))
|
||||
}
|
||||
if options.Team != "" {
|
||||
values.Set("team_filter", options.Team)
|
||||
}
|
||||
if options.HideActive {
|
||||
values.Set("hide_active", "true")
|
||||
}
|
||||
if options.HideInactive {
|
||||
values.Set("hide_inactive", "true")
|
||||
}
|
||||
if options.SortDesc {
|
||||
values.Set("sort_direction", "desc")
|
||||
}
|
||||
if options.LastSortColumnValue != "" {
|
||||
values.Set("last_column_value", options.LastSortColumnValue)
|
||||
}
|
||||
if options.LastUserId != "" {
|
||||
values.Set("last_id", options.LastUserId)
|
||||
}
|
||||
if options.Role != "" {
|
||||
values.Set("role_filter", options.Role)
|
||||
}
|
||||
if options.HasNoTeam {
|
||||
values.Set("has_no_team", "true")
|
||||
}
|
||||
if options.DateRange != "" {
|
||||
values.Set("date_range", options.DateRange)
|
||||
}
|
||||
|
||||
r, err := c.DoAPIGet(ctx, c.usersRoute()+"/report?"+values.Encode(), "")
|
||||
if err != nil {
|
||||
return nil, BuildResponse(r), err
|
||||
}
|
||||
defer closeBody(r)
|
||||
var list []*UserReport
|
||||
if err := json.NewDecoder(r.Body).Decode(&list); err != nil {
|
||||
return nil, nil, NewAppError("GetUsersForReporting", "api.unmarshal_error", nil, "", http.StatusInternalServerError).Wrap(err)
|
||||
}
|
||||
return list, BuildResponse(r), nil
|
||||
}
|
||||
|
||||
// Bots section
|
||||
|
||||
// CreateBot creates a bot in the system based on the provided bot struct.
|
||||
|
||||
@@ -48,6 +48,10 @@ const (
|
||||
PushThreadsNotifyProp = "push_threads"
|
||||
EmailThreadsNotifyProp = "email_threads"
|
||||
|
||||
ReportDurationLast30Days = "last_30_days"
|
||||
ReportDurationPreviousMonth = "previous_month"
|
||||
ReportDurationLast6Months = "last_6_months"
|
||||
|
||||
DefaultLocale = "en"
|
||||
UserAuthServiceEmail = "email"
|
||||
|
||||
@@ -67,6 +71,10 @@ const (
|
||||
DesktopTokenTTL = time.Minute * 3
|
||||
)
|
||||
|
||||
var (
|
||||
UserReportSortColumns = []string{"CreateAt", "Username", "FirstName", "LastName", "Nickname", "Email", "Roles"}
|
||||
)
|
||||
|
||||
//msgp:tuple User
|
||||
|
||||
// User contains the details about the user.
|
||||
@@ -1007,3 +1015,82 @@ type UsersWithGroupsAndCount struct {
|
||||
Users []*UserWithGroups `json:"users"`
|
||||
Count int64 `json:"total_count"`
|
||||
}
|
||||
|
||||
type UserPostStats struct {
|
||||
LastLogin int64 `json:"last_login_at,omitempty"`
|
||||
LastStatusAt *int64 `json:"last_status_at,omitempty"`
|
||||
LastPostDate *int64 `json:"last_post_date,omitempty"`
|
||||
DaysActive *int `json:"days_active,omitempty"`
|
||||
TotalPosts *int `json:"total_posts,omitempty"`
|
||||
}
|
||||
|
||||
type UserReportQuery struct {
|
||||
User
|
||||
UserPostStats
|
||||
}
|
||||
|
||||
type UserReport struct {
|
||||
Id string `json:"id"`
|
||||
Username string `json:"username"`
|
||||
Email string `json:"email"`
|
||||
CreateAt int64 `json:"create_at,omitempty"`
|
||||
DisplayName string `json:"display_name"`
|
||||
Roles string `json:"roles"`
|
||||
UserPostStats
|
||||
}
|
||||
|
||||
type UserReportOptionsWithoutDateRange struct {
|
||||
SortColumn string
|
||||
SortDesc bool
|
||||
PageSize int
|
||||
LastSortColumnValue string
|
||||
LastUserId string
|
||||
Role string
|
||||
Team string
|
||||
HasNoTeam bool
|
||||
HideActive bool
|
||||
HideInactive bool
|
||||
}
|
||||
|
||||
type UserReportOptions struct {
|
||||
UserReportOptionsWithoutDateRange
|
||||
StartAt int64
|
||||
EndAt int64
|
||||
}
|
||||
|
||||
type UserReportOptionsAPI struct {
|
||||
UserReportOptionsWithoutDateRange
|
||||
DateRange string
|
||||
}
|
||||
|
||||
func (u *UserReportOptionsAPI) ToBaseOptions(now time.Time) *UserReportOptions {
|
||||
startAt := int64(0)
|
||||
endAt := int64(0)
|
||||
if u.DateRange == ReportDurationLast30Days {
|
||||
startAt = now.AddDate(0, 0, -30).UnixMilli()
|
||||
} else if u.DateRange == ReportDurationPreviousMonth {
|
||||
startOfMonth := time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, time.Local)
|
||||
startAt = startOfMonth.AddDate(0, -1, 0).UnixMilli()
|
||||
endAt = startOfMonth.UnixMilli()
|
||||
} else if u.DateRange == ReportDurationLast6Months {
|
||||
startAt = now.AddDate(0, -6, -0).UnixMilli()
|
||||
}
|
||||
|
||||
return &UserReportOptions{
|
||||
UserReportOptionsWithoutDateRange: u.UserReportOptionsWithoutDateRange,
|
||||
StartAt: startAt,
|
||||
EndAt: endAt,
|
||||
}
|
||||
}
|
||||
|
||||
func (u *UserReportQuery) ToReport() *UserReport {
|
||||
return &UserReport{
|
||||
Id: u.Id,
|
||||
Username: u.Username,
|
||||
Email: u.Email,
|
||||
CreateAt: u.CreateAt,
|
||||
DisplayName: u.GetDisplayName(ShowNicknameFullName),
|
||||
Roles: u.Roles,
|
||||
UserPostStats: u.UserPostStats,
|
||||
}
|
||||
}
|
||||
|
||||
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Ссылка в новой задаче
Block a user