1
0
forked from lug/matterbridge

Update dependencies (#1784)

This commit is contained in:
Wim
2022-04-01 00:23:19 +02:00
committed by GitHub
parent 4ab72acec6
commit c6716e030c
255 changed files with 69606 additions and 58489 deletions

View File

@@ -0,0 +1,13 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package model
// ExportDataDir is the name of the directory were to store additional data
// included with the export (e.g. file attachments).
const ExportDataDir = "data"
type BulkExportOpts struct {
IncludeAttachments bool
CreateArchive bool
}

View File

@@ -6,6 +6,8 @@ package model
import (
"crypto/sha1"
"encoding/hex"
"encoding/json"
"errors"
"io"
"net/http"
"sort"
@@ -51,11 +53,11 @@ type Channel struct {
ExtraUpdateAt int64 `json:"extra_update_at"`
CreatorId string `json:"creator_id"`
SchemeId *string `json:"scheme_id"`
Props map[string]interface{} `json:"props" db:"-"`
Props map[string]interface{} `json:"props"`
GroupConstrained *bool `json:"group_constrained"`
Shared *bool `json:"shared"`
TotalMsgCountRoot int64 `json:"total_msg_count_root"`
PolicyID *string `json:"policy_id" db:"-"`
PolicyID *string `json:"policy_id"`
LastRootPostAt int64 `json:"last_root_post_at"`
}
@@ -141,6 +143,8 @@ type ChannelSearchOpts struct {
Private bool
Page *int
PerPage *int
LastDeleteAt int
LastUpdateAt int
}
type ChannelMemberCountByGroup struct {
@@ -157,6 +161,23 @@ func WithID(ID string) ChannelOption {
}
}
// The following are some GraphQL methods necessary to return the
// data in float64 type. The spec doesn't support 64 bit integers,
// so we have to pass the data in float64. The _ at the end is
// a hack to keep the attribute name same in GraphQL schema.
func (o *Channel) CreateAt_() float64 {
return float64(o.CreateAt)
}
func (o *Channel) UpdateAt_() float64 {
return float64(o.UpdateAt)
}
func (o *Channel) DeleteAt_() float64 {
return float64(o.DeleteAt)
}
func (o *Channel) DeepCopy() *Channel {
copy := *o
if copy.SchemeId != nil {
@@ -303,6 +324,24 @@ func (o *Channel) GetOtherUserIdForDM(userId string) string {
return otherUserId
}
func (ChannelType) ImplementsGraphQLType(name string) bool {
return name == "ChannelType"
}
func (t ChannelType) MarshalJSON() ([]byte, error) {
return json.Marshal(string(t))
}
func (t *ChannelType) UnmarshalGraphQL(input interface{}) error {
chType, ok := input.(string)
if !ok {
return errors.New("wrong type")
}
*t = ChannelType(chType)
return nil
}
func GetDMNameFromIds(userId1, userId2 string) string {
if userId1 > userId2 {
return userId2 + "__" + userId1

View File

@@ -60,6 +60,31 @@ type ChannelMember struct {
ExplicitRoles string `json:"explicit_roles"`
}
// The following are some GraphQL methods necessary to return the
// data in float64 type. The spec doesn't support 64 bit integers,
// so we have to pass the data in float64. The _ at the end is
// a hack to keep the attribute name same in GraphQL schema.
func (o *ChannelMember) LastViewedAt_() float64 {
return float64(o.LastViewedAt)
}
func (o *ChannelMember) MsgCount_() float64 {
return float64(o.MsgCount)
}
func (o *ChannelMember) MentionCount_() float64 {
return float64(o.MentionCount)
}
func (o *ChannelMember) MentionCountRoot_() float64 {
return float64(o.MentionCountRoot)
}
func (o *ChannelMember) LastUpdateAt_() float64 {
return float64(o.LastUpdateAt)
}
// ChannelMemberWithTeamData contains ChannelMember appended with extra team information
// as well.
type ChannelMemberWithTeamData struct {

View File

@@ -4,6 +4,8 @@
package model
import (
"encoding/json"
"errors"
"regexp"
)
@@ -54,6 +56,10 @@ type SidebarCategoryWithChannels struct {
Channels []string `json:"channel_ids"`
}
func (sc SidebarCategoryWithChannels) ChannelIds() []string {
return sc.Channels
}
type SidebarCategoryOrder []string
// OrderedSidebarCategories combines categories, their channel IDs and an array of Category IDs, sorted
@@ -83,3 +89,39 @@ func IsValidCategoryId(s string) bool {
// Or default categories can follow the pattern {type}_{userID}_{teamID}
return categoryIdPattern.MatchString(s)
}
func (SidebarCategoryType) ImplementsGraphQLType(name string) bool {
return name == "SidebarCategoryType"
}
func (t SidebarCategoryType) MarshalJSON() ([]byte, error) {
return json.Marshal(string(t))
}
func (t *SidebarCategoryType) UnmarshalGraphQL(input interface{}) error {
chType, ok := input.(string)
if !ok {
return errors.New("wrong type")
}
*t = SidebarCategoryType(chType)
return nil
}
func (SidebarCategorySorting) ImplementsGraphQLType(name string) bool {
return name == "SidebarCategorySorting"
}
func (t SidebarCategorySorting) MarshalJSON() ([]byte, error) {
return json.Marshal(string(t))
}
func (t *SidebarCategorySorting) UnmarshalGraphQL(input interface{}) error {
chType, ok := input.(string)
if !ok {
return errors.New("wrong type")
}
*t = SidebarCategorySorting(chType)
return nil
}

View File

@@ -46,6 +46,7 @@ const (
APIURLSuffixV1 = "/api/v1"
APIURLSuffixV4 = "/api/v4"
APIURLSuffixV5 = "/api/v5"
APIURLSuffix = APIURLSuffixV4
)
@@ -5252,7 +5253,7 @@ func (c *Client4) GetGroupsAssociatedToChannelsByTeam(teamId string, opts GroupS
// GetGroups retrieves Mattermost Groups
func (c *Client4) GetGroups(opts GroupSearchOpts) ([]*Group, *Response, error) {
path := fmt.Sprintf(
"%s?include_member_count=%v&not_associated_to_team=%v&not_associated_to_channel=%v&filter_allow_reference=%v&q=%v&filter_parent_team_permitted=%v",
"%s?include_member_count=%v&not_associated_to_team=%v&not_associated_to_channel=%v&filter_allow_reference=%v&q=%v&filter_parent_team_permitted=%v&group_source=%v",
c.groupsRoute(),
opts.IncludeMemberCount,
opts.NotAssociatedToTeam,
@@ -5260,6 +5261,7 @@ func (c *Client4) GetGroups(opts GroupSearchOpts) ([]*Group, *Response, error) {
opts.FilterAllowReference,
opts.Q,
opts.FilterParentTeamPermitted,
opts.Source,
)
if opts.Since > 0 {
path = fmt.Sprintf("%s&since=%v", path, opts.Since)
@@ -7071,6 +7073,36 @@ func (c *Client4) GetGroup(groupID, etag string) (*Group, *Response, error) {
return &g, BuildResponse(r), nil
}
func (c *Client4) CreateGroup(group *Group) (*Group, *Response, error) {
groupJSON, jsonErr := json.Marshal(group)
if jsonErr != nil {
return nil, nil, NewAppError("CreateGroup", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError)
}
r, err := c.DoAPIPostBytes("/groups", groupJSON)
if err != nil {
return nil, BuildResponse(r), err
}
defer closeBody(r)
var p Group
if jsonErr := json.NewDecoder(r.Body).Decode(&p); jsonErr != nil {
return nil, nil, NewAppError("CreateGroup", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError)
}
return &p, BuildResponse(r), nil
}
func (c *Client4) DeleteGroup(groupID string) (*Group, *Response, error) {
r, err := c.DoAPIDelete(c.groupRoute(groupID))
if err != nil {
return nil, BuildResponse(r), err
}
defer closeBody(r)
var p Group
if jsonErr := json.NewDecoder(r.Body).Decode(&p); jsonErr != nil {
return nil, nil, NewAppError("DeleteGroup", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError)
}
return &p, BuildResponse(r), nil
}
func (c *Client4) PatchGroup(groupID string, patch *GroupPatch) (*Group, *Response, error) {
payload, _ := json.Marshal(patch)
r, err := c.DoAPIPut(c.groupRoute(groupID)+"/patch", string(payload))
@@ -7085,6 +7117,40 @@ func (c *Client4) PatchGroup(groupID string, patch *GroupPatch) (*Group, *Respon
return &g, BuildResponse(r), nil
}
func (c *Client4) UpsertGroupMembers(groupID string, userIds *GroupModifyMembers) ([]*GroupMember, *Response, error) {
payload, jsonErr := json.Marshal(userIds)
if jsonErr != nil {
return nil, nil, NewAppError("UpsertGroupMembers", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError)
}
r, err := c.DoAPIPostBytes(c.groupRoute(groupID)+"/members", payload)
if err != nil {
return nil, BuildResponse(r), err
}
defer closeBody(r)
var g []*GroupMember
if jsonErr := json.NewDecoder(r.Body).Decode(&g); jsonErr != nil {
return nil, nil, NewAppError("UpsertGroupMembers", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError)
}
return g, BuildResponse(r), nil
}
func (c *Client4) DeleteGroupMembers(groupID string, userIds *GroupModifyMembers) ([]*GroupMember, *Response, error) {
payload, jsonErr := json.Marshal(userIds)
if jsonErr != nil {
return nil, nil, NewAppError("DeleteGroupMembers", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError)
}
r, err := c.DoAPIDeleteBytes(c.groupRoute(groupID)+"/members", payload)
if err != nil {
return nil, BuildResponse(r), err
}
defer closeBody(r)
var g []*GroupMember
if jsonErr := json.NewDecoder(r.Body).Decode(&g); jsonErr != nil {
return nil, nil, NewAppError("DeleteGroupMembers", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError)
}
return g, BuildResponse(r), nil
}
func (c *Client4) LinkGroupSyncable(groupID, syncableID string, syncableType GroupSyncableType, patch *GroupSyncablePatch) (*GroupSyncable, *Response, error) {
payload, _ := json.Marshal(patch)
url := fmt.Sprintf("%s/link", c.groupSyncableRoute(groupID, syncableID, syncableType))
@@ -7435,6 +7501,20 @@ func (c *Client4) MarkNoticesViewed(ids []string) (*Response, error) {
return BuildResponse(r), nil
}
func (c *Client4) CompleteOnboarding(request *CompleteOnboardingRequest) (*Response, error) {
buf, err := json.Marshal(request)
if err != nil {
return nil, NewAppError("CompleteOnboarding", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError)
}
r, err := c.DoAPIPost(c.systemRoute()+"/onboarding/complete", string(buf))
if err != nil {
return BuildResponse(r), err
}
defer closeBody(r)
return BuildResponse(r), nil
}
// CreateUpload creates a new upload session.
func (c *Client4) CreateUpload(us *UploadSession) (*UploadSession, *Response, error) {
buf, err := json.Marshal(us)
@@ -7834,3 +7914,20 @@ func (c *Client4) GetAncillaryPermissions(subsectionPermissions []string) ([]str
json.NewDecoder(r.Body).Decode(&returnedPermissions)
return returnedPermissions, BuildResponse(r), nil
}
func (c *Client4) GetUsersWithInvalidEmails(page, perPage int) ([]*User, *Response, error) {
query := fmt.Sprintf("/invalid_emails?page=%v&per_page=%v", page, perPage)
r, err := c.DoAPIGet(c.usersRoute()+query, "")
if err != nil {
return nil, BuildResponse(r), err
}
defer closeBody(r)
var list []*User
if r.StatusCode == http.StatusNotModified {
return list, BuildResponse(r), nil
}
if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil {
return nil, nil, NewAppError("GetUsers", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError)
}
return list, BuildResponse(r), nil
}

View File

@@ -114,7 +114,7 @@ const (
TeamSettingsDefaultCustomDescriptionText = ""
TeamSettingsDefaultUserStatusAwayTimeout = 300
SqlSettingsDefaultDataSource = "postgres://mmuser:mostest@localhost/mattermost_test?sslmode=disable&connect_timeout=10"
SqlSettingsDefaultDataSource = "postgres://mmuser:mostest@localhost/mattermost_test?sslmode=disable&connect_timeout=10&binary_parameters=yes"
FileSettingsDefaultDirectory = "./data/"
@@ -305,6 +305,7 @@ type ServiceSettings struct {
EnableTesting *bool `access:"environment_developer,write_restrictable,cloud_restrictable"`
EnableDeveloper *bool `access:"environment_developer,write_restrictable,cloud_restrictable"`
DeveloperFlags *string `access:"environment_developer"`
EnableClientPerformanceDebugging *bool `access:"environment_developer,write_restrictable,cloud_restrictable"`
EnableOpenTracing *bool `access:"write_restrictable,cloud_restrictable"`
EnableSecurityFixAlert *bool `access:"environment_smtp,write_restrictable,cloud_restrictable"`
EnableInsecureOutgoingConnections *bool `access:"environment_web_server,write_restrictable,cloud_restrictable"`
@@ -366,6 +367,7 @@ type ServiceSettings struct {
ThreadAutoFollow *bool `access:"experimental_features"`
CollapsedThreads *string `access:"experimental_features"`
ManagedResourcePaths *string `access:"environment_web_server,write_restrictable,cloud_restrictable"`
EnableCustomGroups *bool `access:"site_users_and_teams"`
}
func (s *ServiceSettings) SetDefaults(isUpdate bool) {
@@ -422,6 +424,10 @@ func (s *ServiceSettings) SetDefaults(isUpdate bool) {
s.DeveloperFlags = NewString("")
}
if s.EnableClientPerformanceDebugging == nil {
s.EnableClientPerformanceDebugging = NewBool(false)
}
if s.EnableOpenTracing == nil {
s.EnableOpenTracing = NewBool(false)
}
@@ -782,6 +788,10 @@ func (s *ServiceSettings) SetDefaults(isUpdate bool) {
if s.ManagedResourcePaths == nil {
s.ManagedResourcePaths = NewString("")
}
if s.EnableCustomGroups == nil {
s.EnableCustomGroups = NewBool(true)
}
}
type ClusterSettings struct {

View File

@@ -8,6 +8,8 @@ import (
"encoding/json"
"fmt"
"time"
"github.com/graph-gophers/graphql-go"
)
const (
@@ -61,6 +63,12 @@ func (cs *CustomStatus) AreDurationAndExpirationTimeValid() bool {
return false
}
// ExpiresAt_ returns the time in a type that has the marshal/unmarshal methods
// attached to it.
func (cs *CustomStatus) ExpiresAt_() graphql.Time {
return graphql.Time{Time: cs.ExpiresAt}
}
func RuneToHexadecimalString(r rune) string {
return fmt.Sprintf("%04x", r)
}

View File

@@ -78,9 +78,12 @@ func (emoji *Emoji) IsValid() *AppError {
}
func IsValidEmojiName(name string) *AppError {
if name == "" || len(name) > EmojiNameMaxLength || !IsValidAlphaNumHyphenUnderscorePlus(name) || inSystemEmoji(name) {
if name == "" || len(name) > EmojiNameMaxLength || !IsValidAlphaNumHyphenUnderscorePlus(name) {
return NewAppError("Emoji.IsValid", "model.emoji.name.app_error", nil, "", http.StatusBadRequest)
}
if inSystemEmoji(name) {
return NewAppError("Emoji.IsValid", "model.emoji.system_emoji_name.app_error", nil, "", http.StatusBadRequest)
}
return nil
}

View File

@@ -41,18 +41,12 @@ type FeatureFlags struct {
// Enable the Global Header
GlobalHeader bool
// Enable different team menu button treatments, possible values = ("none", "by_team_name", "inverted_sidebar_bg_color")
AddChannelButton string
// Determine whether when a user gets created, they'll have noisy notifications e.g. Send desktop notifications for all activity
NewAccountNoisy bool
// Enable Calls plugin support in the mobile app
CallsMobile bool
// Start A/B tour tips automatically, possible values = ("none", "auto")
AutoTour string
// A dash separated list for feature flags to turn on for Boards
BoardsFeatureFlags string
@@ -68,6 +62,8 @@ type FeatureFlags struct {
// A/B test for whether radio buttons or toggle button is more effective in in-screen invite to team modal ("none", "toggle")
InviteToTeam string
CustomGroups bool
// Enable inline post editing
InlinePostEditing bool
@@ -75,6 +71,17 @@ type FeatureFlags struct {
BoardsDataRetention bool
NormalizeLdapDNs bool
EnableInactivityCheckJob bool
// Enable special onboarding flow for first admin
UseCaseOnboarding bool
// Enable Workspace optimization dashboard
WorkspaceOptimizationDashboard bool
// Enable GraphQL feature
GraphQL bool
}
func (f *FeatureFlags) SetDefaults() {
@@ -89,20 +96,22 @@ func (f *FeatureFlags) SetDefaults() {
f.PluginFocalboard = ""
f.PermalinkPreviews = true
f.GlobalHeader = true
f.AddChannelButton = "by_team_name"
f.NewAccountNoisy = false
f.CallsMobile = false
f.AutoTour = "none"
f.BoardsFeatureFlags = ""
f.AddMembersToChannel = "top"
f.GuidedChannelCreation = false
f.ResendInviteEmailInterval = ""
f.InviteToTeam = "none"
f.CustomGroups = true
f.InlinePostEditing = false
f.BoardsDataRetention = false
f.NormalizeLdapDNs = false
f.EnableInactivityCheckJob = true
f.UseCaseOnboarding = true
f.WorkspaceOptimizationDashboard = true
f.GraphQL = false
}
func (f *FeatureFlags) Plugins() map[string]string {
rFFVal := reflect.ValueOf(f).Elem()
rFFType := reflect.TypeOf(f).Elem()

View File

@@ -0,0 +1,26 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package model
import (
"net/http"
)
type GithubReleaseInfo struct {
Id int `json:"id"`
TagName string `json:"tag_name"`
Name string `json:"name"`
CreatedAt string `json:"created_at"`
PublishedAt string `json:"published_at"`
Body string `json:"body"`
Url string `json:"html_url"`
}
func (g *GithubReleaseInfo) IsValid() *AppError {
if g.Id == 0 {
return NewAppError("GithubReleaseInfo.IsValid", "model.github_release_info.is_valid.id.app_error", nil, "", http.StatusInternalServerError)
}
return nil
}

View File

@@ -9,7 +9,8 @@ import (
)
const (
GroupSourceLdap GroupSource = "ldap"
GroupSourceLdap GroupSource = "ldap"
GroupSourceCustom GroupSource = "custom"
GroupNameMaxLength = 64
GroupSourceMaxLength = 64
@@ -22,6 +23,7 @@ type GroupSource string
var allGroupSources = []GroupSource{
GroupSourceLdap,
GroupSourceCustom,
}
var groupSourcesRequiringRemoteID = []GroupSource{
@@ -34,7 +36,7 @@ type Group struct {
DisplayName string `json:"display_name"`
Description string `json:"description"`
Source GroupSource `json:"source"`
RemoteId string `json:"remote_id"`
RemoteId *string `json:"remote_id"`
CreateAt int64 `json:"create_at"`
UpdateAt int64 `json:"update_at"`
DeleteAt int64 `json:"delete_at"`
@@ -43,6 +45,11 @@ type Group struct {
AllowReference bool `json:"allow_reference"`
}
type GroupWithUserIds struct {
Group
UserIds []string `json:"user_ids"`
}
type GroupWithSchemeAdmin struct {
Group
SchemeAdmin *bool `db:"SyncableSchemeAdmin" json:"scheme_admin,omitempty"`
@@ -63,6 +70,8 @@ type GroupPatch struct {
DisplayName *string `json:"display_name"`
Description *string `json:"description"`
AllowReference *bool `json:"allow_reference"`
// For security reasons (including preventing unintended LDAP group synchronization) do no allow a Group's RemoteId or Source field to be
// included in patches.
}
type LdapGroupSearchOpts struct {
@@ -79,12 +88,21 @@ type GroupSearchOpts struct {
FilterAllowReference bool
PageOpts *PageOpts
Since int64
Source GroupSource
// FilterParentTeamPermitted filters the groups to the intersect of the
// set associated to the parent team and those returned by the query.
// If the parent team is not group-constrained or if NotAssociatedToChannel
// is not set then this option is ignored.
FilterParentTeamPermitted bool
// FilterHasMember filters the groups to the intersect of the
// set returned by the query and those that have the given user as a member.
FilterHasMember string
}
type GetGroupOpts struct {
IncludeMemberCount bool
}
type PageOpts struct {
@@ -97,6 +115,10 @@ type GroupStats struct {
TotalMemberCount int64 `json:"total_member_count"`
}
type GroupModifyMembers struct {
UserIds []string `json:"user_ids"`
}
func (group *Group) Patch(patch *GroupPatch) {
if patch.Name != nil {
group.Name = patch.Name
@@ -137,7 +159,7 @@ func (group *Group) IsValidForCreate() *AppError {
return NewAppError("Group.IsValidForCreate", "model.group.source.app_error", nil, "", http.StatusBadRequest)
}
if len(group.RemoteId) > GroupRemoteIDMaxLength || (group.RemoteId == "" && group.requiresRemoteId()) {
if (group.GetRemoteId() == "" && group.requiresRemoteId()) || len(group.GetRemoteId()) > GroupRemoteIDMaxLength {
return NewAppError("Group.IsValidForCreate", "model.group.remote_id.app_error", nil, "", http.StatusBadRequest)
}
@@ -188,3 +210,22 @@ func (group *Group) IsValidName() *AppError {
}
return nil
}
func (group *Group) GetName() string {
if group.Name == nil {
return ""
}
return *group.Name
}
func (group *Group) GetRemoteId() string {
if group.RemoteId == nil {
return ""
}
return *group.RemoteId
}
type GroupsWithCount struct {
Groups []*Group `json:"groups"`
TotalCount int64 `json:"total_count"`
}

View File

@@ -78,29 +78,6 @@ func (j *Job) IsValid() *AppError {
return NewAppError("Job.IsValid", "model.job.is_valid.create_at.app_error", nil, "id="+j.Id, http.StatusBadRequest)
}
switch j.Type {
case JobTypeDataRetention:
case JobTypeElasticsearchPostIndexing:
case JobTypeElasticsearchPostAggregation:
case JobTypeBlevePostIndexing:
case JobTypeLdapSync:
case JobTypeMessageExport:
case JobTypeMigrations:
case JobTypePlugins:
case JobTypeProductNotices:
case JobTypeExpiryNotify:
case JobTypeActiveUsers:
case JobTypeImportProcess:
case JobTypeImportDelete:
case JobTypeExportProcess:
case JobTypeExportDelete:
case JobTypeCloud:
case JobTypeResendInvitationEmail:
case JobTypeExtractContent:
default:
return NewAppError("Job.IsValid", "model.job.is_valid.type.app_error", nil, "id="+j.Id, http.StatusBadRequest)
}
switch j.Status {
case JobStatusPending:
case JobStatusInProgress:
@@ -119,11 +96,10 @@ type Worker interface {
Run()
Stop()
JobChannel() chan<- Job
IsEnabled(cfg *Config) bool
}
type Scheduler interface {
Name() string
JobType() string
Enabled(cfg *Config) bool
NextScheduleTime(cfg *Config, now time.Time, pendingJobs bool, lastSuccessfulJob *Job) *time.Time
ScheduleJob(cfg *Config, pendingJobs bool, lastSuccessfulJob *Job) (*Job, *AppError)

View File

@@ -323,6 +323,12 @@ func NewTestLicense(features ...string) *License {
return ret
}
func NewTestLicenseSKU(skuShortName string, features ...string) *License {
lic := NewTestLicense(features...)
lic.SkuShortName = skuShortName
return lic
}
func (lr *LicenseRecord) IsValid() *AppError {
if !IsValidId(lr.Id) {
return NewAppError("LicenseRecord.IsValid", "model.license_record.is_valid.id.app_error", nil, "", http.StatusBadRequest)

View File

@@ -36,4 +36,5 @@ const (
MigrationKeyAddAboutSubsectionPermissions = "about_subsection_permissions"
MigrationKeyAddIntegrationsSubsectionPermissions = "integrations_subsection_permissions"
MigrationKeyAddPlaybooksPermissions = "playbooks_permissions"
MigrationKeyAddCustomUserGroupsPermissions = "custom_groups_permissions"
)

View File

@@ -0,0 +1,25 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package model
import (
"encoding/json"
"io"
)
// CompleteOnboardingRequest describes parameters of the requested plugin.
type CompleteOnboardingRequest struct {
InstallPlugins []string `json:"install_plugins"` // InstallPlugins is a list of plugins to be installed
}
// CompleteOnboardingRequest decodes a json-encoded request from the given io.Reader.
func CompleteOnboardingRequestFromReader(reader io.Reader) (*CompleteOnboardingRequest, error) {
var r *CompleteOnboardingRequest
err := json.NewDecoder(reader).Decode(&r)
if err != nil {
return nil, err
}
return r, nil
}

View File

@@ -7,6 +7,7 @@ const (
PermissionScopeSystem = "system_scope"
PermissionScopeTeam = "team_scope"
PermissionScopeChannel = "channel_scope"
PermissionScopeGroup = "group_scope"
PermissionScopePlaybook = "playbook_scope"
PermissionScopeRun = "run_scope"
)
@@ -355,6 +356,11 @@ var PermissionRunView *Permission
// admin functions but not others
var PermissionManageSystem *Permission
var PermissionCreateCustomGroup *Permission
var PermissionManageCustomGroupMembers *Permission
var PermissionEditCustomGroup *Permission
var PermissionDeleteCustomGroup *Permission
var AllPermissions []*Permission
var DeprecatedPermissions []*Permission
@@ -1914,6 +1920,34 @@ func initializePermissions() {
PermissionScopeSystem,
}
PermissionCreateCustomGroup = &Permission{
"create_custom_group",
"authentication.permissions.create_custom_group.name",
"authentication.permissions.create_custom_group.description",
PermissionScopeSystem,
}
PermissionManageCustomGroupMembers = &Permission{
"manage_custom_group_members",
"authentication.permissions.manage_custom_group_members.name",
"authentication.permissions.manage_custom_group_members.description",
PermissionScopeGroup,
}
PermissionEditCustomGroup = &Permission{
"edit_custom_group",
"authentication.permissions.edit_custom_group.name",
"authentication.permissions.edit_custom_group.description",
PermissionScopeGroup,
}
PermissionDeleteCustomGroup = &Permission{
"delete_custom_group",
"authentication.permissions.delete_custom_group.name",
"authentication.permissions.delete_custom_group.description",
PermissionScopeGroup,
}
// Playbooks
PermissionPublicPlaybookCreate = &Permission{
"playbook_public_create",
@@ -2200,6 +2234,7 @@ func initializePermissions() {
PermissionGetLogs,
PermissionReadLicenseInformation,
PermissionManageLicenseInformation,
PermissionCreateCustomGroup,
}
TeamScopedPermissions := []*Permission{
@@ -2259,6 +2294,12 @@ func initializePermissions() {
PermissionUseGroupMentions,
}
GroupScopedPermissions := []*Permission{
PermissionManageCustomGroupMembers,
PermissionEditCustomGroup,
PermissionDeleteCustomGroup,
}
DeprecatedPermissions = []*Permission{
PermissionPermanentDeleteUser,
PermissionManageWebhooks,
@@ -2307,6 +2348,7 @@ func initializePermissions() {
AllPermissions = append(AllPermissions, ChannelScopedPermissions...)
AllPermissions = append(AllPermissions, SysconsoleReadPermissions...)
AllPermissions = append(AllPermissions, SysconsoleWritePermissions...)
AllPermissions = append(AllPermissions, GroupScopedPermissions...)
AllPermissions = append(AllPermissions, PlaybookScopedPermissions...)
AllPermissions = append(AllPermissions, RunScopedPermissions...)

View File

@@ -0,0 +1,9 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package model
// OnInstallEvent is sent to the plugin when it gets installed.
type OnInstallEvent struct {
UserId string // The user who installed the plugin
}

View File

@@ -87,7 +87,7 @@ type Post struct {
// MessageSource will contain the message as submitted by the user if Message has been modified
// by Mattermost for presentation (e.g if an image proxy is being used). It should be used to
// populate edit boxes if present.
MessageSource string `json:"message_source,omitempty" db:"-"`
MessageSource string `json:"message_source,omitempty"`
Type string `json:"type"`
propsMu sync.RWMutex `db:"-"` // Unexported mutex used to guard Post.Props.
@@ -95,16 +95,16 @@ type Post struct {
Hashtags string `json:"hashtags"`
Filenames StringArray `json:"-"` // Deprecated, do not use this field any more
FileIds StringArray `json:"file_ids,omitempty"`
PendingPostId string `json:"pending_post_id" db:"-"`
PendingPostId string `json:"pending_post_id"`
HasReactions bool `json:"has_reactions,omitempty"`
RemoteId *string `json:"remote_id,omitempty"`
// Transient data populated before sending a post to the client
ReplyCount int64 `json:"reply_count" db:"-"`
LastReplyAt int64 `json:"last_reply_at" db:"-"`
Participants []*User `json:"participants" db:"-"`
IsFollowing *bool `json:"is_following,omitempty" db:"-"` // for root posts in collapsed thread mode indicates if the current user is following this thread
Metadata *PostMetadata `json:"metadata,omitempty" db:"-"`
ReplyCount int64 `json:"reply_count"`
LastReplyAt int64 `json:"last_reply_at"`
Participants []*User `json:"participants"`
IsFollowing *bool `json:"is_following,omitempty"` // for root posts in collapsed thread mode indicates if the current user is following this thread
Metadata *PostMetadata `json:"metadata,omitempty"`
}
type PostEphemeral struct {

View File

@@ -4,6 +4,7 @@
package model
import (
"fmt"
"strings"
)
@@ -42,6 +43,8 @@ func init() {
ChannelUserRoleId,
ChannelAdminRoleId,
CustomGroupUserRoleId,
PlaybookAdminRoleId,
PlaybookMemberRoleId,
RunAdminRoleId,
@@ -367,6 +370,8 @@ const (
ChannelUserRoleId = "channel_user"
ChannelAdminRoleId = "channel_admin"
CustomGroupUserRoleId = "custom_group_user"
PlaybookAdminRoleId = "playbook_admin"
PlaybookMemberRoleId = "playbook_member"
RunAdminRoleId = "run_admin"
@@ -379,6 +384,7 @@ const (
RoleScopeSystem RoleScope = "System"
RoleScopeTeam RoleScope = "Team"
RoleScopeChannel RoleScope = "Channel"
RoleScopeGroup RoleScope = "Group"
RoleTypeGuest RoleType = "Guest"
RoleTypeUser RoleType = "User"
@@ -683,6 +689,13 @@ func IsValidRoleName(roleName string) bool {
func MakeDefaultRoles() map[string]*Role {
roles := make(map[string]*Role)
roles[CustomGroupUserRoleId] = &Role{
Name: CustomGroupUserRoleId,
DisplayName: fmt.Sprintf("authentication.roles.%s.name", CustomGroupUserRoleId),
Description: fmt.Sprintf("authentication.roles.%s.description", CustomGroupUserRoleId),
Permissions: []string{},
}
roles[ChannelGuestRoleId] = &Role{
Name: "channel_guest",
DisplayName: "authentication.roles.channel_guest.name",
@@ -895,6 +908,10 @@ func MakeDefaultRoles() map[string]*Role {
PermissionCreateGroupChannel.Id,
PermissionViewMembers.Id,
PermissionCreateTeam.Id,
PermissionCreateCustomGroup.Id,
PermissionEditCustomGroup.Id,
PermissionDeleteCustomGroup.Id,
PermissionManageCustomGroupMembers.Id,
},
SchemeManaged: true,
BuiltIn: true,

View File

@@ -34,6 +34,19 @@ func (s *Status) ToJSON() ([]byte, error) {
return json.Marshal(sCopy)
}
// The following are some GraphQL methods necessary to return the
// data in float64 type. The spec doesn't support 64 bit integers,
// so we have to pass the data in float64. The _ at the end is
// a hack to keep the attribute name same in GraphQL schema.
func (s *Status) LastActivityAt_() float64 {
return float64(s.LastActivityAt)
}
func (s *Status) DNDEndTime_() float64 {
return float64(s.DNDEndTime)
}
func StatusListToJSON(u []*Status) ([]byte, error) {
list := make([]Status, len(u))
for i, s := range u {

View File

@@ -30,8 +30,8 @@ const (
SystemWarnMetricNumberOfActiveUsers500 = "warn_metric_number_of_active_users_500"
SystemWarnMetricNumberOfPosts2m = "warn_metric_number_of_posts_2M"
SystemWarnMetricLastRunTimestampKey = "LastWarnMetricRunTimestamp"
SystemMetricSupportEmailNotConfigured = "warn_metric_support_email_not_configured"
SystemFirstAdminVisitMarketplace = "FirstAdminVisitMarketplace"
SystemFirstAdminSetupComplete = "FirstAdminSetupComplete"
AwsMeteringReportInterval = 1
AwsMeteringDimensionUsageHrs = "UsageHrs"
UserLimitOverageCycleEndDate = "UserLimitOverageCycleEndDate"
@@ -147,13 +147,6 @@ var WarnMetricsTable = map[string]WarnMetric{
IsBotOnly: false,
IsRunOnce: true,
},
SystemMetricSupportEmailNotConfigured: {
Id: SystemMetricSupportEmailNotConfigured,
Limit: -1,
IsBotOnly: true,
IsRunOnce: false,
SkipAction: true,
},
}
type WarnMetric struct {

View File

@@ -40,7 +40,7 @@ type Team struct {
LastTeamIconUpdate int64 `json:"last_team_icon_update,omitempty"`
SchemeId *string `json:"scheme_id"`
GroupConstrained *bool `json:"group_constrained"`
PolicyID *string `json:"policy_id" db:"-"`
PolicyID *string `json:"policy_id"`
}
type TeamPatch struct {

View File

@@ -125,3 +125,9 @@ func (o *TeamMember) PreUpdate() {
func (o *TeamMember) GetRoles() []string {
return strings.Fields(o.Roles)
}
// DeleteAt_ returns the deleteAt value in float64. This is necessary to work
// with GraphQL since it doesn't support 64 bit integers.
func (o *TeamMember) DeleteAt_() float64 {
return float64(o.DeleteAt)
}

View File

@@ -3,11 +3,24 @@
package model
// Thread tracks the metadata associated with a root post and its reply posts.
//
// Note that Thread metadata does not exist until the first reply to a root post.
type Thread struct {
PostId string `json:"id"`
ChannelId string `json:"channel_id"`
ReplyCount int64 `json:"reply_count"`
LastReplyAt int64 `json:"last_reply_at"`
// PostId is the root post of the thread.
PostId string `json:"id"`
// ChannelId is the channel in which the thread was posted.
ChannelId string `json:"channel_id"`
// ReplyCount is the number of replies to the thread (excluding deleted posts).
ReplyCount int64 `json:"reply_count"`
// LastReplyAt is the timestamp of the most recent post to the thread.
LastReplyAt int64 `json:"last_reply_at"`
// Participants is a list of user ids that have replied to the thread, sorted by the oldest
// to newest. Note that the root post author is not included in this list until they reply.
Participants StringArray `json:"participants"`
}
@@ -62,11 +75,37 @@ func (o *Thread) Etag() string {
return Etag(o.PostId, o.LastReplyAt)
}
// ThreadMembership models the relationship between a user and a thread of posts, with a similar
// data structure as ChannelMembership.
type ThreadMembership struct {
PostId string `json:"post_id"`
UserId string `json:"user_id"`
Following bool `json:"following"`
LastViewed int64 `json:"last_view_at"`
LastUpdated int64 `json:"last_update_at"`
UnreadMentions int64 `json:"unread_mentions"`
// PostId is the root post id of the thread in question.
PostId string `json:"post_id"`
// UserId is the user whose membership in the thread is being tracked.
UserId string `json:"user_id"`
// Following tracks whether the user is following the given thread. This defaults to true
// when a ThreadMembership record is created (a record doesn't exist until the user first
// starts following the thread), but the user can stop following or resume following at
// will.
Following bool `json:"following"`
// LastUpdated is either the creation time of the membership record, or the last time the
// membership record was changed (e.g. started/stopped following, viewed thread, mention
// count change).
//
// This field is used to constrain queries of thread memberships to those updated after
// a given timestamp (e.g. on websocket reconnect). It's also used as the time column for
// deletion decisions during any configured retention policy.
LastUpdated int64 `json:"last_update_at"`
// LastViewed is the last time the user viewed this thread. It is the thread analogue to
// the ChannelMembership's LastViewedAt and is used to decide when there are new replies
// for the user and where the user should start reading.
LastViewed int64 `json:"last_view_at"`
// UnreadMentions is the number of unseen at-mentions for the user in the given thread. It
// is the thread analogue to the ChannelMembership's MentionCount, and is used to highlight
// threads with the mention count.
UnreadMentions int64 `json:"unread_mentions"`
}

View File

@@ -12,8 +12,9 @@ import (
type UploadType string
const (
UploadTypeAttachment UploadType = "attachment"
UploadTypeImport UploadType = "import"
UploadTypeAttachment UploadType = "attachment"
UploadTypeImport UploadType = "import"
IncompleteUploadSuffix = ".tmp"
)
// UploadNoUserID is a "fake" user id used by the API layer when in local mode.

View File

@@ -95,13 +95,13 @@ type User struct {
MfaActive bool `json:"mfa_active,omitempty"`
MfaSecret string `json:"mfa_secret,omitempty"`
RemoteId *string `json:"remote_id,omitempty"`
LastActivityAt int64 `db:"-" json:"last_activity_at,omitempty"`
IsBot bool `db:"-" json:"is_bot,omitempty"`
BotDescription string `db:"-" json:"bot_description,omitempty"`
BotLastIconUpdate int64 `db:"-" json:"bot_last_icon_update,omitempty"`
TermsOfServiceId string `db:"-" json:"terms_of_service_id,omitempty"`
TermsOfServiceCreateAt int64 `db:"-" json:"terms_of_service_create_at,omitempty"`
DisableWelcomeEmail bool `db:"-" json:"disable_welcome_email"`
LastActivityAt int64 `json:"last_activity_at,omitempty"`
IsBot bool `json:"is_bot,omitempty"`
BotDescription string `json:"bot_description,omitempty"`
BotLastIconUpdate int64 `json:"bot_last_icon_update,omitempty"`
TermsOfServiceId string `json:"terms_of_service_id,omitempty"`
TermsOfServiceCreateAt int64 `json:"terms_of_service_create_at,omitempty"`
DisableWelcomeEmail bool `json:"disable_welcome_email"`
}
//msgp UserMap
@@ -409,6 +409,23 @@ func (u *User) PreSave() {
}
}
// The following are some GraphQL methods necessary to return the
// data in float64 type. The spec doesn't support 64 bit integers,
// so we have to pass the data in float64. The _ at the end is
// a hack to keep the attribute name same in GraphQL schema.
func (u *User) CreateAt_() float64 {
return float64(u.CreateAt)
}
func (u *User) DeleteAt_() float64 {
return float64(u.DeleteAt)
}
func (u *User) LastPictureUpdateAt() float64 {
return float64(u.LastPictureUpdate)
}
// PreUpdate should be run before updating the user in the db.
func (u *User) PreUpdate() {
u.Username = SanitizeUnicode(u.Username)
@@ -630,6 +647,15 @@ func (u *User) GetCustomStatus() *CustomStatus {
return o
}
func (u *User) CustomStatus() *CustomStatus {
var o *CustomStatus
data := u.Props[UserPropsKeyCustomStatus]
_ = json.Unmarshal([]byte(data), &o)
return o
}
func (u *User) ClearCustomStatus() {
u.MakeNonNil()
u.Props[UserPropsKeyCustomStatus] = ""

View File

@@ -14,6 +14,8 @@ type UserGetOptions struct {
NotInChannelId string
// Filters the users in the group
InGroupId string
// Filters the users not in the group
NotInGroupId string
// Filters the users group constrained
GroupConstrained bool
// Filters the users without a team

View File

@@ -22,6 +22,7 @@ type UserSearch struct {
Roles []string `json:"roles"`
ChannelRoles []string `json:"channel_roles"`
TeamRoles []string `json:"team_roles"`
NotInGroupId string `json:"not_in_group_id"`
}
// UserSearchOptions captures internal parameters derived from the user's permissions and a

View File

@@ -132,6 +132,24 @@ func (m StringMap) Value() (driver.Value, error) {
return string(j), err
}
func (StringMap) ImplementsGraphQLType(name string) bool {
return name == "StringMap"
}
func (m StringMap) MarshalJSON() ([]byte, error) {
return json.Marshal((map[string]string)(m))
}
func (m *StringMap) UnmarshalGraphQL(input interface{}) error {
json, ok := input.(map[string]string)
if !ok {
return errors.New("wrong type")
}
*m = json
return nil
}
func (si *StringInterface) Scan(value interface{}) error {
if value == nil {
return nil

View File

@@ -13,8 +13,7 @@ import (
// It should be maintained in chronological order with most current
// release at the front of the list.
var versions = []string{
"6.4.2",
"6.4.1",
"6.5.0",
"6.4.0",
"6.3.0",
"6.2.0",

View File

@@ -62,6 +62,8 @@ const (
WebsocketEventReceivedGroupNotAssociatedToTeam = "received_group_not_associated_to_team"
WebsocketEventReceivedGroupAssociatedToChannel = "received_group_associated_to_channel"
WebsocketEventReceivedGroupNotAssociatedToChannel = "received_group_not_associated_to_channel"
WebsocketEventGroupMemberDelete = "group_member_deleted"
WebsocketEventGroupMemberAdd = "group_member_add"
WebsocketEventSidebarCategoryCreated = "sidebar_category_created"
WebsocketEventSidebarCategoryUpdated = "sidebar_category_updated"
WebsocketEventSidebarCategoryDeleted = "sidebar_category_deleted"
@@ -88,6 +90,9 @@ type WebsocketBroadcast struct {
TeamId string `json:"team_id"` // broadcast only occurs for users in this team
ContainsSanitizedData bool `json:"-"`
ContainsSensitiveData bool `json:"-"`
// ReliableClusterSend indicates whether or not the message should
// be sent through the cluster using the reliable, TCP backed channel.
ReliableClusterSend bool `json:"-"`
}
func (wb *WebsocketBroadcast) copy() *WebsocketBroadcast {