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 }