github.com/mattermosttest/mattermost-server/v5@v5.0.0-20200917143240-9dfa12e121f9/model/team.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 "fmt" 9 "io" 10 "net/http" 11 "regexp" 12 "strings" 13 "unicode/utf8" 14 ) 15 16 const ( 17 TEAM_OPEN = "O" 18 TEAM_INVITE = "I" 19 TEAM_ALLOWED_DOMAINS_MAX_LENGTH = 500 20 TEAM_COMPANY_NAME_MAX_LENGTH = 64 21 TEAM_DESCRIPTION_MAX_LENGTH = 255 22 TEAM_DISPLAY_NAME_MAX_RUNES = 64 23 TEAM_EMAIL_MAX_LENGTH = 128 24 TEAM_NAME_MAX_LENGTH = 64 25 TEAM_NAME_MIN_LENGTH = 2 26 ) 27 28 type Team struct { 29 Id string `json:"id"` 30 CreateAt int64 `json:"create_at"` 31 UpdateAt int64 `json:"update_at"` 32 DeleteAt int64 `json:"delete_at"` 33 DisplayName string `json:"display_name"` 34 Name string `json:"name"` 35 Description string `json:"description"` 36 Email string `json:"email"` 37 Type string `json:"type"` 38 CompanyName string `json:"company_name"` 39 AllowedDomains string `json:"allowed_domains"` 40 InviteId string `json:"invite_id"` 41 AllowOpenInvite bool `json:"allow_open_invite"` 42 LastTeamIconUpdate int64 `json:"last_team_icon_update,omitempty"` 43 SchemeId *string `json:"scheme_id"` 44 GroupConstrained *bool `json:"group_constrained"` 45 } 46 47 type TeamPatch struct { 48 DisplayName *string `json:"display_name"` 49 Description *string `json:"description"` 50 CompanyName *string `json:"company_name"` 51 AllowedDomains *string `json:"allowed_domains"` 52 AllowOpenInvite *bool `json:"allow_open_invite"` 53 GroupConstrained *bool `json:"group_constrained"` 54 } 55 56 type TeamForExport struct { 57 Team 58 SchemeName *string 59 } 60 61 type Invites struct { 62 Invites []map[string]string `json:"invites"` 63 } 64 65 type TeamsWithCount struct { 66 Teams []*Team `json:"teams"` 67 TotalCount int64 `json:"total_count"` 68 } 69 70 func InvitesFromJson(data io.Reader) *Invites { 71 var o *Invites 72 json.NewDecoder(data).Decode(&o) 73 return o 74 } 75 76 func (o *Invites) ToEmailList() []string { 77 emailList := make([]string, len(o.Invites)) 78 for _, invite := range o.Invites { 79 emailList = append(emailList, invite["email"]) 80 } 81 return emailList 82 } 83 84 func (o *Invites) ToJson() string { 85 b, _ := json.Marshal(o) 86 return string(b) 87 } 88 89 func (o *Team) ToJson() string { 90 b, _ := json.Marshal(o) 91 return string(b) 92 } 93 94 func TeamFromJson(data io.Reader) *Team { 95 var o *Team 96 json.NewDecoder(data).Decode(&o) 97 return o 98 } 99 100 func TeamMapToJson(u map[string]*Team) string { 101 b, _ := json.Marshal(u) 102 return string(b) 103 } 104 105 func TeamMapFromJson(data io.Reader) map[string]*Team { 106 var teams map[string]*Team 107 json.NewDecoder(data).Decode(&teams) 108 return teams 109 } 110 111 func TeamListToJson(t []*Team) string { 112 b, _ := json.Marshal(t) 113 return string(b) 114 } 115 116 func TeamsWithCountToJson(tlc *TeamsWithCount) []byte { 117 b, _ := json.Marshal(tlc) 118 return b 119 } 120 121 func TeamsWithCountFromJson(data io.Reader) *TeamsWithCount { 122 var twc *TeamsWithCount 123 json.NewDecoder(data).Decode(&twc) 124 return twc 125 } 126 127 func TeamListFromJson(data io.Reader) []*Team { 128 var teams []*Team 129 json.NewDecoder(data).Decode(&teams) 130 return teams 131 } 132 133 func (o *Team) Etag() string { 134 return Etag(o.Id, o.UpdateAt) 135 } 136 137 func (o *Team) IsValid() *AppError { 138 139 if !IsValidId(o.Id) { 140 return NewAppError("Team.IsValid", "model.team.is_valid.id.app_error", nil, "", http.StatusBadRequest) 141 } 142 143 if o.CreateAt == 0 { 144 return NewAppError("Team.IsValid", "model.team.is_valid.create_at.app_error", nil, "id="+o.Id, http.StatusBadRequest) 145 } 146 147 if o.UpdateAt == 0 { 148 return NewAppError("Team.IsValid", "model.team.is_valid.update_at.app_error", nil, "id="+o.Id, http.StatusBadRequest) 149 } 150 151 if len(o.Email) > TEAM_EMAIL_MAX_LENGTH { 152 return NewAppError("Team.IsValid", "model.team.is_valid.email.app_error", nil, "id="+o.Id, http.StatusBadRequest) 153 } 154 155 if len(o.Email) > 0 && !IsValidEmail(o.Email) { 156 return NewAppError("Team.IsValid", "model.team.is_valid.email.app_error", nil, "id="+o.Id, http.StatusBadRequest) 157 } 158 159 if utf8.RuneCountInString(o.DisplayName) == 0 || utf8.RuneCountInString(o.DisplayName) > TEAM_DISPLAY_NAME_MAX_RUNES { 160 return NewAppError("Team.IsValid", "model.team.is_valid.name.app_error", nil, "id="+o.Id, http.StatusBadRequest) 161 } 162 163 if len(o.Name) > TEAM_NAME_MAX_LENGTH { 164 return NewAppError("Team.IsValid", "model.team.is_valid.url.app_error", nil, "id="+o.Id, http.StatusBadRequest) 165 } 166 167 if len(o.Description) > TEAM_DESCRIPTION_MAX_LENGTH { 168 return NewAppError("Team.IsValid", "model.team.is_valid.description.app_error", nil, "id="+o.Id, http.StatusBadRequest) 169 } 170 171 if len(o.InviteId) == 0 { 172 return NewAppError("Team.IsValid", "model.team.is_valid.invite_id.app_error", nil, "id="+o.Id, http.StatusBadRequest) 173 } 174 175 if IsReservedTeamName(o.Name) { 176 return NewAppError("Team.IsValid", "model.team.is_valid.reserved.app_error", nil, "id="+o.Id, http.StatusBadRequest) 177 } 178 179 if !IsValidTeamName(o.Name) { 180 return NewAppError("Team.IsValid", "model.team.is_valid.characters.app_error", nil, "id="+o.Id, http.StatusBadRequest) 181 } 182 183 if !(o.Type == TEAM_OPEN || o.Type == TEAM_INVITE) { 184 return NewAppError("Team.IsValid", "model.team.is_valid.type.app_error", nil, "id="+o.Id, http.StatusBadRequest) 185 } 186 187 if len(o.CompanyName) > TEAM_COMPANY_NAME_MAX_LENGTH { 188 return NewAppError("Team.IsValid", "model.team.is_valid.company.app_error", nil, "id="+o.Id, http.StatusBadRequest) 189 } 190 191 if len(o.AllowedDomains) > TEAM_ALLOWED_DOMAINS_MAX_LENGTH { 192 return NewAppError("Team.IsValid", "model.team.is_valid.domains.app_error", nil, "id="+o.Id, http.StatusBadRequest) 193 } 194 195 return nil 196 } 197 198 func (o *Team) PreSave() { 199 if o.Id == "" { 200 o.Id = NewId() 201 } 202 203 o.CreateAt = GetMillis() 204 o.UpdateAt = o.CreateAt 205 206 o.Name = SanitizeUnicode(o.Name) 207 o.DisplayName = SanitizeUnicode(o.DisplayName) 208 o.Description = SanitizeUnicode(o.Description) 209 o.CompanyName = SanitizeUnicode(o.CompanyName) 210 211 if len(o.InviteId) == 0 { 212 o.InviteId = NewId() 213 } 214 } 215 216 func (o *Team) PreUpdate() { 217 o.UpdateAt = GetMillis() 218 o.Name = SanitizeUnicode(o.Name) 219 o.DisplayName = SanitizeUnicode(o.DisplayName) 220 o.Description = SanitizeUnicode(o.Description) 221 o.CompanyName = SanitizeUnicode(o.CompanyName) 222 } 223 224 func IsReservedTeamName(s string) bool { 225 s = strings.ToLower(s) 226 227 for _, value := range reservedName { 228 if strings.Index(s, value) == 0 { 229 return true 230 } 231 } 232 233 return false 234 } 235 236 func IsValidTeamName(s string) bool { 237 if !IsValidAlphaNum(s) { 238 return false 239 } 240 241 if len(s) < TEAM_NAME_MIN_LENGTH { 242 return false 243 } 244 245 return true 246 } 247 248 var validTeamNameCharacter = regexp.MustCompile(`^[a-z0-9-]$`) 249 250 func CleanTeamName(s string) string { 251 s = strings.ToLower(strings.Replace(s, " ", "-", -1)) 252 253 for _, value := range reservedName { 254 if strings.Index(s, value) == 0 { 255 s = strings.Replace(s, value, "", -1) 256 } 257 } 258 259 s = strings.TrimSpace(s) 260 261 for _, c := range s { 262 char := fmt.Sprintf("%c", c) 263 if !validTeamNameCharacter.MatchString(char) { 264 s = strings.Replace(s, char, "", -1) 265 } 266 } 267 268 s = strings.Trim(s, "-") 269 270 if !IsValidTeamName(s) { 271 s = NewId() 272 } 273 274 return s 275 } 276 277 func (o *Team) Sanitize() { 278 o.Email = "" 279 o.InviteId = "" 280 } 281 282 func (o *Team) Patch(patch *TeamPatch) { 283 if patch.DisplayName != nil { 284 o.DisplayName = *patch.DisplayName 285 } 286 287 if patch.Description != nil { 288 o.Description = *patch.Description 289 } 290 291 if patch.CompanyName != nil { 292 o.CompanyName = *patch.CompanyName 293 } 294 295 if patch.AllowedDomains != nil { 296 o.AllowedDomains = *patch.AllowedDomains 297 } 298 299 if patch.AllowOpenInvite != nil { 300 o.AllowOpenInvite = *patch.AllowOpenInvite 301 } 302 303 if patch.GroupConstrained != nil { 304 o.GroupConstrained = patch.GroupConstrained 305 } 306 } 307 308 func (o *Team) IsGroupConstrained() bool { 309 return o.GroupConstrained != nil && *o.GroupConstrained 310 } 311 312 func (t *TeamPatch) ToJson() string { 313 b, err := json.Marshal(t) 314 if err != nil { 315 return "" 316 } 317 318 return string(b) 319 } 320 321 func TeamPatchFromJson(data io.Reader) *TeamPatch { 322 decoder := json.NewDecoder(data) 323 var team TeamPatch 324 err := decoder.Decode(&team) 325 if err != nil { 326 return nil 327 } 328 329 return &team 330 }