github.com/haalcala/mattermost-server-change-repo/v5@v5.33.2/model/group.go (about)

     1  // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
     2  // See LICENSE.txt for license information.
     3  
     4  package model
     5  
     6  import (
     7  	"encoding/json"
     8  	"io"
     9  	"net/http"
    10  	"regexp"
    11  )
    12  
    13  const (
    14  	GroupSourceLdap GroupSource = "ldap"
    15  
    16  	GroupNameMaxLength        = 64
    17  	GroupSourceMaxLength      = 64
    18  	GroupDisplayNameMaxLength = 128
    19  	GroupDescriptionMaxLength = 1024
    20  	GroupRemoteIDMaxLength    = 48
    21  )
    22  
    23  type GroupSource string
    24  
    25  var allGroupSources = []GroupSource{
    26  	GroupSourceLdap,
    27  }
    28  
    29  var groupSourcesRequiringRemoteID = []GroupSource{
    30  	GroupSourceLdap,
    31  }
    32  
    33  type Group struct {
    34  	Id             string      `json:"id"`
    35  	Name           *string     `json:"name,omitempty"`
    36  	DisplayName    string      `json:"display_name"`
    37  	Description    string      `json:"description"`
    38  	Source         GroupSource `json:"source"`
    39  	RemoteId       string      `json:"remote_id"`
    40  	CreateAt       int64       `json:"create_at"`
    41  	UpdateAt       int64       `json:"update_at"`
    42  	DeleteAt       int64       `json:"delete_at"`
    43  	HasSyncables   bool        `db:"-" json:"has_syncables"`
    44  	MemberCount    *int        `db:"-" json:"member_count,omitempty"`
    45  	AllowReference bool        `json:"allow_reference"`
    46  }
    47  
    48  type GroupWithSchemeAdmin struct {
    49  	Group
    50  	SchemeAdmin *bool `db:"SyncableSchemeAdmin" json:"scheme_admin,omitempty"`
    51  }
    52  
    53  type GroupsAssociatedToChannelWithSchemeAdmin struct {
    54  	ChannelId string `json:"channel_id"`
    55  	Group
    56  	SchemeAdmin *bool `db:"SyncableSchemeAdmin" json:"scheme_admin,omitempty"`
    57  }
    58  type GroupsAssociatedToChannel struct {
    59  	ChannelId string                  `json:"channel_id"`
    60  	Groups    []*GroupWithSchemeAdmin `json:"groups"`
    61  }
    62  
    63  type GroupPatch struct {
    64  	Name           *string `json:"name"`
    65  	DisplayName    *string `json:"display_name"`
    66  	Description    *string `json:"description"`
    67  	AllowReference *bool   `json:"allow_reference"`
    68  }
    69  
    70  type LdapGroupSearchOpts struct {
    71  	Q            string
    72  	IsLinked     *bool
    73  	IsConfigured *bool
    74  }
    75  
    76  type GroupSearchOpts struct {
    77  	Q                      string
    78  	NotAssociatedToTeam    string
    79  	NotAssociatedToChannel string
    80  	IncludeMemberCount     bool
    81  	FilterAllowReference   bool
    82  	PageOpts               *PageOpts
    83  	Since                  int64
    84  
    85  	// FilterParentTeamPermitted filters the groups to the intersect of the
    86  	// set associated to the parent team and those returned by the query.
    87  	// If the parent team is not group-constrained or if NotAssociatedToChannel
    88  	// is not set then this option is ignored.
    89  	FilterParentTeamPermitted bool
    90  }
    91  
    92  type PageOpts struct {
    93  	Page    int
    94  	PerPage int
    95  }
    96  
    97  type GroupStats struct {
    98  	GroupID          string `json:"group_id"`
    99  	TotalMemberCount int64  `json:"total_member_count"`
   100  }
   101  
   102  func (group *Group) Patch(patch *GroupPatch) {
   103  	if patch.Name != nil {
   104  		group.Name = patch.Name
   105  	}
   106  	if patch.DisplayName != nil {
   107  		group.DisplayName = *patch.DisplayName
   108  	}
   109  	if patch.Description != nil {
   110  		group.Description = *patch.Description
   111  	}
   112  	if patch.AllowReference != nil {
   113  		group.AllowReference = *patch.AllowReference
   114  	}
   115  }
   116  
   117  func (group *Group) IsValidForCreate() *AppError {
   118  	err := group.IsValidName()
   119  	if err != nil {
   120  		return err
   121  	}
   122  
   123  	if l := len(group.DisplayName); l == 0 || l > GroupDisplayNameMaxLength {
   124  		return NewAppError("Group.IsValidForCreate", "model.group.display_name.app_error", map[string]interface{}{"GroupDisplayNameMaxLength": GroupDisplayNameMaxLength}, "", http.StatusBadRequest)
   125  	}
   126  
   127  	if len(group.Description) > GroupDescriptionMaxLength {
   128  		return NewAppError("Group.IsValidForCreate", "model.group.description.app_error", map[string]interface{}{"GroupDescriptionMaxLength": GroupDescriptionMaxLength}, "", http.StatusBadRequest)
   129  	}
   130  
   131  	isValidSource := false
   132  	for _, groupSource := range allGroupSources {
   133  		if group.Source == groupSource {
   134  			isValidSource = true
   135  			break
   136  		}
   137  	}
   138  	if !isValidSource {
   139  		return NewAppError("Group.IsValidForCreate", "model.group.source.app_error", nil, "", http.StatusBadRequest)
   140  	}
   141  
   142  	if len(group.RemoteId) > GroupRemoteIDMaxLength || (group.RemoteId == "" && group.requiresRemoteId()) {
   143  		return NewAppError("Group.IsValidForCreate", "model.group.remote_id.app_error", nil, "", http.StatusBadRequest)
   144  	}
   145  
   146  	return nil
   147  }
   148  
   149  func (group *Group) requiresRemoteId() bool {
   150  	for _, groupSource := range groupSourcesRequiringRemoteID {
   151  		if groupSource == group.Source {
   152  			return true
   153  		}
   154  	}
   155  	return false
   156  }
   157  
   158  func (group *Group) IsValidForUpdate() *AppError {
   159  	if !IsValidId(group.Id) {
   160  		return NewAppError("Group.IsValidForUpdate", "app.group.id.app_error", nil, "", http.StatusBadRequest)
   161  	}
   162  	if group.CreateAt == 0 {
   163  		return NewAppError("Group.IsValidForUpdate", "model.group.create_at.app_error", nil, "", http.StatusBadRequest)
   164  	}
   165  	if group.UpdateAt == 0 {
   166  		return NewAppError("Group.IsValidForUpdate", "model.group.update_at.app_error", nil, "", http.StatusBadRequest)
   167  	}
   168  	if err := group.IsValidForCreate(); err != nil {
   169  		return err
   170  	}
   171  	return nil
   172  }
   173  
   174  func (group *Group) ToJson() string {
   175  	b, _ := json.Marshal(group)
   176  	return string(b)
   177  }
   178  
   179  var validGroupnameChars = regexp.MustCompile(`^[a-z0-9\.\-_]+$`)
   180  
   181  func (group *Group) IsValidName() *AppError {
   182  
   183  	if group.Name == nil {
   184  		if group.AllowReference {
   185  			return NewAppError("Group.IsValidName", "model.group.name.app_error", map[string]interface{}{"GroupNameMaxLength": GroupNameMaxLength}, "", http.StatusBadRequest)
   186  		}
   187  	} else {
   188  		if l := len(*group.Name); l == 0 || l > GroupNameMaxLength {
   189  			return NewAppError("Group.IsValidName", "model.group.name.invalid_length.app_error", map[string]interface{}{"GroupNameMaxLength": GroupNameMaxLength}, "", http.StatusBadRequest)
   190  		}
   191  
   192  		if !validGroupnameChars.MatchString(*group.Name) {
   193  			return NewAppError("Group.IsValidName", "model.group.name.invalid_chars.app_error", nil, "", http.StatusBadRequest)
   194  		}
   195  	}
   196  	return nil
   197  }
   198  
   199  func GroupFromJson(data io.Reader) *Group {
   200  	var group *Group
   201  	json.NewDecoder(data).Decode(&group)
   202  	return group
   203  }
   204  
   205  func GroupsFromJson(data io.Reader) []*Group {
   206  	var groups []*Group
   207  	json.NewDecoder(data).Decode(&groups)
   208  	return groups
   209  }
   210  
   211  func GroupPatchFromJson(data io.Reader) *GroupPatch {
   212  	var groupPatch *GroupPatch
   213  	json.NewDecoder(data).Decode(&groupPatch)
   214  	return groupPatch
   215  }
   216  
   217  func GroupStatsFromJson(data io.Reader) *GroupStats {
   218  	var groupStats *GroupStats
   219  	json.NewDecoder(data).Decode(&groupStats)
   220  	return groupStats
   221  }