Этот коммит содержится в:
Ben Schumacher
2025-01-13 20:23:09 +01:00
коммит произвёл GitHub
родитель 091d1bba8b
Коммит 8d4bf4bae0
50 изменённых файлов: 2429 добавлений и 745 удалений

Просмотреть файл

@@ -9,6 +9,7 @@ import (
"encoding/json"
"fmt"
"io"
"mime"
"mime/multipart"
"net"
"net/http"
@@ -4778,18 +4779,19 @@ func (c *Client4) GetFileInfosForPostIncludeDeleted(ctx context.Context, postId
// General/System Section
// GenerateSupportPacket generates and downloads a Support Packet.
func (c *Client4) GenerateSupportPacket(ctx context.Context) ([]byte, *Response, error) {
// It returns a ReadCloser to the packet and the filename. The caller needs to close the ReadCloser.
func (c *Client4) GenerateSupportPacket(ctx context.Context) (io.ReadCloser, string, *Response, error) {
r, err := c.DoAPIGet(ctx, c.systemRoute()+"/support_packet", "")
if err != nil {
return nil, BuildResponse(r), err
return nil, "", BuildResponse(r), err
}
defer closeBody(r)
data, err := io.ReadAll(r.Body)
_, params, err := mime.ParseMediaType(r.Header.Get("Content-Disposition"))
if err != nil {
return nil, BuildResponse(r), NewAppError("GetFile", "model.client.read_job_result_file.app_error", nil, "", r.StatusCode).Wrap(err)
return nil, "", BuildResponse(r), fmt.Errorf("could not parse Content-Disposition header: %w", err)
}
return data, BuildResponse(r), nil
return r.Body, params["filename"], BuildResponse(r), nil
}
// GetPing will return ok if the running goRoutines are below the threshold and unhealthy for above.

Просмотреть файл

@@ -5,6 +5,8 @@ package model
import (
"net/http"
"github.com/mattermost/mattermost/server/public/utils/timeutils"
)
const (
@@ -103,6 +105,75 @@ func (j *Job) Auditable() map[string]interface{} {
}
}
func (j *Job) MarshalYAML() (any, error) {
return struct {
Id string `yaml:"id"`
Type string `yaml:"type"`
Priority int64 `yaml:"priority"`
CreateAt string `yaml:"create_at"`
StartAt string `yaml:"start_at"`
LastActivityAt string `yaml:"last_activity_at"`
Status string `yaml:"status"`
Progress int64 `yaml:"progress"`
Data StringMap `yaml:"data"`
}{
Id: j.Id,
Type: j.Type,
Priority: j.Priority,
CreateAt: timeutils.FormatMillis(j.CreateAt),
StartAt: timeutils.FormatMillis(j.StartAt),
LastActivityAt: timeutils.FormatMillis(j.LastActivityAt),
Status: j.Status,
Progress: j.Progress,
Data: j.Data,
}, nil
}
func (j *Job) UnmarshalYAML(unmarshal func(interface{}) error) error {
out := struct {
Id string `yaml:"id"`
Type string `yaml:"type"`
Priority int64 `yaml:"priority"`
CreateAt string `yaml:"create_at"`
StartAt string `yaml:"start_at"`
LastActivityAt string `yaml:"last_activity_at"`
Status string `yaml:"status"`
Progress int64 `yaml:"progress"`
Data StringMap `yaml:"data"`
}{}
err := unmarshal(&out)
if err != nil {
return err
}
createAt, err := timeutils.ParseFormatedMillis(out.CreateAt)
if err != nil {
return err
}
updateAt, err := timeutils.ParseFormatedMillis(out.StartAt)
if err != nil {
return err
}
deleteAt, err := timeutils.ParseFormatedMillis(out.LastActivityAt)
if err != nil {
return err
}
*j = Job{
Id: out.Id,
Type: out.Type,
Priority: out.Priority,
CreateAt: createAt,
StartAt: updateAt,
LastActivityAt: deleteAt,
Status: out.Status,
Progress: out.Progress,
Data: out.Data,
}
return nil
}
func (j *Job) IsValid() *AppError {
if !IsValidId(j.Id) {
return NewAppError("Job.IsValid", "model.job.is_valid.id.app_error", nil, "id="+j.Id, http.StatusBadRequest)

Просмотреть файл

@@ -13,7 +13,7 @@ import (
"github.com/blang/semver/v4"
"github.com/pkg/errors"
"gopkg.in/yaml.v2"
"gopkg.in/yaml.v3"
)
type PluginOption struct {

Просмотреть файл

@@ -12,7 +12,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"gopkg.in/yaml.v2"
"gopkg.in/yaml.v3"
)
func TestIsValid(t *testing.T) {

Просмотреть файл

@@ -7,7 +7,7 @@ import (
"fmt"
"github.com/blang/semver/v4"
"gopkg.in/yaml.v2"
"gopkg.in/yaml.v3"
)
type PacketType string

Просмотреть файл

@@ -7,7 +7,7 @@ import (
"testing"
"github.com/stretchr/testify/require"
"gopkg.in/yaml.v2"
"gopkg.in/yaml.v3"
)
func TestPacketMetadataValidate(t *testing.T) {

Просмотреть файл

@@ -6,6 +6,8 @@ package model
import (
"fmt"
"strings"
"github.com/mattermost/mattermost/server/public/utils/timeutils"
)
// SysconsoleAncillaryPermissions maps the non-sysconsole permissions required by each sysconsole view.
@@ -438,6 +440,84 @@ func (r *Role) Auditable() map[string]interface{} {
}
}
func (r *Role) Sanitize() {
r.DisplayName = FakeSetting
r.Description = FakeSetting
}
func (r *Role) MarshalYAML() (any, error) {
return struct {
Id string `yaml:"id"`
Name string `yaml:"name"`
DisplayName string `yaml:"display_name"`
Description string `yaml:"description"`
CreateAt string `yaml:"create_at"`
UpdateAt string `yaml:"update_at"`
DeleteAt string `yaml:"delete_at"`
Permissions []string `yaml:"permissions"`
SchemeManaged bool `yaml:"scheme_managed"`
BuiltIn bool `yaml:"built_in"`
}{
Id: r.Id,
Name: r.Name,
DisplayName: r.DisplayName,
Description: r.Description,
CreateAt: timeutils.FormatMillis(r.CreateAt),
UpdateAt: timeutils.FormatMillis(r.UpdateAt),
DeleteAt: timeutils.FormatMillis(r.DeleteAt),
Permissions: r.Permissions,
SchemeManaged: r.SchemeManaged,
BuiltIn: r.BuiltIn,
}, nil
}
func (r *Role) UnmarshalYAML(unmarshal func(interface{}) error) error {
out := struct {
Id string `yaml:"id"`
Name string `yaml:"name"`
DisplayName string `yaml:"display_name"`
Description string `yaml:"description"`
CreateAt string `yaml:"create_at"`
UpdateAt string `yaml:"update_at"`
DeleteAt string `yaml:"delete_at"`
Permissions []string `yaml:"permissions"`
SchemeManaged bool `yaml:"scheme_managed"`
BuiltIn bool `yaml:"built_in"`
}{}
err := unmarshal(&out)
if err != nil {
return err
}
createAt, err := timeutils.ParseFormatedMillis(out.CreateAt)
if err != nil {
return err
}
updateAt, err := timeutils.ParseFormatedMillis(out.UpdateAt)
if err != nil {
return err
}
deleteAt, err := timeutils.ParseFormatedMillis(out.DeleteAt)
if err != nil {
return err
}
*r = Role{
Id: out.Id,
Name: out.Name,
DisplayName: out.DisplayName,
Description: out.Description,
CreateAt: createAt,
UpdateAt: updateAt,
DeleteAt: deleteAt,
Permissions: out.Permissions,
SchemeManaged: out.SchemeManaged,
BuiltIn: out.BuiltIn,
}
return nil
}
type RolePatch struct {
Permissions *[]string `json:"permissions"`
}

Просмотреть файл

@@ -6,6 +6,8 @@ package model
import (
"fmt"
"regexp"
"github.com/mattermost/mattermost/server/public/utils/timeutils"
)
const (
@@ -62,6 +64,117 @@ func (scheme *Scheme) Auditable() map[string]interface{} {
}
}
func (scheme *Scheme) Sanitize() {
scheme.Name = FakeSetting
scheme.DisplayName = FakeSetting
scheme.Description = FakeSetting
}
func (scheme *Scheme) MarshalYAML() (any, error) {
return struct {
Id string `yaml:"id"`
Name string `yaml:"name"`
DisplayName string `yaml:"display_name"`
Description string `yaml:"description"`
CreateAt string `yaml:"create_at"`
UpdateAt string `yaml:"update_at"`
DeleteAt string `yaml:"delete_at"`
Scope string `yaml:"scope"`
DefaultTeamAdminRole string `yaml:"default_team_admin_role"`
DefaultTeamUserRole string `yaml:"default_team_user_role"`
DefaultChannelAdminRole string `yaml:"default_channel_admin_role"`
DefaultChannelUserRole string `yaml:"default_channel_user_role"`
DefaultTeamGuestRole string `yaml:"default_team_guest_role"`
DefaultChannelGuestRole string `yaml:"default_channel_guest_role"`
DefaultPlaybookAdminRole string `yaml:"default_playbook_admin_role"`
DefaultPlaybookMemberRole string `yaml:"default_playbook_member_role"`
DefaultRunAdminRole string `yaml:"default_run_admin_role"`
DefaultRunMemberRole string `yaml:"default_run_member_role"`
}{
Id: scheme.Id,
Name: scheme.Name,
DisplayName: scheme.DisplayName,
Description: scheme.Description,
CreateAt: timeutils.FormatMillis(scheme.CreateAt),
UpdateAt: timeutils.FormatMillis(scheme.UpdateAt),
DeleteAt: timeutils.FormatMillis(scheme.DeleteAt),
Scope: scheme.Scope,
DefaultTeamAdminRole: scheme.DefaultTeamAdminRole,
DefaultTeamUserRole: scheme.DefaultTeamUserRole,
DefaultChannelAdminRole: scheme.DefaultChannelAdminRole,
DefaultChannelUserRole: scheme.DefaultChannelUserRole,
DefaultTeamGuestRole: scheme.DefaultTeamGuestRole,
DefaultChannelGuestRole: scheme.DefaultChannelGuestRole,
DefaultPlaybookAdminRole: scheme.DefaultPlaybookAdminRole,
DefaultPlaybookMemberRole: scheme.DefaultPlaybookMemberRole,
DefaultRunAdminRole: scheme.DefaultRunAdminRole,
DefaultRunMemberRole: scheme.DefaultRunMemberRole,
}, nil
}
func (scheme *Scheme) UnmarshalYAML(unmarshal func(interface{}) error) error {
out := struct {
Id string `yaml:"id"`
Name string `yaml:"name"`
DisplayName string `yaml:"display_name"`
Description string `yaml:"description"`
CreateAt string `yaml:"create_at"`
UpdateAt string `yaml:"update_at"`
DeleteAt string `yaml:"delete_at"`
Scope string `yaml:"scope"`
DefaultTeamAdminRole string `yaml:"default_team_admin_role"`
DefaultTeamUserRole string `yaml:"default_team_user_role"`
DefaultChannelAdminRole string `yaml:"default_channel_admin_role"`
DefaultChannelUserRole string `yaml:"default_channel_user_role"`
DefaultTeamGuestRole string `yaml:"default_team_guest_role"`
DefaultChannelGuestRole string `yaml:"default_channel_guest_role"`
DefaultPlaybookAdminRole string `yaml:"default_playbook_admin_role"`
DefaultPlaybookMemberRole string `yaml:"default_playbook_member_role"`
DefaultRunAdminRole string `yaml:"default_run_admin_role"`
DefaultRunMemberRole string `yaml:"default_run_member_role"`
}{}
err := unmarshal(&out)
if err != nil {
return err
}
createAt, err := timeutils.ParseFormatedMillis(out.CreateAt)
if err != nil {
return err
}
updateAt, err := timeutils.ParseFormatedMillis(out.UpdateAt)
if err != nil {
return err
}
deleteAt, err := timeutils.ParseFormatedMillis(out.DeleteAt)
if err != nil {
return err
}
*scheme = Scheme{
Id: out.Id,
Name: out.Name,
DisplayName: out.DisplayName,
Description: out.Description,
CreateAt: createAt,
UpdateAt: updateAt,
DeleteAt: deleteAt,
Scope: out.Scope,
DefaultTeamAdminRole: out.DefaultTeamAdminRole,
DefaultTeamUserRole: out.DefaultTeamUserRole,
DefaultChannelAdminRole: out.DefaultChannelAdminRole,
DefaultChannelUserRole: out.DefaultChannelUserRole,
DefaultTeamGuestRole: out.DefaultTeamGuestRole,
DefaultChannelGuestRole: out.DefaultChannelGuestRole,
DefaultPlaybookAdminRole: out.DefaultPlaybookAdminRole,
DefaultPlaybookMemberRole: out.DefaultPlaybookMemberRole,
DefaultRunAdminRole: out.DefaultRunAdminRole,
DefaultRunMemberRole: out.DefaultRunMemberRole,
}
return nil
}
type SchemePatch struct {
Name *string `json:"name"`
DisplayName *string `json:"display_name"`

Просмотреть файл

@@ -9,72 +9,120 @@ import (
)
const (
SupportPacketErrorFile = "warning.txt"
CurrentSupportPacketVersion = 1
SupportPacketErrorFile = "warning.txt"
)
type SupportPacket struct {
/* Build information */
type SupportPacketDiagnostics struct {
Version int `yaml:"version"`
ServerOS string `yaml:"server_os"`
ServerArchitecture string `yaml:"server_architecture"`
ServerVersion string `yaml:"server_version"`
BuildHash string `yaml:"build_hash"`
License struct {
Company string `yaml:"company"`
Users int `yaml:"users"`
SkuShortName string `yaml:"sku_short_name"`
IsTrial bool `yaml:"is_trial,omitempty"`
IsGovSKU bool `yaml:"is_gov_sku,omitempty"`
} `yaml:"license"`
/* DB */
Server struct {
OS string `yaml:"os"`
Architecture string `yaml:"architecture"`
Hostname string `yaml:"hostname"`
Version string `yaml:"version"`
BuildHash string `yaml:"build_hash"`
InstallationType string `yaml:"installation_type"`
} `yaml:"server"`
DatabaseType string `yaml:"database_type"`
DatabaseVersion string `yaml:"database_version"`
DatabaseSchemaVersion string `yaml:"database_schema_version"`
WebsocketConnections int `yaml:"websocket_connections"`
MasterDbConnections int `yaml:"master_db_connections"`
ReplicaDbConnections int `yaml:"read_db_connections"`
Config struct {
Source string `yaml:"store_type"`
} `yaml:"config"`
/* Cluster */
Database struct {
Type string `yaml:"type"`
Version string `yaml:"version"`
SchemaVersion string `yaml:"schema_version"`
MasterConnectios int `yaml:"master_connections"`
ReplicaConnectios int `yaml:"replica_connections"`
SearchConnections int `yaml:"search_connections"`
} `yaml:"database"`
ClusterID string `yaml:"cluster_id"`
FileStore struct {
Status string `yaml:"file_status"`
Error string `yaml:"erorr,omitempty"`
Driver string `yaml:"file_driver"`
} `yaml:"file_store"`
/* File store */
Websocket struct {
Connections int `yaml:"connections"`
} `yaml:"websocket"`
FileDriver string `yaml:"file_driver"`
FileStatus string `yaml:"file_status"`
Cluster struct {
ID string `yaml:"id"`
NumberOfNodes int `yaml:"number_of_nodes"`
} `yaml:"cluster"`
/* LDAP */
LDAP struct {
Status string `yaml:"status,omitempty"`
Error string `yaml:"erorr,omitempty"`
ServerName string `yaml:"server_name,omitempty"`
ServerVersion string `yaml:"server_version,omitempty"`
} `yaml:"ldap"`
LdapVendorName string `yaml:"ldap_vendor_name,omitempty"`
LdapVendorVersion string `yaml:"ldap_vendor_version,omitempty"`
ElasticSearch struct {
ServerVersion string `yaml:"server_version,omitempty"`
ServerPlugins []string `yaml:"server_plugins,omitempty"`
} `yaml:"elastic"`
}
/* Elastic Search */
ElasticServerVersion string `yaml:"elastic_server_version,omitempty"`
ElasticServerPlugins []string `yaml:"elastic_server_plugins,omitempty"`
/* License */
LicenseTo string `yaml:"license_to"`
LicenseSupportedUsers int `yaml:"license_supported_users"`
LicenseIsTrial bool `yaml:"license_is_trial,omitempty"`
/* Server stats */
ActiveUsers int `yaml:"active_users"`
DailyActiveUsers int `yaml:"daily_active_users"`
MonthlyActiveUsers int `yaml:"monthly_active_users"`
InactiveUserCount int `yaml:"inactive_user_count"`
TotalPosts int `yaml:"total_posts"`
TotalChannels int `yaml:"total_channels"`
TotalTeams int `yaml:"total_teams"`
/* Jobs */
type SupportPacketStats struct {
RegisteredUsers int64 `yaml:"registered_users"`
ActiveUsers int64 `yaml:"active_users"`
DailyActiveUsers int64 `yaml:"daily_active_users"`
MonthlyActiveUsers int64 `yaml:"monthly_active_users"`
DeactivatedUsers int64 `yaml:"deactivated_users"`
Guests int64 `yaml:"guests"`
BotAccounts int64 `yaml:"bot_accounts"`
Posts int64 `yaml:"posts"`
Channels int64 `yaml:"channels"`
Teams int64 `yaml:"teams"`
SlashCommands int64 `yaml:"slash_commands"`
IncomingWebhooks int64 `yaml:"incoming_webhooks"`
OutgoingWebhooks int64 `yaml:"outgoing_webhooks"`
}
// SupportPacketJobList contains the list of latest run enterprise job runs.
// It is included in the Support Packet.
type SupportPacketJobList struct {
LDAPSyncJobs []*Job `yaml:"ldap_sync_jobs"`
DataRetentionJobs []*Job `yaml:"data_retention_jobs"`
MessageExportJobs []*Job `yaml:"message_export_jobs"`
ElasticPostIndexingJobs []*Job `yaml:"elastic_post_indexing_jobs"`
ElasticPostAggregationJobs []*Job `yaml:"elastic_post_aggregation_jobs"`
BlevePostIndexingJobs []*Job `yaml:"bleve_post_indexin_jobs"`
LdapSyncJobs []*Job `yaml:"ldap_sync_jobs"`
MigrationJobs []*Job `yaml:"migration_jobs"`
}
// SupportPacketPermissionInfo contains the list of schemes and the list of roles.
// It is included in the Support Packet.
type SupportPacketPermissionInfo struct {
Roles []*Role `yaml:"roles"`
Schemes []*Scheme `yaml:"schemes"`
}
// SupportPacketConfig contains the Mattermost configuration. In contrast to [Config], it also contains the list of Feature Flags.
// It is included in the Support Packet.
type SupportPacketConfig struct {
*Config
FeatureFlags FeatureFlags `json:"FeatureFlags"`
}
// SupportPacketPluginList contains the list of enabled and disabled plugins.
// It is included in the Support Packet.
type SupportPacketPluginList struct {
Enabled []Manifest `json:"enabled"`
Disabled []Manifest `json:"disabled"`
}
type FileData struct {
Filename string
Body []byte