Update dependencies for 5.6 (#24)

This commit is contained in:
Hanzei 2018-12-17 08:28:01 +01:00 committed by GitHub
parent 76ba0b57a7
commit 415e8b5f72
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
41 changed files with 3499 additions and 1746 deletions

View file

@ -1,6 +1,14 @@
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. # This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
[[projects]]
digest = "1:705c40022f5c03bf96ffeb6477858d88565064485a513abcd0f11a0911546cb6"
name = "github.com/blang/semver"
packages = ["."]
pruneopts = "UT"
revision = "2ee87856327ba09384cabd113bc6b5d174e9ec0f"
version = "v3.5.1"
[[projects]] [[projects]]
branch = "master" branch = "master"
digest = "1:bc36a17a513f15717b5fa3dcfd666f5ddb6fd3db06f5f2834ac2f5979d4f5070" digest = "1:bc36a17a513f15717b5fa3dcfd666f5ddb6fd3db06f5f2834ac2f5979d4f5070"
@ -10,7 +18,7 @@
revision = "5ed622c449da6d44c3c8329331ff47a9e5844f71" revision = "5ed622c449da6d44c3c8329331ff47a9e5844f71"
[[projects]] [[projects]]
digest = "1:771649e04a49766e04f498731699e62874ffa2439a071294fde36d61b2db0685" digest = "1:1cebd7208d10c6f20d5fd71c9c7062fea74524842db93fec2993fb5ea4975c73"
name = "github.com/mattermost/mattermost-server" name = "github.com/mattermost/mattermost-server"
packages = [ packages = [
"mlog", "mlog",
@ -19,8 +27,8 @@
"utils/markdown", "utils/markdown",
] ]
pruneopts = "UT" pruneopts = "UT"
revision = "d5b613cb1bbdaa856fa126e7102d94783b9e80b6" revision = "0c1207215852a8726c3f09dea157d597fec368df"
version = "v5.4.0" version = "v5.6.0"
[[projects]] [[projects]]
digest = "1:07140002dbf37da92090f731b46fa47be4820b82fe5c14a035203b0e813d0ec2" digest = "1:07140002dbf37da92090f731b46fa47be4820b82fe5c14a035203b0e813d0ec2"

View file

@ -4,7 +4,7 @@
[[constraint]] [[constraint]]
name = "github.com/mattermost/mattermost-server" name = "github.com/mattermost/mattermost-server"
version = "~5.4.0" version = "~5.6.0"
[[constraint]] [[constraint]]
name = "github.com/pkg/errors" name = "github.com/pkg/errors"

View file

@ -0,0 +1,21 @@
language: go
matrix:
include:
- go: 1.4.3
- go: 1.5.4
- go: 1.6.3
- go: 1.7
- go: tip
allow_failures:
- go: tip
install:
- go get golang.org/x/tools/cmd/cover
- go get github.com/mattn/goveralls
script:
- echo "Test and track coverage" ; $HOME/gopath/bin/goveralls -package "." -service=travis-ci
-repotoken $COVERALLS_TOKEN
- echo "Build examples" ; cd examples && go build
- echo "Check if gofmt'd" ; diff -u <(echo -n) <(gofmt -d -s .)
env:
global:
secure: HroGEAUQpVq9zX1b1VIkraLiywhGbzvNnTZq2TMxgK7JHP8xqNplAeF1izrR2i4QLL9nsY+9WtYss4QuPvEtZcVHUobw6XnL6radF7jS1LgfYZ9Y7oF+zogZ2I5QUMRLGA7rcxQ05s7mKq3XZQfeqaNts4bms/eZRefWuaFZbkw=

22
build/manifest/vendor/github.com/blang/semver/LICENSE generated vendored Normal file
View file

@ -0,0 +1,22 @@
The MIT License
Copyright (c) 2014 Benedikt Lang <github at benediktlang.de>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

194
build/manifest/vendor/github.com/blang/semver/README.md generated vendored Normal file
View file

@ -0,0 +1,194 @@
semver for golang [![Build Status](https://travis-ci.org/blang/semver.svg?branch=master)](https://travis-ci.org/blang/semver) [![GoDoc](https://godoc.org/github.com/blang/semver?status.png)](https://godoc.org/github.com/blang/semver) [![Coverage Status](https://img.shields.io/coveralls/blang/semver.svg)](https://coveralls.io/r/blang/semver?branch=master)
======
semver is a [Semantic Versioning](http://semver.org/) library written in golang. It fully covers spec version `2.0.0`.
Usage
-----
```bash
$ go get github.com/blang/semver
```
Note: Always vendor your dependencies or fix on a specific version tag.
```go
import github.com/blang/semver
v1, err := semver.Make("1.0.0-beta")
v2, err := semver.Make("2.0.0-beta")
v1.Compare(v2)
```
Also check the [GoDocs](http://godoc.org/github.com/blang/semver).
Why should I use this lib?
-----
- Fully spec compatible
- No reflection
- No regex
- Fully tested (Coverage >99%)
- Readable parsing/validation errors
- Fast (See [Benchmarks](#benchmarks))
- Only Stdlib
- Uses values instead of pointers
- Many features, see below
Features
-----
- Parsing and validation at all levels
- Comparator-like comparisons
- Compare Helper Methods
- InPlace manipulation
- Ranges `>=1.0.0 <2.0.0 || >=3.0.0 !3.0.1-beta.1`
- Wildcards `>=1.x`, `<=2.5.x`
- Sortable (implements sort.Interface)
- database/sql compatible (sql.Scanner/Valuer)
- encoding/json compatible (json.Marshaler/Unmarshaler)
Ranges
------
A `Range` is a set of conditions which specify which versions satisfy the range.
A condition is composed of an operator and a version. The supported operators are:
- `<1.0.0` Less than `1.0.0`
- `<=1.0.0` Less than or equal to `1.0.0`
- `>1.0.0` Greater than `1.0.0`
- `>=1.0.0` Greater than or equal to `1.0.0`
- `1.0.0`, `=1.0.0`, `==1.0.0` Equal to `1.0.0`
- `!1.0.0`, `!=1.0.0` Not equal to `1.0.0`. Excludes version `1.0.0`.
Note that spaces between the operator and the version will be gracefully tolerated.
A `Range` can link multiple `Ranges` separated by space:
Ranges can be linked by logical AND:
- `>1.0.0 <2.0.0` would match between both ranges, so `1.1.1` and `1.8.7` but not `1.0.0` or `2.0.0`
- `>1.0.0 <3.0.0 !2.0.3-beta.2` would match every version between `1.0.0` and `3.0.0` except `2.0.3-beta.2`
Ranges can also be linked by logical OR:
- `<2.0.0 || >=3.0.0` would match `1.x.x` and `3.x.x` but not `2.x.x`
AND has a higher precedence than OR. It's not possible to use brackets.
Ranges can be combined by both AND and OR
- `>1.0.0 <2.0.0 || >3.0.0 !4.2.1` would match `1.2.3`, `1.9.9`, `3.1.1`, but not `4.2.1`, `2.1.1`
Range usage:
```
v, err := semver.Parse("1.2.3")
range, err := semver.ParseRange(">1.0.0 <2.0.0 || >=3.0.0")
if range(v) {
//valid
}
```
Example
-----
Have a look at full examples in [examples/main.go](examples/main.go)
```go
import github.com/blang/semver
v, err := semver.Make("0.0.1-alpha.preview+123.github")
fmt.Printf("Major: %d\n", v.Major)
fmt.Printf("Minor: %d\n", v.Minor)
fmt.Printf("Patch: %d\n", v.Patch)
fmt.Printf("Pre: %s\n", v.Pre)
fmt.Printf("Build: %s\n", v.Build)
// Prerelease versions array
if len(v.Pre) > 0 {
fmt.Println("Prerelease versions:")
for i, pre := range v.Pre {
fmt.Printf("%d: %q\n", i, pre)
}
}
// Build meta data array
if len(v.Build) > 0 {
fmt.Println("Build meta data:")
for i, build := range v.Build {
fmt.Printf("%d: %q\n", i, build)
}
}
v001, err := semver.Make("0.0.1")
// Compare using helpers: v.GT(v2), v.LT, v.GTE, v.LTE
v001.GT(v) == true
v.LT(v001) == true
v.GTE(v) == true
v.LTE(v) == true
// Or use v.Compare(v2) for comparisons (-1, 0, 1):
v001.Compare(v) == 1
v.Compare(v001) == -1
v.Compare(v) == 0
// Manipulate Version in place:
v.Pre[0], err = semver.NewPRVersion("beta")
if err != nil {
fmt.Printf("Error parsing pre release version: %q", err)
}
fmt.Println("\nValidate versions:")
v.Build[0] = "?"
err = v.Validate()
if err != nil {
fmt.Printf("Validation failed: %s\n", err)
}
```
Benchmarks
-----
BenchmarkParseSimple-4 5000000 390 ns/op 48 B/op 1 allocs/op
BenchmarkParseComplex-4 1000000 1813 ns/op 256 B/op 7 allocs/op
BenchmarkParseAverage-4 1000000 1171 ns/op 163 B/op 4 allocs/op
BenchmarkStringSimple-4 20000000 119 ns/op 16 B/op 1 allocs/op
BenchmarkStringLarger-4 10000000 206 ns/op 32 B/op 2 allocs/op
BenchmarkStringComplex-4 5000000 324 ns/op 80 B/op 3 allocs/op
BenchmarkStringAverage-4 5000000 273 ns/op 53 B/op 2 allocs/op
BenchmarkValidateSimple-4 200000000 9.33 ns/op 0 B/op 0 allocs/op
BenchmarkValidateComplex-4 3000000 469 ns/op 0 B/op 0 allocs/op
BenchmarkValidateAverage-4 5000000 256 ns/op 0 B/op 0 allocs/op
BenchmarkCompareSimple-4 100000000 11.8 ns/op 0 B/op 0 allocs/op
BenchmarkCompareComplex-4 50000000 30.8 ns/op 0 B/op 0 allocs/op
BenchmarkCompareAverage-4 30000000 41.5 ns/op 0 B/op 0 allocs/op
BenchmarkSort-4 3000000 419 ns/op 256 B/op 2 allocs/op
BenchmarkRangeParseSimple-4 2000000 850 ns/op 192 B/op 5 allocs/op
BenchmarkRangeParseAverage-4 1000000 1677 ns/op 400 B/op 10 allocs/op
BenchmarkRangeParseComplex-4 300000 5214 ns/op 1440 B/op 30 allocs/op
BenchmarkRangeMatchSimple-4 50000000 25.6 ns/op 0 B/op 0 allocs/op
BenchmarkRangeMatchAverage-4 30000000 56.4 ns/op 0 B/op 0 allocs/op
BenchmarkRangeMatchComplex-4 10000000 153 ns/op 0 B/op 0 allocs/op
See benchmark cases at [semver_test.go](semver_test.go)
Motivation
-----
I simply couldn't find any lib supporting the full spec. Others were just wrong or used reflection and regex which i don't like.
Contribution
-----
Feel free to make a pull request. For bigger changes create a issue first to discuss about it.
License
-----
See [LICENSE](LICENSE) file.

23
build/manifest/vendor/github.com/blang/semver/json.go generated vendored Normal file
View file

@ -0,0 +1,23 @@
package semver
import (
"encoding/json"
)
// MarshalJSON implements the encoding/json.Marshaler interface.
func (v Version) MarshalJSON() ([]byte, error) {
return json.Marshal(v.String())
}
// UnmarshalJSON implements the encoding/json.Unmarshaler interface.
func (v *Version) UnmarshalJSON(data []byte) (err error) {
var versionString string
if err = json.Unmarshal(data, &versionString); err != nil {
return
}
*v, err = Parse(versionString)
return
}

View file

@ -0,0 +1,17 @@
{
"author": "blang",
"bugs": {
"URL": "https://github.com/blang/semver/issues",
"url": "https://github.com/blang/semver/issues"
},
"gx": {
"dvcsimport": "github.com/blang/semver"
},
"gxVersion": "0.10.0",
"language": "go",
"license": "MIT",
"name": "semver",
"releaseCmd": "git commit -a -m \"gx publish $VERSION\"",
"version": "3.5.1"
}

416
build/manifest/vendor/github.com/blang/semver/range.go generated vendored Normal file
View file

@ -0,0 +1,416 @@
package semver
import (
"fmt"
"strconv"
"strings"
"unicode"
)
type wildcardType int
const (
noneWildcard wildcardType = iota
majorWildcard wildcardType = 1
minorWildcard wildcardType = 2
patchWildcard wildcardType = 3
)
func wildcardTypefromInt(i int) wildcardType {
switch i {
case 1:
return majorWildcard
case 2:
return minorWildcard
case 3:
return patchWildcard
default:
return noneWildcard
}
}
type comparator func(Version, Version) bool
var (
compEQ comparator = func(v1 Version, v2 Version) bool {
return v1.Compare(v2) == 0
}
compNE = func(v1 Version, v2 Version) bool {
return v1.Compare(v2) != 0
}
compGT = func(v1 Version, v2 Version) bool {
return v1.Compare(v2) == 1
}
compGE = func(v1 Version, v2 Version) bool {
return v1.Compare(v2) >= 0
}
compLT = func(v1 Version, v2 Version) bool {
return v1.Compare(v2) == -1
}
compLE = func(v1 Version, v2 Version) bool {
return v1.Compare(v2) <= 0
}
)
type versionRange struct {
v Version
c comparator
}
// rangeFunc creates a Range from the given versionRange.
func (vr *versionRange) rangeFunc() Range {
return Range(func(v Version) bool {
return vr.c(v, vr.v)
})
}
// Range represents a range of versions.
// A Range can be used to check if a Version satisfies it:
//
// range, err := semver.ParseRange(">1.0.0 <2.0.0")
// range(semver.MustParse("1.1.1") // returns true
type Range func(Version) bool
// OR combines the existing Range with another Range using logical OR.
func (rf Range) OR(f Range) Range {
return Range(func(v Version) bool {
return rf(v) || f(v)
})
}
// AND combines the existing Range with another Range using logical AND.
func (rf Range) AND(f Range) Range {
return Range(func(v Version) bool {
return rf(v) && f(v)
})
}
// ParseRange parses a range and returns a Range.
// If the range could not be parsed an error is returned.
//
// Valid ranges are:
// - "<1.0.0"
// - "<=1.0.0"
// - ">1.0.0"
// - ">=1.0.0"
// - "1.0.0", "=1.0.0", "==1.0.0"
// - "!1.0.0", "!=1.0.0"
//
// A Range can consist of multiple ranges separated by space:
// Ranges can be linked by logical AND:
// - ">1.0.0 <2.0.0" would match between both ranges, so "1.1.1" and "1.8.7" but not "1.0.0" or "2.0.0"
// - ">1.0.0 <3.0.0 !2.0.3-beta.2" would match every version between 1.0.0 and 3.0.0 except 2.0.3-beta.2
//
// Ranges can also be linked by logical OR:
// - "<2.0.0 || >=3.0.0" would match "1.x.x" and "3.x.x" but not "2.x.x"
//
// AND has a higher precedence than OR. It's not possible to use brackets.
//
// Ranges can be combined by both AND and OR
//
// - `>1.0.0 <2.0.0 || >3.0.0 !4.2.1` would match `1.2.3`, `1.9.9`, `3.1.1`, but not `4.2.1`, `2.1.1`
func ParseRange(s string) (Range, error) {
parts := splitAndTrim(s)
orParts, err := splitORParts(parts)
if err != nil {
return nil, err
}
expandedParts, err := expandWildcardVersion(orParts)
if err != nil {
return nil, err
}
var orFn Range
for _, p := range expandedParts {
var andFn Range
for _, ap := range p {
opStr, vStr, err := splitComparatorVersion(ap)
if err != nil {
return nil, err
}
vr, err := buildVersionRange(opStr, vStr)
if err != nil {
return nil, fmt.Errorf("Could not parse Range %q: %s", ap, err)
}
rf := vr.rangeFunc()
// Set function
if andFn == nil {
andFn = rf
} else { // Combine with existing function
andFn = andFn.AND(rf)
}
}
if orFn == nil {
orFn = andFn
} else {
orFn = orFn.OR(andFn)
}
}
return orFn, nil
}
// splitORParts splits the already cleaned parts by '||'.
// Checks for invalid positions of the operator and returns an
// error if found.
func splitORParts(parts []string) ([][]string, error) {
var ORparts [][]string
last := 0
for i, p := range parts {
if p == "||" {
if i == 0 {
return nil, fmt.Errorf("First element in range is '||'")
}
ORparts = append(ORparts, parts[last:i])
last = i + 1
}
}
if last == len(parts) {
return nil, fmt.Errorf("Last element in range is '||'")
}
ORparts = append(ORparts, parts[last:])
return ORparts, nil
}
// buildVersionRange takes a slice of 2: operator and version
// and builds a versionRange, otherwise an error.
func buildVersionRange(opStr, vStr string) (*versionRange, error) {
c := parseComparator(opStr)
if c == nil {
return nil, fmt.Errorf("Could not parse comparator %q in %q", opStr, strings.Join([]string{opStr, vStr}, ""))
}
v, err := Parse(vStr)
if err != nil {
return nil, fmt.Errorf("Could not parse version %q in %q: %s", vStr, strings.Join([]string{opStr, vStr}, ""), err)
}
return &versionRange{
v: v,
c: c,
}, nil
}
// inArray checks if a byte is contained in an array of bytes
func inArray(s byte, list []byte) bool {
for _, el := range list {
if el == s {
return true
}
}
return false
}
// splitAndTrim splits a range string by spaces and cleans whitespaces
func splitAndTrim(s string) (result []string) {
last := 0
var lastChar byte
excludeFromSplit := []byte{'>', '<', '='}
for i := 0; i < len(s); i++ {
if s[i] == ' ' && !inArray(lastChar, excludeFromSplit) {
if last < i-1 {
result = append(result, s[last:i])
}
last = i + 1
} else if s[i] != ' ' {
lastChar = s[i]
}
}
if last < len(s)-1 {
result = append(result, s[last:])
}
for i, v := range result {
result[i] = strings.Replace(v, " ", "", -1)
}
// parts := strings.Split(s, " ")
// for _, x := range parts {
// if s := strings.TrimSpace(x); len(s) != 0 {
// result = append(result, s)
// }
// }
return
}
// splitComparatorVersion splits the comparator from the version.
// Input must be free of leading or trailing spaces.
func splitComparatorVersion(s string) (string, string, error) {
i := strings.IndexFunc(s, unicode.IsDigit)
if i == -1 {
return "", "", fmt.Errorf("Could not get version from string: %q", s)
}
return strings.TrimSpace(s[0:i]), s[i:], nil
}
// getWildcardType will return the type of wildcard that the
// passed version contains
func getWildcardType(vStr string) wildcardType {
parts := strings.Split(vStr, ".")
nparts := len(parts)
wildcard := parts[nparts-1]
possibleWildcardType := wildcardTypefromInt(nparts)
if wildcard == "x" {
return possibleWildcardType
}
return noneWildcard
}
// createVersionFromWildcard will convert a wildcard version
// into a regular version, replacing 'x's with '0's, handling
// special cases like '1.x.x' and '1.x'
func createVersionFromWildcard(vStr string) string {
// handle 1.x.x
vStr2 := strings.Replace(vStr, ".x.x", ".x", 1)
vStr2 = strings.Replace(vStr2, ".x", ".0", 1)
parts := strings.Split(vStr2, ".")
// handle 1.x
if len(parts) == 2 {
return vStr2 + ".0"
}
return vStr2
}
// incrementMajorVersion will increment the major version
// of the passed version
func incrementMajorVersion(vStr string) (string, error) {
parts := strings.Split(vStr, ".")
i, err := strconv.Atoi(parts[0])
if err != nil {
return "", err
}
parts[0] = strconv.Itoa(i + 1)
return strings.Join(parts, "."), nil
}
// incrementMajorVersion will increment the minor version
// of the passed version
func incrementMinorVersion(vStr string) (string, error) {
parts := strings.Split(vStr, ".")
i, err := strconv.Atoi(parts[1])
if err != nil {
return "", err
}
parts[1] = strconv.Itoa(i + 1)
return strings.Join(parts, "."), nil
}
// expandWildcardVersion will expand wildcards inside versions
// following these rules:
//
// * when dealing with patch wildcards:
// >= 1.2.x will become >= 1.2.0
// <= 1.2.x will become < 1.3.0
// > 1.2.x will become >= 1.3.0
// < 1.2.x will become < 1.2.0
// != 1.2.x will become < 1.2.0 >= 1.3.0
//
// * when dealing with minor wildcards:
// >= 1.x will become >= 1.0.0
// <= 1.x will become < 2.0.0
// > 1.x will become >= 2.0.0
// < 1.0 will become < 1.0.0
// != 1.x will become < 1.0.0 >= 2.0.0
//
// * when dealing with wildcards without
// version operator:
// 1.2.x will become >= 1.2.0 < 1.3.0
// 1.x will become >= 1.0.0 < 2.0.0
func expandWildcardVersion(parts [][]string) ([][]string, error) {
var expandedParts [][]string
for _, p := range parts {
var newParts []string
for _, ap := range p {
if strings.Index(ap, "x") != -1 {
opStr, vStr, err := splitComparatorVersion(ap)
if err != nil {
return nil, err
}
versionWildcardType := getWildcardType(vStr)
flatVersion := createVersionFromWildcard(vStr)
var resultOperator string
var shouldIncrementVersion bool
switch opStr {
case ">":
resultOperator = ">="
shouldIncrementVersion = true
case ">=":
resultOperator = ">="
case "<":
resultOperator = "<"
case "<=":
resultOperator = "<"
shouldIncrementVersion = true
case "", "=", "==":
newParts = append(newParts, ">="+flatVersion)
resultOperator = "<"
shouldIncrementVersion = true
case "!=", "!":
newParts = append(newParts, "<"+flatVersion)
resultOperator = ">="
shouldIncrementVersion = true
}
var resultVersion string
if shouldIncrementVersion {
switch versionWildcardType {
case patchWildcard:
resultVersion, _ = incrementMinorVersion(flatVersion)
case minorWildcard:
resultVersion, _ = incrementMajorVersion(flatVersion)
}
} else {
resultVersion = flatVersion
}
ap = resultOperator + resultVersion
}
newParts = append(newParts, ap)
}
expandedParts = append(expandedParts, newParts)
}
return expandedParts, nil
}
func parseComparator(s string) comparator {
switch s {
case "==":
fallthrough
case "":
fallthrough
case "=":
return compEQ
case ">":
return compGT
case ">=":
return compGE
case "<":
return compLT
case "<=":
return compLE
case "!":
fallthrough
case "!=":
return compNE
}
return nil
}
// MustParseRange is like ParseRange but panics if the range cannot be parsed.
func MustParseRange(s string) Range {
r, err := ParseRange(s)
if err != nil {
panic(`semver: ParseRange(` + s + `): ` + err.Error())
}
return r
}

418
build/manifest/vendor/github.com/blang/semver/semver.go generated vendored Normal file
View file

@ -0,0 +1,418 @@
package semver
import (
"errors"
"fmt"
"strconv"
"strings"
)
const (
numbers string = "0123456789"
alphas = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-"
alphanum = alphas + numbers
)
// SpecVersion is the latest fully supported spec version of semver
var SpecVersion = Version{
Major: 2,
Minor: 0,
Patch: 0,
}
// Version represents a semver compatible version
type Version struct {
Major uint64
Minor uint64
Patch uint64
Pre []PRVersion
Build []string //No Precendence
}
// Version to string
func (v Version) String() string {
b := make([]byte, 0, 5)
b = strconv.AppendUint(b, v.Major, 10)
b = append(b, '.')
b = strconv.AppendUint(b, v.Minor, 10)
b = append(b, '.')
b = strconv.AppendUint(b, v.Patch, 10)
if len(v.Pre) > 0 {
b = append(b, '-')
b = append(b, v.Pre[0].String()...)
for _, pre := range v.Pre[1:] {
b = append(b, '.')
b = append(b, pre.String()...)
}
}
if len(v.Build) > 0 {
b = append(b, '+')
b = append(b, v.Build[0]...)
for _, build := range v.Build[1:] {
b = append(b, '.')
b = append(b, build...)
}
}
return string(b)
}
// Equals checks if v is equal to o.
func (v Version) Equals(o Version) bool {
return (v.Compare(o) == 0)
}
// EQ checks if v is equal to o.
func (v Version) EQ(o Version) bool {
return (v.Compare(o) == 0)
}
// NE checks if v is not equal to o.
func (v Version) NE(o Version) bool {
return (v.Compare(o) != 0)
}
// GT checks if v is greater than o.
func (v Version) GT(o Version) bool {
return (v.Compare(o) == 1)
}
// GTE checks if v is greater than or equal to o.
func (v Version) GTE(o Version) bool {
return (v.Compare(o) >= 0)
}
// GE checks if v is greater than or equal to o.
func (v Version) GE(o Version) bool {
return (v.Compare(o) >= 0)
}
// LT checks if v is less than o.
func (v Version) LT(o Version) bool {
return (v.Compare(o) == -1)
}
// LTE checks if v is less than or equal to o.
func (v Version) LTE(o Version) bool {
return (v.Compare(o) <= 0)
}
// LE checks if v is less than or equal to o.
func (v Version) LE(o Version) bool {
return (v.Compare(o) <= 0)
}
// Compare compares Versions v to o:
// -1 == v is less than o
// 0 == v is equal to o
// 1 == v is greater than o
func (v Version) Compare(o Version) int {
if v.Major != o.Major {
if v.Major > o.Major {
return 1
}
return -1
}
if v.Minor != o.Minor {
if v.Minor > o.Minor {
return 1
}
return -1
}
if v.Patch != o.Patch {
if v.Patch > o.Patch {
return 1
}
return -1
}
// Quick comparison if a version has no prerelease versions
if len(v.Pre) == 0 && len(o.Pre) == 0 {
return 0
} else if len(v.Pre) == 0 && len(o.Pre) > 0 {
return 1
} else if len(v.Pre) > 0 && len(o.Pre) == 0 {
return -1
}
i := 0
for ; i < len(v.Pre) && i < len(o.Pre); i++ {
if comp := v.Pre[i].Compare(o.Pre[i]); comp == 0 {
continue
} else if comp == 1 {
return 1
} else {
return -1
}
}
// If all pr versions are the equal but one has further prversion, this one greater
if i == len(v.Pre) && i == len(o.Pre) {
return 0
} else if i == len(v.Pre) && i < len(o.Pre) {
return -1
} else {
return 1
}
}
// Validate validates v and returns error in case
func (v Version) Validate() error {
// Major, Minor, Patch already validated using uint64
for _, pre := range v.Pre {
if !pre.IsNum { //Numeric prerelease versions already uint64
if len(pre.VersionStr) == 0 {
return fmt.Errorf("Prerelease can not be empty %q", pre.VersionStr)
}
if !containsOnly(pre.VersionStr, alphanum) {
return fmt.Errorf("Invalid character(s) found in prerelease %q", pre.VersionStr)
}
}
}
for _, build := range v.Build {
if len(build) == 0 {
return fmt.Errorf("Build meta data can not be empty %q", build)
}
if !containsOnly(build, alphanum) {
return fmt.Errorf("Invalid character(s) found in build meta data %q", build)
}
}
return nil
}
// New is an alias for Parse and returns a pointer, parses version string and returns a validated Version or error
func New(s string) (vp *Version, err error) {
v, err := Parse(s)
vp = &v
return
}
// Make is an alias for Parse, parses version string and returns a validated Version or error
func Make(s string) (Version, error) {
return Parse(s)
}
// ParseTolerant allows for certain version specifications that do not strictly adhere to semver
// specs to be parsed by this library. It does so by normalizing versions before passing them to
// Parse(). It currently trims spaces, removes a "v" prefix, and adds a 0 patch number to versions
// with only major and minor components specified
func ParseTolerant(s string) (Version, error) {
s = strings.TrimSpace(s)
s = strings.TrimPrefix(s, "v")
// Split into major.minor.(patch+pr+meta)
parts := strings.SplitN(s, ".", 3)
if len(parts) < 3 {
if strings.ContainsAny(parts[len(parts)-1], "+-") {
return Version{}, errors.New("Short version cannot contain PreRelease/Build meta data")
}
for len(parts) < 3 {
parts = append(parts, "0")
}
s = strings.Join(parts, ".")
}
return Parse(s)
}
// Parse parses version string and returns a validated Version or error
func Parse(s string) (Version, error) {
if len(s) == 0 {
return Version{}, errors.New("Version string empty")
}
// Split into major.minor.(patch+pr+meta)
parts := strings.SplitN(s, ".", 3)
if len(parts) != 3 {
return Version{}, errors.New("No Major.Minor.Patch elements found")
}
// Major
if !containsOnly(parts[0], numbers) {
return Version{}, fmt.Errorf("Invalid character(s) found in major number %q", parts[0])
}
if hasLeadingZeroes(parts[0]) {
return Version{}, fmt.Errorf("Major number must not contain leading zeroes %q", parts[0])
}
major, err := strconv.ParseUint(parts[0], 10, 64)
if err != nil {
return Version{}, err
}
// Minor
if !containsOnly(parts[1], numbers) {
return Version{}, fmt.Errorf("Invalid character(s) found in minor number %q", parts[1])
}
if hasLeadingZeroes(parts[1]) {
return Version{}, fmt.Errorf("Minor number must not contain leading zeroes %q", parts[1])
}
minor, err := strconv.ParseUint(parts[1], 10, 64)
if err != nil {
return Version{}, err
}
v := Version{}
v.Major = major
v.Minor = minor
var build, prerelease []string
patchStr := parts[2]
if buildIndex := strings.IndexRune(patchStr, '+'); buildIndex != -1 {
build = strings.Split(patchStr[buildIndex+1:], ".")
patchStr = patchStr[:buildIndex]
}
if preIndex := strings.IndexRune(patchStr, '-'); preIndex != -1 {
prerelease = strings.Split(patchStr[preIndex+1:], ".")
patchStr = patchStr[:preIndex]
}
if !containsOnly(patchStr, numbers) {
return Version{}, fmt.Errorf("Invalid character(s) found in patch number %q", patchStr)
}
if hasLeadingZeroes(patchStr) {
return Version{}, fmt.Errorf("Patch number must not contain leading zeroes %q", patchStr)
}
patch, err := strconv.ParseUint(patchStr, 10, 64)
if err != nil {
return Version{}, err
}
v.Patch = patch
// Prerelease
for _, prstr := range prerelease {
parsedPR, err := NewPRVersion(prstr)
if err != nil {
return Version{}, err
}
v.Pre = append(v.Pre, parsedPR)
}
// Build meta data
for _, str := range build {
if len(str) == 0 {
return Version{}, errors.New("Build meta data is empty")
}
if !containsOnly(str, alphanum) {
return Version{}, fmt.Errorf("Invalid character(s) found in build meta data %q", str)
}
v.Build = append(v.Build, str)
}
return v, nil
}
// MustParse is like Parse but panics if the version cannot be parsed.
func MustParse(s string) Version {
v, err := Parse(s)
if err != nil {
panic(`semver: Parse(` + s + `): ` + err.Error())
}
return v
}
// PRVersion represents a PreRelease Version
type PRVersion struct {
VersionStr string
VersionNum uint64
IsNum bool
}
// NewPRVersion creates a new valid prerelease version
func NewPRVersion(s string) (PRVersion, error) {
if len(s) == 0 {
return PRVersion{}, errors.New("Prerelease is empty")
}
v := PRVersion{}
if containsOnly(s, numbers) {
if hasLeadingZeroes(s) {
return PRVersion{}, fmt.Errorf("Numeric PreRelease version must not contain leading zeroes %q", s)
}
num, err := strconv.ParseUint(s, 10, 64)
// Might never be hit, but just in case
if err != nil {
return PRVersion{}, err
}
v.VersionNum = num
v.IsNum = true
} else if containsOnly(s, alphanum) {
v.VersionStr = s
v.IsNum = false
} else {
return PRVersion{}, fmt.Errorf("Invalid character(s) found in prerelease %q", s)
}
return v, nil
}
// IsNumeric checks if prerelease-version is numeric
func (v PRVersion) IsNumeric() bool {
return v.IsNum
}
// Compare compares two PreRelease Versions v and o:
// -1 == v is less than o
// 0 == v is equal to o
// 1 == v is greater than o
func (v PRVersion) Compare(o PRVersion) int {
if v.IsNum && !o.IsNum {
return -1
} else if !v.IsNum && o.IsNum {
return 1
} else if v.IsNum && o.IsNum {
if v.VersionNum == o.VersionNum {
return 0
} else if v.VersionNum > o.VersionNum {
return 1
} else {
return -1
}
} else { // both are Alphas
if v.VersionStr == o.VersionStr {
return 0
} else if v.VersionStr > o.VersionStr {
return 1
} else {
return -1
}
}
}
// PreRelease version to string
func (v PRVersion) String() string {
if v.IsNum {
return strconv.FormatUint(v.VersionNum, 10)
}
return v.VersionStr
}
func containsOnly(s string, set string) bool {
return strings.IndexFunc(s, func(r rune) bool {
return !strings.ContainsRune(set, r)
}) == -1
}
func hasLeadingZeroes(s string) bool {
return len(s) > 1 && s[0] == '0'
}
// NewBuildVersion creates a new valid build version
func NewBuildVersion(s string) (string, error) {
if len(s) == 0 {
return "", errors.New("Buildversion is empty")
}
if !containsOnly(s, alphanum) {
return "", fmt.Errorf("Invalid character(s) found in build meta data %q", s)
}
return s, nil
}

28
build/manifest/vendor/github.com/blang/semver/sort.go generated vendored Normal file
View file

@ -0,0 +1,28 @@
package semver
import (
"sort"
)
// Versions represents multiple versions.
type Versions []Version
// Len returns length of version collection
func (s Versions) Len() int {
return len(s)
}
// Swap swaps two versions inside the collection by its indices
func (s Versions) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
// Less checks if version at index i is less than version at index j
func (s Versions) Less(i, j int) bool {
return s[i].LT(s[j])
}
// Sort sorts a slice of versions
func Sort(versions []Version) {
sort.Sort(Versions(versions))
}

30
build/manifest/vendor/github.com/blang/semver/sql.go generated vendored Normal file
View file

@ -0,0 +1,30 @@
package semver
import (
"database/sql/driver"
"fmt"
)
// Scan implements the database/sql.Scanner interface.
func (v *Version) Scan(src interface{}) (err error) {
var str string
switch src := src.(type) {
case string:
str = src
case []byte:
str = string(src)
default:
return fmt.Errorf("Version.Scan: cannot convert %T to string.", src)
}
if t, err := Parse(str); err == nil {
*v = t
}
return
}
// Value implements the database/sql/driver.Valuer interface.
func (v Version) Value() (driver.Value, error) {
return v.String(), nil
}

View file

@ -429,6 +429,41 @@ Go package for fast and reliable abstraction of browser user agent strings.
--- ---
## blang/semver
This product contains 'semver' by Benedikt Lang.
Semantic Versioning (semver) library written in golang
* HOMEPAGE:
* https://github.com/blang/semver
* LICENSE: MIT
The MIT License
Copyright (c) 2014 Benedikt Lang <github at benediktlang.de>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
---
## dgryski/dgoogauth ## dgryski/dgoogauth
This product contains 'dgoogauth' by Damian Gryski. This product contains 'dgoogauth' by Damian Gryski.
@ -2947,6 +2982,41 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
--- ---
## sirupsen/logrus
This product contains 'logrus' by Simon Eskildsen.
Structured, pluggable logging for Go.
* HOMEPAGE:
* https://github.com/sirupsen/logrus
* LICENSE: MIT
The MIT License (MIT)
Copyright (c) 2014 Simon Eskildsen
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
---
## spf13/cobra ## spf13/cobra
This product contains 'cobra' by Steve Francia. This product contains 'cobra' by Steve Francia.

View file

@ -29,6 +29,9 @@ const (
CHANNEL_HEADER_MAX_RUNES = 1024 CHANNEL_HEADER_MAX_RUNES = 1024
CHANNEL_PURPOSE_MAX_RUNES = 250 CHANNEL_PURPOSE_MAX_RUNES = 250
CHANNEL_CACHE_SIZE = 25000 CHANNEL_CACHE_SIZE = 25000
CHANNEL_SORT_BY_USERNAME = "username"
CHANNEL_SORT_BY_STATUS = "status"
) )
type Channel struct { type Channel struct {

View file

@ -17,6 +17,10 @@ const (
CHANNEL_NOTIFY_NONE = "none" CHANNEL_NOTIFY_NONE = "none"
CHANNEL_MARK_UNREAD_ALL = "all" CHANNEL_MARK_UNREAD_ALL = "all"
CHANNEL_MARK_UNREAD_MENTION = "mention" CHANNEL_MARK_UNREAD_MENTION = "mention"
IGNORE_CHANNEL_MENTIONS_DEFAULT = "default"
IGNORE_CHANNEL_MENTIONS_OFF = "off"
IGNORE_CHANNEL_MENTIONS_ON = "on"
IGNORE_CHANNEL_MENTIONS_NOTIFY_PROP = "ignore_channel_mentions"
) )
type ChannelUnread struct { type ChannelUnread struct {
@ -116,6 +120,12 @@ func (o *ChannelMember) IsValid() *AppError {
} }
} }
if ignoreChannelMentions, ok := o.NotifyProps[IGNORE_CHANNEL_MENTIONS_NOTIFY_PROP]; ok {
if len(ignoreChannelMentions) > 40 || !IsIgnoreChannelMentionsValid(ignoreChannelMentions) {
return NewAppError("ChannelMember.IsValid", "model.channel_member.is_valid.ignore_channel_mentions_value.app_error", nil, "ignore_channel_mentions="+ignoreChannelMentions, http.StatusBadRequest)
}
}
return nil return nil
} }
@ -146,11 +156,16 @@ func IsSendEmailValid(sendEmail string) bool {
return sendEmail == CHANNEL_NOTIFY_DEFAULT || sendEmail == "true" || sendEmail == "false" return sendEmail == CHANNEL_NOTIFY_DEFAULT || sendEmail == "true" || sendEmail == "false"
} }
func IsIgnoreChannelMentionsValid(ignoreChannelMentions string) bool {
return ignoreChannelMentions == IGNORE_CHANNEL_MENTIONS_ON || ignoreChannelMentions == IGNORE_CHANNEL_MENTIONS_OFF || ignoreChannelMentions == IGNORE_CHANNEL_MENTIONS_DEFAULT
}
func GetDefaultChannelNotifyProps() StringMap { func GetDefaultChannelNotifyProps() StringMap {
return StringMap{ return StringMap{
DESKTOP_NOTIFY_PROP: CHANNEL_NOTIFY_DEFAULT, DESKTOP_NOTIFY_PROP: CHANNEL_NOTIFY_DEFAULT,
MARK_UNREAD_NOTIFY_PROP: CHANNEL_MARK_UNREAD_ALL, MARK_UNREAD_NOTIFY_PROP: CHANNEL_MARK_UNREAD_ALL,
PUSH_NOTIFY_PROP: CHANNEL_NOTIFY_DEFAULT, PUSH_NOTIFY_PROP: CHANNEL_NOTIFY_DEFAULT,
EMAIL_NOTIFY_PROP: CHANNEL_NOTIFY_DEFAULT, EMAIL_NOTIFY_PROP: CHANNEL_NOTIFY_DEFAULT,
IGNORE_CHANNEL_MENTIONS_NOTIFY_PROP: IGNORE_CHANNEL_MENTIONS_DEFAULT,
} }
} }

File diff suppressed because it is too large Load diff

View file

@ -16,6 +16,7 @@ type CommandArgs struct {
TeamId string `json:"team_id"` TeamId string `json:"team_id"`
RootId string `json:"root_id"` RootId string `json:"root_id"`
ParentId string `json:"parent_id"` ParentId string `json:"parent_id"`
TriggerId string `json:"trigger_id,omitempty"`
Command string `json:"command"` Command string `json:"command"`
SiteURL string `json:"-"` SiteURL string `json:"-"`
T goi18n.TranslateFunc `json:"-"` T goi18n.TranslateFunc `json:"-"`

View file

@ -25,7 +25,9 @@ type CommandResponse struct {
Type string `json:"type"` Type string `json:"type"`
Props StringInterface `json:"props"` Props StringInterface `json:"props"`
GotoLocation string `json:"goto_location"` GotoLocation string `json:"goto_location"`
TriggerId string `json:"trigger_id"`
Attachments []*SlackAttachment `json:"attachments"` Attachments []*SlackAttachment `json:"attachments"`
ExtraResponses []*CommandResponse `json:"extra_responses"`
} }
func (o *CommandResponse) ToJson() string { func (o *CommandResponse) ToJson() string {
@ -63,5 +65,11 @@ func CommandResponseFromJson(data io.Reader) (*CommandResponse, error) {
o.Attachments = StringifySlackFieldValue(o.Attachments) o.Attachments = StringifySlackFieldValue(o.Attachments)
if o.ExtraResponses != nil {
for _, resp := range o.ExtraResponses {
resp.Attachments = StringifySlackFieldValue(resp.Attachments)
}
}
return &o, nil return &o, nil
} }

View file

@ -4,12 +4,14 @@
package model package model
import ( import (
"crypto/tls"
"encoding/json" "encoding/json"
"io" "io"
"math" "math"
"net" "net"
"net/http" "net/http"
"net/url" "net/url"
"os"
"regexp" "regexp"
"strconv" "strconv"
"strings" "strings"
@ -110,6 +112,7 @@ const (
SUPPORT_SETTINGS_DEFAULT_HELP_LINK = "https://about.mattermost.com/default-help/" SUPPORT_SETTINGS_DEFAULT_HELP_LINK = "https://about.mattermost.com/default-help/"
SUPPORT_SETTINGS_DEFAULT_REPORT_A_PROBLEM_LINK = "https://about.mattermost.com/default-report-a-problem/" SUPPORT_SETTINGS_DEFAULT_REPORT_A_PROBLEM_LINK = "https://about.mattermost.com/default-report-a-problem/"
SUPPORT_SETTINGS_DEFAULT_SUPPORT_EMAIL = "feedback@mattermost.com" SUPPORT_SETTINGS_DEFAULT_SUPPORT_EMAIL = "feedback@mattermost.com"
SUPPORT_SETTINGS_DEFAULT_RE_ACCEPTANCE_PERIOD = 365
LDAP_SETTINGS_DEFAULT_FIRST_NAME_ATTRIBUTE = "" LDAP_SETTINGS_DEFAULT_FIRST_NAME_ATTRIBUTE = ""
LDAP_SETTINGS_DEFAULT_LAST_NAME_ATTRIBUTE = "" LDAP_SETTINGS_DEFAULT_LAST_NAME_ATTRIBUTE = ""
@ -133,9 +136,6 @@ const (
NATIVEAPP_SETTINGS_DEFAULT_ANDROID_APP_DOWNLOAD_LINK = "https://about.mattermost.com/mattermost-android-app/" NATIVEAPP_SETTINGS_DEFAULT_ANDROID_APP_DOWNLOAD_LINK = "https://about.mattermost.com/mattermost-android-app/"
NATIVEAPP_SETTINGS_DEFAULT_IOS_APP_DOWNLOAD_LINK = "https://about.mattermost.com/mattermost-ios-app/" NATIVEAPP_SETTINGS_DEFAULT_IOS_APP_DOWNLOAD_LINK = "https://about.mattermost.com/mattermost-ios-app/"
WEBRTC_SETTINGS_DEFAULT_STUN_URI = ""
WEBRTC_SETTINGS_DEFAULT_TURN_URI = ""
ANALYTICS_SETTINGS_DEFAULT_MAX_USERS_FOR_STATISTICS = 2500 ANALYTICS_SETTINGS_DEFAULT_MAX_USERS_FOR_STATISTICS = 2500
ANNOUNCEMENT_SETTINGS_DEFAULT_BANNER_COLOR = "#f2a93b" ANNOUNCEMENT_SETTINGS_DEFAULT_BANNER_COLOR = "#f2a93b"
@ -174,6 +174,31 @@ const (
CLIENT_SIDE_CERT_CHECK_SECONDARY_AUTH = "secondary" CLIENT_SIDE_CERT_CHECK_SECONDARY_AUTH = "secondary"
) )
var ServerTLSSupportedCiphers = map[string]uint16{
"TLS_RSA_WITH_RC4_128_SHA": tls.TLS_RSA_WITH_RC4_128_SHA,
"TLS_RSA_WITH_3DES_EDE_CBC_SHA": tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA,
"TLS_RSA_WITH_AES_128_CBC_SHA": tls.TLS_RSA_WITH_AES_128_CBC_SHA,
"TLS_RSA_WITH_AES_256_CBC_SHA": tls.TLS_RSA_WITH_AES_256_CBC_SHA,
"TLS_RSA_WITH_AES_128_CBC_SHA256": tls.TLS_RSA_WITH_AES_128_CBC_SHA256,
"TLS_RSA_WITH_AES_128_GCM_SHA256": tls.TLS_RSA_WITH_AES_128_GCM_SHA256,
"TLS_RSA_WITH_AES_256_GCM_SHA384": tls.TLS_RSA_WITH_AES_256_GCM_SHA384,
"TLS_ECDHE_ECDSA_WITH_RC4_128_SHA": tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA": tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA": tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
"TLS_ECDHE_RSA_WITH_RC4_128_SHA": tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA,
"TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA": tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA": tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA": tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256": tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256": tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256": tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256": tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384": tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384": tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305": tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305": tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
}
type ServiceSettings struct { type ServiceSettings struct {
SiteURL *string SiteURL *string
WebsocketURL *string WebsocketURL *string
@ -182,6 +207,10 @@ type ServiceSettings struct {
ConnectionSecurity *string ConnectionSecurity *string
TLSCertFile *string TLSCertFile *string
TLSKeyFile *string TLSKeyFile *string
TLSMinVer *string
TLSStrictTransport *bool
TLSStrictTransportMaxAge *int64
TLSOverwriteCiphers []string
UseLetsEncrypt *bool UseLetsEncrypt *bool
LetsEncryptCertificateCacheFile *string LetsEncryptCertificateCacheFile *string
Forward80To443 *bool Forward80To443 *bool
@ -194,7 +223,7 @@ type ServiceSettings struct {
EnableIncomingWebhooks bool EnableIncomingWebhooks bool
EnableOutgoingWebhooks bool EnableOutgoingWebhooks bool
EnableCommands *bool EnableCommands *bool
EnableOnlyAdminIntegrations *bool DEPRECATED_DO_NOT_USE_EnableOnlyAdminIntegrations *bool `json:"EnableOnlyAdminIntegrations"` // This field is deprecated and must not be used.
EnablePostUsernameOverride bool EnablePostUsernameOverride bool
EnablePostIconOverride bool EnablePostIconOverride bool
EnableLinkPreviews *bool EnableLinkPreviews *bool
@ -224,9 +253,9 @@ type ServiceSettings struct {
EnableGifPicker *bool EnableGifPicker *bool
GfycatApiKey *string GfycatApiKey *string
GfycatApiSecret *string GfycatApiSecret *string
RestrictCustomEmojiCreation *string DEPRECATED_DO_NOT_USE_RestrictCustomEmojiCreation *string `json:"RestrictCustomEmojiCreation"` // This field is deprecated and must not be used.
RestrictPostDelete *string DEPRECATED_DO_NOT_USE_RestrictPostDelete *string `json:"RestrictPostDelete"` // This field is deprecated and must not be used.
AllowEditPost *string DEPRECATED_DO_NOT_USE_AllowEditPost *string `json:"AllowEditPost"` // This field is deprecated and must not be used.
PostEditTimeLimit *int PostEditTimeLimit *int
TimeBetweenUserTypingUpdatesMilliseconds *int64 TimeBetweenUserTypingUpdatesMilliseconds *int64
EnablePostSearch *bool EnablePostSearch *bool
@ -246,7 +275,6 @@ type ServiceSettings struct {
ImageProxyOptions *string ImageProxyOptions *string
EnableAPITeamDeletion *bool EnableAPITeamDeletion *bool
ExperimentalEnableHardenedMode *bool ExperimentalEnableHardenedMode *bool
ExperimentalLimitClientConfig *bool
EnableEmailInvitations *bool EnableEmailInvitations *bool
} }
@ -324,6 +352,22 @@ func (s *ServiceSettings) SetDefaults() {
s.TLSCertFile = NewString(SERVICE_SETTINGS_DEFAULT_TLS_CERT_FILE) s.TLSCertFile = NewString(SERVICE_SETTINGS_DEFAULT_TLS_CERT_FILE)
} }
if s.TLSMinVer == nil {
s.TLSMinVer = NewString("1.2")
}
if s.TLSStrictTransport == nil {
s.TLSStrictTransport = NewBool(false)
}
if s.TLSStrictTransportMaxAge == nil {
s.TLSStrictTransportMaxAge = NewInt64(63072000)
}
if s.TLSOverwriteCiphers == nil {
s.TLSOverwriteCiphers = []string{}
}
if s.UseLetsEncrypt == nil { if s.UseLetsEncrypt == nil {
s.UseLetsEncrypt = NewBool(false) s.UseLetsEncrypt = NewBool(false)
} }
@ -404,8 +448,8 @@ func (s *ServiceSettings) SetDefaults() {
s.EnableCommands = NewBool(false) s.EnableCommands = NewBool(false)
} }
if s.EnableOnlyAdminIntegrations == nil { if s.DEPRECATED_DO_NOT_USE_EnableOnlyAdminIntegrations == nil {
s.EnableOnlyAdminIntegrations = NewBool(true) s.DEPRECATED_DO_NOT_USE_EnableOnlyAdminIntegrations = NewBool(true)
} }
if s.WebsocketPort == nil { if s.WebsocketPort == nil {
@ -462,16 +506,16 @@ func (s *ServiceSettings) SetDefaults() {
s.GfycatApiSecret = NewString(SERVICE_SETTINGS_DEFAULT_GFYCAT_API_SECRET) s.GfycatApiSecret = NewString(SERVICE_SETTINGS_DEFAULT_GFYCAT_API_SECRET)
} }
if s.RestrictCustomEmojiCreation == nil { if s.DEPRECATED_DO_NOT_USE_RestrictCustomEmojiCreation == nil {
s.RestrictCustomEmojiCreation = NewString(RESTRICT_EMOJI_CREATION_ALL) s.DEPRECATED_DO_NOT_USE_RestrictCustomEmojiCreation = NewString(RESTRICT_EMOJI_CREATION_ALL)
} }
if s.RestrictPostDelete == nil { if s.DEPRECATED_DO_NOT_USE_RestrictPostDelete == nil {
s.RestrictPostDelete = NewString(PERMISSIONS_DELETE_POST_ALL) s.DEPRECATED_DO_NOT_USE_RestrictPostDelete = NewString(PERMISSIONS_DELETE_POST_ALL)
} }
if s.AllowEditPost == nil { if s.DEPRECATED_DO_NOT_USE_AllowEditPost == nil {
s.AllowEditPost = NewString(ALLOW_EDIT_POST_ALWAYS) s.DEPRECATED_DO_NOT_USE_AllowEditPost = NewString(ALLOW_EDIT_POST_ALWAYS)
} }
if s.ExperimentalEnableAuthenticationTransfer == nil { if s.ExperimentalEnableAuthenticationTransfer == nil {
@ -522,10 +566,6 @@ func (s *ServiceSettings) SetDefaults() {
if s.ExperimentalEnableHardenedMode == nil { if s.ExperimentalEnableHardenedMode == nil {
s.ExperimentalEnableHardenedMode = NewBool(false) s.ExperimentalEnableHardenedMode = NewBool(false)
} }
if s.ExperimentalLimitClientConfig == nil {
s.ExperimentalLimitClientConfig = NewBool(false)
}
} }
type ClusterSettings struct { type ClusterSettings struct {
@ -611,6 +651,7 @@ func (s *MetricsSettings) SetDefaults() {
type ExperimentalSettings struct { type ExperimentalSettings struct {
ClientSideCertEnable *bool ClientSideCertEnable *bool
ClientSideCertCheck *string ClientSideCertCheck *string
EnablePostMetadata *bool
} }
func (s *ExperimentalSettings) SetDefaults() { func (s *ExperimentalSettings) SetDefaults() {
@ -621,6 +662,10 @@ func (s *ExperimentalSettings) SetDefaults() {
if s.ClientSideCertCheck == nil { if s.ClientSideCertCheck == nil {
s.ClientSideCertCheck = NewString(CLIENT_SIDE_CERT_CHECK_SECONDARY_AUTH) s.ClientSideCertCheck = NewString(CLIENT_SIDE_CERT_CHECK_SECONDARY_AUTH)
} }
if s.EnablePostMetadata == nil {
s.EnablePostMetadata = NewBool(false)
}
} }
type AnalyticsSettings struct { type AnalyticsSettings struct {
@ -654,7 +699,6 @@ type SqlSettings struct {
Trace bool Trace bool
AtRestEncryptKey string AtRestEncryptKey string
QueryTimeout *int QueryTimeout *int
EnablePublicChannelsMaterialization *bool
} }
func (s *SqlSettings) SetDefaults() { func (s *SqlSettings) SetDefaults() {
@ -685,10 +729,6 @@ func (s *SqlSettings) SetDefaults() {
if s.QueryTimeout == nil { if s.QueryTimeout == nil {
s.QueryTimeout = NewInt(30) s.QueryTimeout = NewInt(30)
} }
if s.EnablePublicChannelsMaterialization == nil {
s.EnablePublicChannelsMaterialization = NewBool(true)
}
} }
type LogSettings struct { type LogSettings struct {
@ -1003,6 +1043,7 @@ type SupportSettings struct {
ReportAProblemLink *string ReportAProblemLink *string
SupportEmail *string SupportEmail *string
CustomTermsOfServiceEnabled *bool CustomTermsOfServiceEnabled *bool
CustomTermsOfServiceReAcceptancePeriod *int
} }
func (s *SupportSettings) SetDefaults() { func (s *SupportSettings) SetDefaults() {
@ -1053,6 +1094,10 @@ func (s *SupportSettings) SetDefaults() {
if s.CustomTermsOfServiceEnabled == nil { if s.CustomTermsOfServiceEnabled == nil {
s.CustomTermsOfServiceEnabled = NewBool(false) s.CustomTermsOfServiceEnabled = NewBool(false)
} }
if s.CustomTermsOfServiceReAcceptancePeriod == nil {
s.CustomTermsOfServiceReAcceptancePeriod = NewInt(SUPPORT_SETTINGS_DEFAULT_RE_ACCEPTANCE_PERIOD)
}
} }
type AnnouncementSettings struct { type AnnouncementSettings struct {
@ -1113,7 +1158,7 @@ func (s *ThemeSettings) SetDefaults() {
type TeamSettings struct { type TeamSettings struct {
SiteName string SiteName string
MaxUsersPerTeam *int MaxUsersPerTeam *int
EnableTeamCreation *bool DEPRECATED_DO_NOT_USE_EnableTeamCreation *bool `json:"EnableTeamCreation"` // This field is deprecated and must not be used.
EnableUserCreation *bool EnableUserCreation *bool
EnableOpenServer *bool EnableOpenServer *bool
EnableUserDeactivation *bool EnableUserDeactivation *bool
@ -1122,14 +1167,14 @@ type TeamSettings struct {
CustomBrandText *string CustomBrandText *string
CustomDescriptionText *string CustomDescriptionText *string
RestrictDirectMessage *string RestrictDirectMessage *string
RestrictTeamInvite *string DEPRECATED_DO_NOT_USE_RestrictTeamInvite *string `json:"RestrictTeamInvite"` // This field is deprecated and must not be used.
RestrictPublicChannelManagement *string DEPRECATED_DO_NOT_USE_RestrictPublicChannelManagement *string `json:"RestrictPublicChannelManagement"` // This field is deprecated and must not be used.
RestrictPrivateChannelManagement *string DEPRECATED_DO_NOT_USE_RestrictPrivateChannelManagement *string `json:"RestrictPrivateChannelManagement"` // This field is deprecated and must not be used.
RestrictPublicChannelCreation *string DEPRECATED_DO_NOT_USE_RestrictPublicChannelCreation *string `json:"RestrictPublicChannelCreation"` // This field is deprecated and must not be used.
RestrictPrivateChannelCreation *string DEPRECATED_DO_NOT_USE_RestrictPrivateChannelCreation *string `json:"RestrictPrivateChannelCreation"` // This field is deprecated and must not be used.
RestrictPublicChannelDeletion *string DEPRECATED_DO_NOT_USE_RestrictPublicChannelDeletion *string `json:"RestrictPublicChannelDeletion"` // This field is deprecated and must not be used.
RestrictPrivateChannelDeletion *string DEPRECATED_DO_NOT_USE_RestrictPrivateChannelDeletion *string `json:"RestrictPrivateChannelDeletion"` // This field is deprecated and must not be used.
RestrictPrivateChannelManageMembers *string DEPRECATED_DO_NOT_USE_RestrictPrivateChannelManageMembers *string `json:"RestrictPrivateChannelManageMembers"` // This field is deprecated and must not be used.
EnableXToLeaveChannelsFromLHS *bool EnableXToLeaveChannelsFromLHS *bool
UserStatusAwayTimeout *int64 UserStatusAwayTimeout *int64
MaxChannelsPerTeam *int64 MaxChannelsPerTeam *int64
@ -1173,49 +1218,49 @@ func (s *TeamSettings) SetDefaults() {
s.RestrictDirectMessage = NewString(DIRECT_MESSAGE_ANY) s.RestrictDirectMessage = NewString(DIRECT_MESSAGE_ANY)
} }
if s.RestrictTeamInvite == nil { if s.DEPRECATED_DO_NOT_USE_RestrictTeamInvite == nil {
s.RestrictTeamInvite = NewString(PERMISSIONS_ALL) s.DEPRECATED_DO_NOT_USE_RestrictTeamInvite = NewString(PERMISSIONS_ALL)
} }
if s.RestrictPublicChannelManagement == nil { if s.DEPRECATED_DO_NOT_USE_RestrictPublicChannelManagement == nil {
s.RestrictPublicChannelManagement = NewString(PERMISSIONS_ALL) s.DEPRECATED_DO_NOT_USE_RestrictPublicChannelManagement = NewString(PERMISSIONS_ALL)
} }
if s.RestrictPrivateChannelManagement == nil { if s.DEPRECATED_DO_NOT_USE_RestrictPrivateChannelManagement == nil {
s.RestrictPrivateChannelManagement = NewString(PERMISSIONS_ALL) s.DEPRECATED_DO_NOT_USE_RestrictPrivateChannelManagement = NewString(PERMISSIONS_ALL)
} }
if s.RestrictPublicChannelCreation == nil { if s.DEPRECATED_DO_NOT_USE_RestrictPublicChannelCreation == nil {
s.RestrictPublicChannelCreation = new(string) s.DEPRECATED_DO_NOT_USE_RestrictPublicChannelCreation = new(string)
// If this setting does not exist, assume migration from <3.6, so use management setting as default. // If this setting does not exist, assume migration from <3.6, so use management setting as default.
if *s.RestrictPublicChannelManagement == PERMISSIONS_CHANNEL_ADMIN { if *s.DEPRECATED_DO_NOT_USE_RestrictPublicChannelManagement == PERMISSIONS_CHANNEL_ADMIN {
*s.RestrictPublicChannelCreation = PERMISSIONS_TEAM_ADMIN *s.DEPRECATED_DO_NOT_USE_RestrictPublicChannelCreation = PERMISSIONS_TEAM_ADMIN
} else { } else {
*s.RestrictPublicChannelCreation = *s.RestrictPublicChannelManagement *s.DEPRECATED_DO_NOT_USE_RestrictPublicChannelCreation = *s.DEPRECATED_DO_NOT_USE_RestrictPublicChannelManagement
} }
} }
if s.RestrictPrivateChannelCreation == nil { if s.DEPRECATED_DO_NOT_USE_RestrictPrivateChannelCreation == nil {
// If this setting does not exist, assume migration from <3.6, so use management setting as default. // If this setting does not exist, assume migration from <3.6, so use management setting as default.
if *s.RestrictPrivateChannelManagement == PERMISSIONS_CHANNEL_ADMIN { if *s.DEPRECATED_DO_NOT_USE_RestrictPrivateChannelManagement == PERMISSIONS_CHANNEL_ADMIN {
s.RestrictPrivateChannelCreation = NewString(PERMISSIONS_TEAM_ADMIN) s.DEPRECATED_DO_NOT_USE_RestrictPrivateChannelCreation = NewString(PERMISSIONS_TEAM_ADMIN)
} else { } else {
s.RestrictPrivateChannelCreation = NewString(*s.RestrictPrivateChannelManagement) s.DEPRECATED_DO_NOT_USE_RestrictPrivateChannelCreation = NewString(*s.DEPRECATED_DO_NOT_USE_RestrictPrivateChannelManagement)
} }
} }
if s.RestrictPublicChannelDeletion == nil { if s.DEPRECATED_DO_NOT_USE_RestrictPublicChannelDeletion == nil {
// If this setting does not exist, assume migration from <3.6, so use management setting as default. // If this setting does not exist, assume migration from <3.6, so use management setting as default.
s.RestrictPublicChannelDeletion = NewString(*s.RestrictPublicChannelManagement) s.DEPRECATED_DO_NOT_USE_RestrictPublicChannelDeletion = NewString(*s.DEPRECATED_DO_NOT_USE_RestrictPublicChannelManagement)
} }
if s.RestrictPrivateChannelDeletion == nil { if s.DEPRECATED_DO_NOT_USE_RestrictPrivateChannelDeletion == nil {
// If this setting does not exist, assume migration from <3.6, so use management setting as default. // If this setting does not exist, assume migration from <3.6, so use management setting as default.
s.RestrictPrivateChannelDeletion = NewString(*s.RestrictPrivateChannelManagement) s.DEPRECATED_DO_NOT_USE_RestrictPrivateChannelDeletion = NewString(*s.DEPRECATED_DO_NOT_USE_RestrictPrivateChannelManagement)
} }
if s.RestrictPrivateChannelManageMembers == nil { if s.DEPRECATED_DO_NOT_USE_RestrictPrivateChannelManageMembers == nil {
s.RestrictPrivateChannelManageMembers = NewString(PERMISSIONS_ALL) s.DEPRECATED_DO_NOT_USE_RestrictPrivateChannelManageMembers = NewString(PERMISSIONS_ALL)
} }
if s.EnableXToLeaveChannelsFromLHS == nil { if s.EnableXToLeaveChannelsFromLHS == nil {
@ -1258,8 +1303,8 @@ func (s *TeamSettings) SetDefaults() {
s.ExperimentalDefaultChannels = []string{} s.ExperimentalDefaultChannels = []string{}
} }
if s.EnableTeamCreation == nil { if s.DEPRECATED_DO_NOT_USE_EnableTeamCreation == nil {
s.EnableTeamCreation = NewBool(true) s.DEPRECATED_DO_NOT_USE_EnableTeamCreation = NewBool(true)
} }
if s.EnableUserCreation == nil { if s.EnableUserCreation == nil {
@ -1624,51 +1669,6 @@ func (s *NativeAppSettings) SetDefaults() {
} }
} }
type WebrtcSettings struct {
Enable *bool
GatewayWebsocketUrl *string
GatewayAdminUrl *string
GatewayAdminSecret *string
StunURI *string
TurnURI *string
TurnUsername *string
TurnSharedKey *string
}
func (s *WebrtcSettings) SetDefaults() {
if s.Enable == nil {
s.Enable = NewBool(false)
}
if s.GatewayWebsocketUrl == nil {
s.GatewayWebsocketUrl = NewString("")
}
if s.GatewayAdminUrl == nil {
s.GatewayAdminUrl = NewString("")
}
if s.GatewayAdminSecret == nil {
s.GatewayAdminSecret = NewString("")
}
if s.StunURI == nil {
s.StunURI = NewString(WEBRTC_SETTINGS_DEFAULT_STUN_URI)
}
if s.TurnURI == nil {
s.TurnURI = NewString(WEBRTC_SETTINGS_DEFAULT_TURN_URI)
}
if s.TurnUsername == nil {
s.TurnUsername = NewString("")
}
if s.TurnSharedKey == nil {
s.TurnSharedKey = NewString("")
}
}
type ElasticsearchSettings struct { type ElasticsearchSettings struct {
ConnectionUrl *string ConnectionUrl *string
Username *string Username *string
@ -1886,14 +1886,6 @@ func (s *MessageExportSettings) SetDefaults() {
s.ExportFromTimestamp = NewInt64(0) s.ExportFromTimestamp = NewInt64(0)
} }
if s.EnableExport != nil && *s.EnableExport && *s.ExportFromTimestamp == int64(0) {
// when the feature is enabled via the System Console, use the current timestamp as the start time for future exports
s.ExportFromTimestamp = NewInt64(GetMillis())
} else if s.EnableExport != nil && !*s.EnableExport {
// when the feature is disabled, reset the timestamp so that the timestamp will be set if the feature is re-enabled
s.ExportFromTimestamp = NewInt64(0)
}
if s.BatchSize == nil { if s.BatchSize == nil {
s.BatchSize = NewInt(10000) s.BatchSize = NewInt(10000)
} }
@ -1959,7 +1951,6 @@ type Config struct {
MetricsSettings MetricsSettings MetricsSettings MetricsSettings
ExperimentalSettings ExperimentalSettings ExperimentalSettings ExperimentalSettings
AnalyticsSettings AnalyticsSettings AnalyticsSettings AnalyticsSettings
WebrtcSettings WebrtcSettings
ElasticsearchSettings ElasticsearchSettings ElasticsearchSettings ElasticsearchSettings
DataRetentionSettings DataRetentionSettings DataRetentionSettings DataRetentionSettings
MessageExportSettings MessageExportSettings MessageExportSettings MessageExportSettings
@ -2035,7 +2026,6 @@ func (o *Config) SetDefaults() {
o.RateLimitSettings.SetDefaults() o.RateLimitSettings.SetDefaults()
o.LogSettings.SetDefaults() o.LogSettings.SetDefaults()
o.JobSettings.SetDefaults() o.JobSettings.SetDefaults()
o.WebrtcSettings.SetDefaults()
o.MessageExportSettings.SetDefaults() o.MessageExportSettings.SetDefaults()
o.TimezoneSettings.SetDefaults() o.TimezoneSettings.SetDefaults()
o.DisplaySettings.SetDefaults() o.DisplaySettings.SetDefaults()
@ -2087,10 +2077,6 @@ func (o *Config) IsValid() *AppError {
return err return err
} }
if err := o.WebrtcSettings.isValid(); err != nil {
return err
}
if err := o.ServiceSettings.isValid(); err != nil { if err := o.ServiceSettings.isValid(); err != nil {
return err return err
} }
@ -2322,36 +2308,37 @@ func (ss *SamlSettings) isValid() *AppError {
return nil return nil
} }
func (ws *WebrtcSettings) isValid() *AppError {
if *ws.Enable {
if len(*ws.GatewayWebsocketUrl) == 0 || !IsValidWebsocketUrl(*ws.GatewayWebsocketUrl) {
return NewAppError("Config.IsValid", "model.config.is_valid.webrtc_gateway_ws_url.app_error", nil, "", http.StatusBadRequest)
} else if len(*ws.GatewayAdminUrl) == 0 || !IsValidHttpUrl(*ws.GatewayAdminUrl) {
return NewAppError("Config.IsValid", "model.config.is_valid.webrtc_gateway_admin_url.app_error", nil, "", http.StatusBadRequest)
} else if len(*ws.GatewayAdminSecret) == 0 {
return NewAppError("Config.IsValid", "model.config.is_valid.webrtc_gateway_admin_secret.app_error", nil, "", http.StatusBadRequest)
} else if len(*ws.StunURI) != 0 && !IsValidTurnOrStunServer(*ws.StunURI) {
return NewAppError("Config.IsValid", "model.config.is_valid.webrtc_stun_uri.app_error", nil, "", http.StatusBadRequest)
} else if len(*ws.TurnURI) != 0 {
if !IsValidTurnOrStunServer(*ws.TurnURI) {
return NewAppError("Config.IsValid", "model.config.is_valid.webrtc_turn_uri.app_error", nil, "", http.StatusBadRequest)
}
if len(*ws.TurnUsername) == 0 {
return NewAppError("Config.IsValid", "model.config.is_valid.webrtc_turn_username.app_error", nil, "", http.StatusBadRequest)
} else if len(*ws.TurnSharedKey) == 0 {
return NewAppError("Config.IsValid", "model.config.is_valid.webrtc_turn_shared_key.app_error", nil, "", http.StatusBadRequest)
}
}
}
return nil
}
func (ss *ServiceSettings) isValid() *AppError { func (ss *ServiceSettings) isValid() *AppError {
if !(*ss.ConnectionSecurity == CONN_SECURITY_NONE || *ss.ConnectionSecurity == CONN_SECURITY_TLS) { if !(*ss.ConnectionSecurity == CONN_SECURITY_NONE || *ss.ConnectionSecurity == CONN_SECURITY_TLS) {
return NewAppError("Config.IsValid", "model.config.is_valid.webserver_security.app_error", nil, "", http.StatusBadRequest) return NewAppError("Config.IsValid", "model.config.is_valid.webserver_security.app_error", nil, "", http.StatusBadRequest)
} }
if *ss.ConnectionSecurity == CONN_SECURITY_TLS && *ss.UseLetsEncrypt == false {
appErr := NewAppError("Config.IsValid", "model.config.is_valid.tls_cert_file.app_error", nil, "", http.StatusBadRequest)
if *ss.TLSCertFile == "" {
return appErr
} else if _, err := os.Stat(*ss.TLSCertFile); os.IsNotExist(err) {
return appErr
}
appErr = NewAppError("Config.IsValid", "model.config.is_valid.tls_key_file.app_error", nil, "", http.StatusBadRequest)
if *ss.TLSKeyFile == "" {
return appErr
} else if _, err := os.Stat(*ss.TLSKeyFile); os.IsNotExist(err) {
return appErr
}
}
if len(ss.TLSOverwriteCiphers) > 0 {
for _, cipher := range ss.TLSOverwriteCiphers {
if _, ok := ServerTLSSupportedCiphers[cipher]; !ok {
return NewAppError("Config.IsValid", "model.config.is_valid.tls_overwrite_cipher.app_error", map[string]interface{}{"name": cipher}, "", http.StatusBadRequest)
}
}
}
if *ss.ReadTimeout <= 0 { if *ss.ReadTimeout <= 0 {
return NewAppError("Config.IsValid", "model.config.is_valid.read_timeout.app_error", nil, "", http.StatusBadRequest) return NewAppError("Config.IsValid", "model.config.is_valid.read_timeout.app_error", nil, "", http.StatusBadRequest)
} }

View file

@ -7,6 +7,7 @@ import (
"encoding/json" "encoding/json"
"io" "io"
"net/http" "net/http"
"regexp"
) )
const ( const (
@ -14,6 +15,8 @@ const (
EMOJI_SORT_BY_NAME = "name" EMOJI_SORT_BY_NAME = "name"
) )
var EMOJI_PATTERN = regexp.MustCompile(`:[a-zA-Z0-9_-]+:`)
type Emoji struct { type Emoji struct {
Id string `json:"id"` Id string `json:"id"`
CreateAt int64 `json:"create_at"` CreateAt int64 `json:"create_at"`

View file

@ -85,7 +85,7 @@ func (o *FileInfo) IsValid() *AppError {
return NewAppError("FileInfo.IsValid", "model.file_info.is_valid.id.app_error", nil, "", http.StatusBadRequest) return NewAppError("FileInfo.IsValid", "model.file_info.is_valid.id.app_error", nil, "", http.StatusBadRequest)
} }
if len(o.CreatorId) != 26 { if len(o.CreatorId) != 26 && o.CreatorId != "nouser" {
return NewAppError("FileInfo.IsValid", "model.file_info.is_valid.user_id.app_error", nil, "id="+o.Id, http.StatusBadRequest) return NewAppError("FileInfo.IsValid", "model.file_info.is_valid.user_id.app_error", nil, "id="+o.Id, http.StatusBadRequest)
} }

View file

@ -0,0 +1,294 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
import (
"crypto"
"crypto/ecdsa"
"crypto/rand"
"encoding/asn1"
"encoding/base64"
"encoding/json"
"io"
"math/big"
"net/http"
"strconv"
"strings"
)
const (
POST_ACTION_TYPE_BUTTON = "button"
POST_ACTION_TYPE_SELECT = "select"
INTERACTIVE_DIALOG_TRIGGER_TIMEOUT_MILLISECONDS = 3000
)
type DoPostActionRequest struct {
SelectedOption string `json:"selected_option"`
}
type PostAction struct {
Id string `json:"id"`
Name string `json:"name"`
Type string `json:"type"`
DataSource string `json:"data_source"`
Options []*PostActionOptions `json:"options"`
Integration *PostActionIntegration `json:"integration,omitempty"`
}
type PostActionOptions struct {
Text string `json:"text"`
Value string `json:"value"`
}
type PostActionIntegration struct {
URL string `json:"url,omitempty"`
Context map[string]interface{} `json:"context,omitempty"`
}
type PostActionIntegrationRequest struct {
UserId string `json:"user_id"`
ChannelId string `json:"channel_id"`
TeamId string `json:"team_id"`
PostId string `json:"post_id"`
TriggerId string `json:"trigger_id"`
Type string `json:"type"`
DataSource string `json:"data_source"`
Context map[string]interface{} `json:"context,omitempty"`
}
type PostActionIntegrationResponse struct {
Update *Post `json:"update"`
EphemeralText string `json:"ephemeral_text"`
}
type PostActionAPIResponse struct {
Status string `json:"status"` // needed to maintain backwards compatibility
TriggerId string `json:"trigger_id"`
}
type Dialog struct {
CallbackId string `json:"callback_id"`
Title string `json:"title"`
IconURL string `json:"icon_url"`
Elements []DialogElement `json:"elements"`
SubmitLabel string `json:"submit_label"`
NotifyOnCancel bool `json:"notify_on_cancel"`
State string `json:"state"`
}
type DialogElement struct {
DisplayName string `json:"display_name"`
Name string `json:"name"`
Type string `json:"type"`
SubType string `json:"subtype"`
Default string `json:"default"`
Placeholder string `json:"placeholder"`
HelpText string `json:"help_text"`
Optional bool `json:"optional"`
MinLength int `json:"min_length"`
MaxLength int `json:"max_length"`
DataSource string `json:"data_source"`
Options []*PostActionOptions `json:"options"`
}
type OpenDialogRequest struct {
TriggerId string `json:"trigger_id"`
URL string `json:"url"`
Dialog Dialog `json:"dialog"`
}
type SubmitDialogRequest struct {
Type string `json:"type"`
URL string `json:"url,omitempty"`
CallbackId string `json:"callback_id"`
State string `json:"state"`
UserId string `json:"user_id"`
ChannelId string `json:"channel_id"`
TeamId string `json:"team_id"`
Submission map[string]interface{} `json:"submission"`
Cancelled bool `json:"cancelled"`
}
type SubmitDialogResponse struct {
Errors map[string]string `json:"errors,omitempty"`
}
func GenerateTriggerId(userId string, s crypto.Signer) (string, string, *AppError) {
clientTriggerId := NewId()
triggerData := strings.Join([]string{clientTriggerId, userId, strconv.FormatInt(GetMillis(), 10)}, ":") + ":"
h := crypto.SHA256
sum := h.New()
sum.Write([]byte(triggerData))
signature, err := s.Sign(rand.Reader, sum.Sum(nil), h)
if err != nil {
return "", "", NewAppError("GenerateTriggerId", "interactive_message.generate_trigger_id.signing_failed", nil, err.Error(), http.StatusInternalServerError)
}
base64Sig := base64.StdEncoding.EncodeToString(signature)
triggerId := base64.StdEncoding.EncodeToString([]byte(triggerData + base64Sig))
return clientTriggerId, triggerId, nil
}
func (r *PostActionIntegrationRequest) GenerateTriggerId(s crypto.Signer) (string, string, *AppError) {
clientTriggerId, triggerId, err := GenerateTriggerId(r.UserId, s)
if err != nil {
return "", "", err
}
r.TriggerId = triggerId
return clientTriggerId, triggerId, nil
}
func DecodeAndVerifyTriggerId(triggerId string, s *ecdsa.PrivateKey) (string, string, *AppError) {
triggerIdBytes, err := base64.StdEncoding.DecodeString(triggerId)
if err != nil {
return "", "", NewAppError("DecodeAndVerifyTriggerId", "interactive_message.decode_trigger_id.base64_decode_failed", nil, err.Error(), http.StatusBadRequest)
}
split := strings.Split(string(triggerIdBytes), ":")
if len(split) != 4 {
return "", "", NewAppError("DecodeAndVerifyTriggerId", "interactive_message.decode_trigger_id.missing_data", nil, "", http.StatusBadRequest)
}
clientTriggerId := split[0]
userId := split[1]
timestampStr := split[2]
timestamp, _ := strconv.ParseInt(timestampStr, 10, 64)
now := GetMillis()
if now-timestamp > INTERACTIVE_DIALOG_TRIGGER_TIMEOUT_MILLISECONDS {
return "", "", NewAppError("DecodeAndVerifyTriggerId", "interactive_message.decode_trigger_id.expired", map[string]interface{}{"Seconds": INTERACTIVE_DIALOG_TRIGGER_TIMEOUT_MILLISECONDS / 1000}, "", http.StatusBadRequest)
}
signature, err := base64.StdEncoding.DecodeString(split[3])
if err != nil {
return "", "", NewAppError("DecodeAndVerifyTriggerId", "interactive_message.decode_trigger_id.base64_decode_failed_signature", nil, err.Error(), http.StatusBadRequest)
}
var esig struct {
R, S *big.Int
}
if _, err := asn1.Unmarshal([]byte(signature), &esig); err != nil {
return "", "", NewAppError("DecodeAndVerifyTriggerId", "interactive_message.decode_trigger_id.signature_decode_failed", nil, err.Error(), http.StatusBadRequest)
}
triggerData := strings.Join([]string{clientTriggerId, userId, timestampStr}, ":") + ":"
h := crypto.SHA256
sum := h.New()
sum.Write([]byte(triggerData))
if !ecdsa.Verify(&s.PublicKey, sum.Sum(nil), esig.R, esig.S) {
return "", "", NewAppError("DecodeAndVerifyTriggerId", "interactive_message.decode_trigger_id.verify_signature_failed", nil, "", http.StatusBadRequest)
}
return clientTriggerId, userId, nil
}
func (r *OpenDialogRequest) DecodeAndVerifyTriggerId(s *ecdsa.PrivateKey) (string, string, *AppError) {
return DecodeAndVerifyTriggerId(r.TriggerId, s)
}
func (r *PostActionIntegrationRequest) ToJson() []byte {
b, _ := json.Marshal(r)
return b
}
func PostActionIntegrationRequestFromJson(data io.Reader) *PostActionIntegrationRequest {
var o *PostActionIntegrationRequest
err := json.NewDecoder(data).Decode(&o)
if err != nil {
return nil
}
return o
}
func (r *PostActionIntegrationResponse) ToJson() []byte {
b, _ := json.Marshal(r)
return b
}
func PostActionIntegrationResponseFromJson(data io.Reader) *PostActionIntegrationResponse {
var o *PostActionIntegrationResponse
err := json.NewDecoder(data).Decode(&o)
if err != nil {
return nil
}
return o
}
func SubmitDialogRequestFromJson(data io.Reader) *SubmitDialogRequest {
var o *SubmitDialogRequest
err := json.NewDecoder(data).Decode(&o)
if err != nil {
return nil
}
return o
}
func (r *SubmitDialogRequest) ToJson() []byte {
b, _ := json.Marshal(r)
return b
}
func SubmitDialogResponseFromJson(data io.Reader) *SubmitDialogResponse {
var o *SubmitDialogResponse
err := json.NewDecoder(data).Decode(&o)
if err != nil {
return nil
}
return o
}
func (r *SubmitDialogResponse) ToJson() []byte {
b, _ := json.Marshal(r)
return b
}
func (o *Post) StripActionIntegrations() {
attachments := o.Attachments()
if o.Props["attachments"] != nil {
o.Props["attachments"] = attachments
}
for _, attachment := range attachments {
for _, action := range attachment.Actions {
action.Integration = nil
}
}
}
func (o *Post) GetAction(id string) *PostAction {
for _, attachment := range o.Attachments() {
for _, action := range attachment.Actions {
if action.Id == id {
return action
}
}
}
return nil
}
func (o *Post) GenerateActionIds() {
if o.Props["attachments"] != nil {
o.Props["attachments"] = o.Attachments()
}
if attachments, ok := o.Props["attachments"].([]*SlackAttachment); ok {
for _, attachment := range attachments {
for _, action := range attachment.Actions {
if action.Id == "" {
action.Id = NewId()
}
}
}
}
}
func DoPostActionRequestFromJson(data io.Reader) *DoPostActionRequest {
var o *DoPostActionRequest
json.NewDecoder(data).Decode(&o)
return o
}

View file

@ -17,6 +17,7 @@ const (
JOB_TYPE_ELASTICSEARCH_POST_AGGREGATION = "elasticsearch_post_aggregation" JOB_TYPE_ELASTICSEARCH_POST_AGGREGATION = "elasticsearch_post_aggregation"
JOB_TYPE_LDAP_SYNC = "ldap_sync" JOB_TYPE_LDAP_SYNC = "ldap_sync"
JOB_TYPE_MIGRATIONS = "migrations" JOB_TYPE_MIGRATIONS = "migrations"
JOB_TYPE_PLUGINS = "plugins"
JOB_STATUS_PENDING = "pending" JOB_STATUS_PENDING = "pending"
JOB_STATUS_IN_PROGRESS = "in_progress" JOB_STATUS_IN_PROGRESS = "in_progress"

View file

@ -27,6 +27,8 @@ type License struct {
ExpiresAt int64 `json:"expires_at"` ExpiresAt int64 `json:"expires_at"`
Customer *Customer `json:"customer"` Customer *Customer `json:"customer"`
Features *Features `json:"features"` Features *Features `json:"features"`
SkuName string `json:"sku_name"`
SkuShortName string `json:"sku_short_name"`
} }
type Customer struct { type Customer struct {
@ -57,7 +59,7 @@ type Features struct {
CustomPermissionsSchemes *bool `json:"custom_permissions_schemes"` CustomPermissionsSchemes *bool `json:"custom_permissions_schemes"`
CustomTermsOfService *bool `json:"custom_terms_of_service"` CustomTermsOfService *bool `json:"custom_terms_of_service"`
// after we enabled more features for webrtc we'll need to control them with this // after we enabled more features we'll need to control them with this
FutureFeatures *bool `json:"future_features"` FutureFeatures *bool `json:"future_features"`
} }

View file

@ -5,6 +5,7 @@ package model
import ( import (
"encoding/json" "encoding/json"
"errors"
"fmt" "fmt"
"io" "io"
"io/ioutil" "io/ioutil"
@ -12,6 +13,7 @@ import (
"path/filepath" "path/filepath"
"strings" "strings"
"github.com/blang/semver"
"gopkg.in/yaml.v2" "gopkg.in/yaml.v2"
) )
@ -45,6 +47,8 @@ type PluginSetting struct {
// //
// "text" will result in a string setting that can be typed in manually. // "text" will result in a string setting that can be typed in manually.
// //
// "longtext" will result in a multi line string that can be typed in manually.
//
// "username" will result in a text setting that will autocomplete to a username. // "username" will result in a text setting that will autocomplete to a username.
Type string `json:"type" yaml:"type"` Type string `json:"type" yaml:"type"`
@ -109,6 +113,11 @@ type Manifest struct {
// A version number for your plugin. Semantic versioning is recommended: http://semver.org // A version number for your plugin. Semantic versioning is recommended: http://semver.org
Version string `json:"version" yaml:"version"` Version string `json:"version" yaml:"version"`
// The minimum Mattermost server version required for your plugin.
//
// Minimum server version: 5.6
MinServerVersion string `json:"min_server_version,omitempty" yaml:"min_server_version,omitempty"`
// Server defines the server-side portion of your plugin. // Server defines the server-side portion of your plugin.
Server *ManifestServer `json:"server,omitempty" yaml:"server,omitempty"` Server *ManifestServer `json:"server,omitempty" yaml:"server,omitempty"`
@ -240,6 +249,18 @@ func (m *Manifest) HasWebapp() bool {
return m.Webapp != nil return m.Webapp != nil
} }
func (m *Manifest) MeetMinServerVersion(serverVersion string) (bool, error) {
minServerVersion, err := semver.Parse(m.MinServerVersion)
if err != nil {
return false, errors.New("failed to parse MinServerVersion")
}
sv := semver.MustParse(serverVersion)
if sv.LT(minServerVersion) {
return false, nil
}
return true, nil
}
// FindManifest will find and parse the manifest in a given directory. // FindManifest will find and parse the manifest in a given directory.
// //
// In all cases other than a does-not-exist error, path is set to the path of the manifest file that was // In all cases other than a does-not-exist error, path is set to the path of the manifest file that was
@ -252,25 +273,23 @@ func FindManifest(dir string) (manifest *Manifest, path string, err error) {
f, ferr := os.Open(path) f, ferr := os.Open(path)
if ferr != nil { if ferr != nil {
if !os.IsNotExist(ferr) { if !os.IsNotExist(ferr) {
err = ferr return nil, "", ferr
return
} }
continue continue
} }
b, ioerr := ioutil.ReadAll(f) b, ioerr := ioutil.ReadAll(f)
f.Close() f.Close()
if ioerr != nil { if ioerr != nil {
err = ioerr return nil, path, ioerr
return
} }
var parsed Manifest var parsed Manifest
err = yaml.Unmarshal(b, &parsed) err = yaml.Unmarshal(b, &parsed)
if err != nil { if err != nil {
return return nil, path, err
} }
manifest = &parsed manifest = &parsed
manifest.Id = strings.ToLower(manifest.Id) manifest.Id = strings.ToLower(manifest.Id)
return return manifest, path, nil
} }
path = filepath.Join(dir, "plugin.json") path = filepath.Join(dir, "plugin.json")
@ -279,16 +298,15 @@ func FindManifest(dir string) (manifest *Manifest, path string, err error) {
if os.IsNotExist(ferr) { if os.IsNotExist(ferr) {
path = "" path = ""
} }
err = ferr return nil, path, ferr
return
} }
defer f.Close() defer f.Close()
var parsed Manifest var parsed Manifest
err = json.NewDecoder(f).Decode(&parsed) err = json.NewDecoder(f).Decode(&parsed)
if err != nil { if err != nil {
return return nil, path, err
} }
manifest = &parsed manifest = &parsed
manifest.Id = strings.ToLower(manifest.Id) manifest.Id = strings.ToLower(manifest.Id)
return return manifest, path, nil
} }

View file

@ -17,6 +17,7 @@ type PluginKeyValue struct {
PluginId string `json:"plugin_id"` PluginId string `json:"plugin_id"`
Key string `json:"key" db:"PKey"` Key string `json:"key" db:"PKey"`
Value []byte `json:"value" db:"PValue"` Value []byte `json:"value" db:"PValue"`
ExpireAt int64 `json:"expire_at"`
} }
func (kv *PluginKeyValue) IsValid() *AppError { func (kv *PluginKeyValue) IsValid() *AppError {

View file

@ -50,8 +50,6 @@ const (
PROPS_ADD_CHANNEL_MEMBER = "add_channel_member" PROPS_ADD_CHANNEL_MEMBER = "add_channel_member"
POST_PROPS_ADDED_USER_ID = "addedUserId" POST_PROPS_ADDED_USER_ID = "addedUserId"
POST_PROPS_DELETE_BY = "deleteBy" POST_PROPS_DELETE_BY = "deleteBy"
POST_ACTION_TYPE_BUTTON = "button"
POST_ACTION_TYPE_SELECT = "select"
) )
type Post struct { type Post struct {
@ -81,6 +79,9 @@ type Post struct {
FileIds StringArray `json:"file_ids,omitempty"` FileIds StringArray `json:"file_ids,omitempty"`
PendingPostId string `json:"pending_post_id" db:"-"` PendingPostId string `json:"pending_post_id" db:"-"`
HasReactions bool `json:"has_reactions,omitempty"` HasReactions bool `json:"has_reactions,omitempty"`
// Transient data populated before sending a post to the client
Metadata *PostMetadata `json:"metadata,omitempty" db:"-"`
} }
type PostEphemeral struct { type PostEphemeral struct {
@ -132,48 +133,16 @@ type PostForIndexing struct {
ParentCreateAt *int64 `json:"parent_create_at"` ParentCreateAt *int64 `json:"parent_create_at"`
} }
type DoPostActionRequest struct { // Clone shallowly copies the post.
SelectedOption string `json:"selected_option"` func (o *Post) Clone() *Post {
} copy := *o
return &copy
type PostAction struct {
Id string `json:"id"`
Name string `json:"name"`
Type string `json:"type"`
DataSource string `json:"data_source"`
Options []*PostActionOptions `json:"options"`
Integration *PostActionIntegration `json:"integration,omitempty"`
}
type PostActionOptions struct {
Text string `json:"text"`
Value string `json:"value"`
}
type PostActionIntegration struct {
URL string `json:"url,omitempty"`
Context StringInterface `json:"context,omitempty"`
}
type PostActionIntegrationRequest struct {
UserId string `json:"user_id"`
ChannelId string `json:"channel_id"`
TeamId string `json:"team_id"`
PostId string `json:"post_id"`
Type string `json:"type"`
DataSource string `json:"data_source"`
Context StringInterface `json:"context,omitempty"`
}
type PostActionIntegrationResponse struct {
Update *Post `json:"update"`
EphemeralText string `json:"ephemeral_text"`
} }
func (o *Post) ToJson() string { func (o *Post) ToJson() string {
copy := *o copy := o.Clone()
copy.StripActionIntegrations() copy.StripActionIntegrations()
b, _ := json.Marshal(&copy) b, _ := json.Marshal(copy)
return string(b) return string(b)
} }
@ -407,34 +376,6 @@ func (o *Post) ChannelMentions() []string {
return ChannelMentions(o.Message) return ChannelMentions(o.Message)
} }
func (r *PostActionIntegrationRequest) ToJson() string {
b, _ := json.Marshal(r)
return string(b)
}
func PostActionIntegrationRequesteFromJson(data io.Reader) *PostActionIntegrationRequest {
var o *PostActionIntegrationRequest
err := json.NewDecoder(data).Decode(&o)
if err != nil {
return nil
}
return o
}
func (r *PostActionIntegrationResponse) ToJson() string {
b, _ := json.Marshal(r)
return string(b)
}
func PostActionIntegrationResponseFromJson(data io.Reader) *PostActionIntegrationResponse {
var o *PostActionIntegrationResponse
err := json.NewDecoder(data).Decode(&o)
if err != nil {
return nil
}
return o
}
func (o *Post) Attachments() []*SlackAttachment { func (o *Post) Attachments() []*SlackAttachment {
if attachments, ok := o.Props["attachments"].([]*SlackAttachment); ok { if attachments, ok := o.Props["attachments"].([]*SlackAttachment); ok {
return attachments return attachments
@ -453,44 +394,6 @@ func (o *Post) Attachments() []*SlackAttachment {
return ret return ret
} }
func (o *Post) StripActionIntegrations() {
attachments := o.Attachments()
if o.Props["attachments"] != nil {
o.Props["attachments"] = attachments
}
for _, attachment := range attachments {
for _, action := range attachment.Actions {
action.Integration = nil
}
}
}
func (o *Post) GetAction(id string) *PostAction {
for _, attachment := range o.Attachments() {
for _, action := range attachment.Actions {
if action.Id == id {
return action
}
}
}
return nil
}
func (o *Post) GenerateActionIds() {
if o.Props["attachments"] != nil {
o.Props["attachments"] = o.Attachments()
}
if attachments, ok := o.Props["attachments"].([]*SlackAttachment); ok {
for _, attachment := range attachments {
for _, action := range attachment.Actions {
if action.Id == "" {
action.Id = NewId()
}
}
}
}
}
var markdownDestinationEscaper = strings.NewReplacer( var markdownDestinationEscaper = strings.NewReplacer(
`\`, `\\`, `\`, `\\`,
`<`, `\<`, `<`, `\<`,
@ -502,12 +405,12 @@ var markdownDestinationEscaper = strings.NewReplacer(
// WithRewrittenImageURLs returns a new shallow copy of the post where the message has been // WithRewrittenImageURLs returns a new shallow copy of the post where the message has been
// rewritten via RewriteImageURLs. // rewritten via RewriteImageURLs.
func (o *Post) WithRewrittenImageURLs(f func(string) string) *Post { func (o *Post) WithRewrittenImageURLs(f func(string) string) *Post {
copy := *o copy := o.Clone()
copy.Message = RewriteImageURLs(o.Message, f) copy.Message = RewriteImageURLs(o.Message, f)
if copy.MessageSource == "" && copy.Message != o.Message { if copy.MessageSource == "" && copy.Message != o.Message {
copy.MessageSource = o.Message copy.MessageSource = o.Message
} }
return &copy return copy
} }
func (o *PostEphemeral) ToUnsanitizedJson() string { func (o *PostEphemeral) ToUnsanitizedJson() string {
@ -515,12 +418,6 @@ func (o *PostEphemeral) ToUnsanitizedJson() string {
return string(b) return string(b)
} }
func DoPostActionRequestFromJson(data io.Reader) *DoPostActionRequest {
var o *DoPostActionRequest
json.NewDecoder(data).Decode(&o)
return o
}
// RewriteImageURLs takes a message and returns a copy that has all of the image URLs replaced // RewriteImageURLs takes a message and returns a copy that has all of the image URLs replaced
// according to the function f. For each image URL, f will be invoked, and the resulting markdown // according to the function f. For each image URL, f will be invoked, and the resulting markdown
// will contain the URL returned by that invocation instead. // will contain the URL returned by that invocation instead.

View file

@ -0,0 +1,22 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
const (
POST_EMBED_IMAGE PostEmbedType = "image"
POST_EMBED_MESSAGE_ATTACHMENT PostEmbedType = "message_attachment"
POST_EMBED_OPENGRAPH PostEmbedType = "opengraph"
)
type PostEmbedType string
type PostEmbed struct {
Type PostEmbedType `json:"type"`
// The URL of the embedded content. Used for image and OpenGraph embeds.
URL string `json:"url,omitempty"`
// Any additional data for the embedded content. Only used for OpenGraph embeds.
Data interface{} `json:"data,omitempty"`
}

View file

@ -0,0 +1,30 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
type PostMetadata struct {
// Embeds holds information required to render content embedded in the post. This includes the OpenGraph metadata
// for links in the post.
Embeds []*PostEmbed `json:"embeds,omitempty"`
// Emojis holds all custom emojis used in the post or used in reaction to the post.
Emojis []*Emoji `json:"emojis,omitempty"`
// Files holds information about the file attachments on the post.
Files []*FileInfo `json:"files,omitempty"`
// Images holds the dimensions of all external images in the post as a map of the image URL to its diemsnions.
// This includes image embeds (when the message contains a plaintext link to an image), Markdown images, images
// contained in the OpenGraph metadata, and images contained in message attachments. It does not contain
// the dimensions of any file attachments as those are stored in FileInfos.
Images map[string]*PostImage `json:"images,omitempty"`
// Reactions holds reactions made to the post.
Reactions []*Reaction `json:"reactions,omitempty"`
}
type PostImage struct {
Width int `json:"width"`
Height int `json:"height"`
}

View file

@ -42,6 +42,11 @@ const (
PREFERENCE_EMAIL_INTERVAL_NO_BATCHING_SECONDS = "30" // the "immediate" setting is actually 30s PREFERENCE_EMAIL_INTERVAL_NO_BATCHING_SECONDS = "30" // the "immediate" setting is actually 30s
PREFERENCE_EMAIL_INTERVAL_BATCHING_SECONDS = "900" // fifteen minutes is 900 seconds PREFERENCE_EMAIL_INTERVAL_BATCHING_SECONDS = "900" // fifteen minutes is 900 seconds
PREFERENCE_EMAIL_INTERVAL_IMMEDIATELY = "immediately"
PREFERENCE_EMAIL_INTERVAL_FIFTEEN = "fifteen"
PREFERENCE_EMAIL_INTERVAL_FIFTEEN_AS_SECONDS = "900"
PREFERENCE_EMAIL_INTERVAL_HOUR = "hour"
PREFERENCE_EMAIL_INTERVAL_HOUR_AS_SECONDS = "3600"
) )
type Preference struct { type Preference struct {

View file

@ -10,7 +10,7 @@ import (
const ( const (
USER_AUTH_SERVICE_SAML = "saml" USER_AUTH_SERVICE_SAML = "saml"
USER_AUTH_SERVICE_SAML_TEXT = "With SAML" USER_AUTH_SERVICE_SAML_TEXT = "SAML"
) )
type SamlAuthRequest struct { type SamlAuthRequest struct {

View file

@ -64,7 +64,9 @@ func StringifySlackFieldValue(a []*SlackAttachment) []*SlackAttachment {
// This method only parses and processes the attachments, // This method only parses and processes the attachments,
// all else should be set in the post which is passed // all else should be set in the post which is passed
func ParseSlackAttachment(post *Post, attachments []*SlackAttachment) { func ParseSlackAttachment(post *Post, attachments []*SlackAttachment) {
if post.Type == "" {
post.Type = POST_SLACK_ATTACHMENT post.Type = POST_SLACK_ATTACHMENT
}
for _, attachment := range attachments { for _, attachment := range attachments {
attachment.Text = ParseSlackLinksToMarkdown(attachment.Text) attachment.Text = ParseSlackLinksToMarkdown(attachment.Text)

View file

@ -11,7 +11,6 @@ import (
"unicode/utf8" "unicode/utf8"
) )
// we only ever need the latest version of terms of service
const TERMS_OF_SERVICE_CACHE_SIZE = 1 const TERMS_OF_SERVICE_CACHE_SIZE = 1
type TermsOfService struct { type TermsOfService struct {
@ -58,7 +57,7 @@ func InvalidTermsOfServiceError(fieldName string, termsOfServiceId string) *AppE
if termsOfServiceId != "" { if termsOfServiceId != "" {
details = "terms_of_service_id=" + termsOfServiceId details = "terms_of_service_id=" + termsOfServiceId
} }
return NewAppError("TermsOfServiceStore.IsValid", id, map[string]interface{}{"MaxLength": POST_MESSAGE_MAX_RUNES_V2}, details, http.StatusBadRequest) return NewAppError("TermsOfService.IsValid", id, map[string]interface{}{"MaxLength": POST_MESSAGE_MAX_RUNES_V2}, details, http.StatusBadRequest)
} }
func (t *TermsOfService) PreSave() { func (t *TermsOfService) PreSave() {

View file

@ -74,7 +74,6 @@ type User struct {
MfaActive bool `json:"mfa_active,omitempty"` MfaActive bool `json:"mfa_active,omitempty"`
MfaSecret string `json:"mfa_secret,omitempty"` MfaSecret string `json:"mfa_secret,omitempty"`
LastActivityAt int64 `db:"-" json:"last_activity_at,omitempty"` LastActivityAt int64 `db:"-" json:"last_activity_at,omitempty"`
AcceptedTermsOfServiceId string `json:"accepted_terms_of_service_id,omitempty"` // TODO remove this field when new TOS user action table is created
} }
type UserPatch struct { type UserPatch struct {
@ -499,11 +498,7 @@ func (u *User) IsSAMLUser() bool {
} }
func (u *User) GetPreferredTimezone() string { func (u *User) GetPreferredTimezone() string {
if u.Timezone["useAutomaticTimezone"] == "true" { return GetPreferredTimezone(u.Timezone)
return u.Timezone["automaticTimezone"]
}
return u.Timezone["manualTimezone"]
} }
// UserFromJson will decode the input and return a User // UserFromJson will decode the input and return a User
@ -639,3 +634,9 @@ func IsValidCommentsNotifyLevel(notifyLevel string) bool {
notifyLevel == COMMENTS_NOTIFY_ROOT || notifyLevel == COMMENTS_NOTIFY_ROOT ||
notifyLevel == COMMENTS_NOTIFY_NEVER notifyLevel == COMMENTS_NOTIFY_NEVER
} }
func IsValidEmailBatchingInterval(emailInterval string) bool {
return emailInterval == PREFERENCE_EMAIL_INTERVAL_IMMEDIATELY ||
emailInterval == PREFERENCE_EMAIL_INTERVAL_FIFTEEN ||
emailInterval == PREFERENCE_EMAIL_INTERVAL_HOUR
}

View file

@ -8,6 +8,10 @@ import (
"io" "io"
) )
const USER_SEARCH_MAX_LIMIT = 1000
const USER_SEARCH_DEFAULT_LIMIT = 100
// UserSearch captures the parameters provided by a client for initiating a user search.
type UserSearch struct { type UserSearch struct {
Term string `json:"term"` Term string `json:"term"`
TeamId string `json:"team_id"` TeamId string `json:"team_id"`
@ -16,17 +20,38 @@ type UserSearch struct {
NotInChannelId string `json:"not_in_channel_id"` NotInChannelId string `json:"not_in_channel_id"`
AllowInactive bool `json:"allow_inactive"` AllowInactive bool `json:"allow_inactive"`
WithoutTeam bool `json:"without_team"` WithoutTeam bool `json:"without_team"`
Limit int `json:"limit"`
} }
// ToJson convert a User to a json string // ToJson convert a User to a json string
func (u *UserSearch) ToJson() string { func (u *UserSearch) ToJson() []byte {
b, _ := json.Marshal(u) b, _ := json.Marshal(u)
return string(b) return b
} }
// UserSearchFromJson will decode the input and return a User // UserSearchFromJson will decode the input and return a User
func UserSearchFromJson(data io.Reader) *UserSearch { func UserSearchFromJson(data io.Reader) *UserSearch {
var us *UserSearch var us *UserSearch
json.NewDecoder(data).Decode(&us) json.NewDecoder(data).Decode(&us)
if us.Limit == 0 {
us.Limit = USER_SEARCH_DEFAULT_LIMIT
}
return us return us
} }
// UserSearchOptions captures internal parameters derived from the user's permissions and a
// UserSearch request.
type UserSearchOptions struct {
// IsAdmin tracks whether or not the search is being conducted by an administrator.
IsAdmin bool
// AllowEmails allows search to examine the emails of users.
AllowEmails bool
// AllowFullNames allows search to examine the full names of users, vs. just usernames and nicknames.
AllowFullNames bool
// AllowInactive configures whether or not to return inactive users in the search results.
AllowInactive bool
// Limit limits the total number of results returned.
Limit int
}

View file

@ -0,0 +1,61 @@
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
import (
"encoding/json"
"fmt"
"io"
"net/http"
)
type UserTermsOfService struct {
UserId string `json:"user_id"`
TermsOfServiceId string `json:"terms_of_service_id"`
CreateAt int64 `json:"create_at"`
}
func (ut *UserTermsOfService) IsValid() *AppError {
if len(ut.UserId) != 26 {
return InvalidUserTermsOfServiceError("user_id", ut.UserId)
}
if len(ut.TermsOfServiceId) != 26 {
return InvalidUserTermsOfServiceError("terms_of_service_id", ut.UserId)
}
if ut.CreateAt == 0 {
return InvalidUserTermsOfServiceError("create_at", ut.UserId)
}
return nil
}
func (ut *UserTermsOfService) ToJson() string {
b, _ := json.Marshal(ut)
return string(b)
}
func (ut *UserTermsOfService) PreSave() {
if ut.UserId == "" {
ut.UserId = NewId()
}
ut.CreateAt = GetMillis()
}
func UserTermsOfServiceFromJson(data io.Reader) *UserTermsOfService {
var userTermsOfService *UserTermsOfService
json.NewDecoder(data).Decode(&userTermsOfService)
return userTermsOfService
}
func InvalidUserTermsOfServiceError(fieldName string, userTermsOfServiceId string) *AppError {
id := fmt.Sprintf("model.user_terms_of_service.is_valid.%s.app_error", fieldName)
details := ""
if userTermsOfServiceId != "" {
details = "user_terms_of_service_user_id=" + userTermsOfServiceId
}
return NewAppError("UserTermsOfService.IsValid", id, nil, details, http.StatusBadRequest)
}

View file

@ -564,3 +564,26 @@ func IsDomainName(s string) bool {
return ok return ok
} }
func RemoveDuplicateStrings(in []string) []string {
out := []string{}
seen := make(map[string]bool, len(in))
for _, item := range in {
if !seen[item] {
out = append(out, item)
seen[item] = true
}
}
return out
}
func GetPreferredTimezone(timezone StringMap) string {
if timezone["useAutomaticTimezone"] == "true" {
return timezone["automaticTimezone"]
}
return timezone["manualTimezone"]
}

View file

@ -13,6 +13,8 @@ import (
// It should be maintained in chronological order with most current // It should be maintained in chronological order with most current
// release at the front of the list. // release at the front of the list.
var versions = []string{ var versions = []string{
"5.6.0",
"5.5.0",
"5.4.0", "5.4.0",
"5.3.0", "5.3.0",
"5.2.0", "5.2.0",

View file

@ -1,39 +0,0 @@
// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
import (
"encoding/json"
"io"
)
type WebrtcInfoResponse struct {
Token string `json:"token"`
GatewayUrl string `json:"gateway_url"`
StunUri string `json:"stun_uri,omitempty"`
TurnUri string `json:"turn_uri,omitempty"`
TurnPassword string `json:"turn_password,omitempty"`
TurnUsername string `json:"turn_username,omitempty"`
}
type GatewayResponse struct {
Status string `json:"janus"`
}
func GatewayResponseFromJson(data io.Reader) *GatewayResponse {
var o *GatewayResponse
json.NewDecoder(data).Decode(&o)
return o
}
func (o *WebrtcInfoResponse) ToJson() string {
b, _ := json.Marshal(o)
return string(b)
}
func WebrtcInfoResponseFromJson(data io.Reader) *WebrtcInfoResponse {
var o *WebrtcInfoResponse
json.NewDecoder(data).Decode(&o)
return o
}

View file

@ -37,7 +37,6 @@ const (
WEBSOCKET_EVENT_EPHEMERAL_MESSAGE = "ephemeral_message" WEBSOCKET_EVENT_EPHEMERAL_MESSAGE = "ephemeral_message"
WEBSOCKET_EVENT_STATUS_CHANGE = "status_change" WEBSOCKET_EVENT_STATUS_CHANGE = "status_change"
WEBSOCKET_EVENT_HELLO = "hello" WEBSOCKET_EVENT_HELLO = "hello"
WEBSOCKET_EVENT_WEBRTC = "webrtc"
WEBSOCKET_AUTHENTICATION_CHALLENGE = "authentication_challenge" WEBSOCKET_AUTHENTICATION_CHALLENGE = "authentication_challenge"
WEBSOCKET_EVENT_REACTION_ADDED = "reaction_added" WEBSOCKET_EVENT_REACTION_ADDED = "reaction_added"
WEBSOCKET_EVENT_REACTION_REMOVED = "reaction_removed" WEBSOCKET_EVENT_REACTION_REMOVED = "reaction_removed"
@ -50,6 +49,7 @@ const (
WEBSOCKET_EVENT_ROLE_UPDATED = "role_updated" WEBSOCKET_EVENT_ROLE_UPDATED = "role_updated"
WEBSOCKET_EVENT_LICENSE_CHANGED = "license_changed" WEBSOCKET_EVENT_LICENSE_CHANGED = "license_changed"
WEBSOCKET_EVENT_CONFIG_CHANGED = "config_changed" WEBSOCKET_EVENT_CONFIG_CHANGED = "config_changed"
WEBSOCKET_EVENT_OPEN_DIALOG = "open_dialog"
) )
type WebSocketMessage interface { type WebSocketMessage interface {

34
server/Gopkg.lock generated
View file

@ -1,6 +1,14 @@
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. # This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
[[projects]]
digest = "1:aba270497eb2d49f5cba6f4162d524b9a1195a24cbce8be20bf56a0051f47deb"
name = "github.com/blang/semver"
packages = ["."]
pruneopts = "NUT"
revision = "2ee87856327ba09384cabd113bc6b5d174e9ec0f"
version = "v3.5.1"
[[projects]] [[projects]]
digest = "1:ffe9824d294da03b391f44e1ae8281281b4afc1bdaa9588c9097785e3af10cec" digest = "1:ffe9824d294da03b391f44e1ae8281281b4afc1bdaa9588c9097785e3af10cec"
name = "github.com/davecgh/go-spew" name = "github.com/davecgh/go-spew"
@ -9,6 +17,14 @@
revision = "8991bc29aa16c548c550c7ff78260e27b9ab7c73" revision = "8991bc29aa16c548c550c7ff78260e27b9ab7c73"
version = "v1.1.1" version = "v1.1.1"
[[projects]]
branch = "master"
digest = "1:665c8850f673be8d358fe61ab00412049e685202aa7466ae5c72ad50d89c84f7"
name = "github.com/dyatlov/go-opengraph"
packages = ["opengraph"]
pruneopts = "NUT"
revision = "816b6608b3c8c1e871bc9cf777f390e2532081fe"
[[projects]] [[projects]]
digest = "1:1b91ae0dc69a41d4c2ed23ea5cffb721ea63f5037ca4b81e6d6771fbb8f45129" digest = "1:1b91ae0dc69a41d4c2ed23ea5cffb721ea63f5037ca4b81e6d6771fbb8f45129"
name = "github.com/fsnotify/fsnotify" name = "github.com/fsnotify/fsnotify"
@ -48,18 +64,18 @@
revision = "a51a35ae3232254685f26a0b6d995ca0e81e2248" revision = "a51a35ae3232254685f26a0b6d995ca0e81e2248"
[[projects]] [[projects]]
digest = "1:58ba5285227b0f635652cd4aa82c4cfd00b590191eadd823462f0c9f64e3ae07" digest = "1:ce8deaa2f422b7315ee4fa91f29963ed24f33eb1e1f921fe9f27ce7987776c01"
name = "github.com/hashicorp/go-hclog" name = "github.com/hashicorp/go-hclog"
packages = ["."] packages = ["."]
pruneopts = "NUT" pruneopts = "NUT"
revision = "69ff559dc25f3b435631604f573a5fa1efdb6433" revision = "e45cbeb79f0411b1cfedd3f226ff69d5d433c762"
[[projects]] [[projects]]
digest = "1:532090ffc3b05a7e4c0229dd2698d79149f2e0683df993224a8b202f607fb605" digest = "1:af00abbd22cc527703068245c819a5f53567918f8c088157a4c01dd6244b58fb"
name = "github.com/hashicorp/go-plugin" name = "github.com/hashicorp/go-plugin"
packages = ["."] packages = ["."]
pruneopts = "NUT" pruneopts = "NUT"
revision = "e8d22c780116115ae5624720c9af0c97afe4f551" revision = "a4620f9913d19f03a6bf19b2f304daaaf83ea130"
[[projects]] [[projects]]
digest = "1:11c6c696067d3127ecf332b10f89394d386d9083f82baf71f40f2da31841a009" digest = "1:11c6c696067d3127ecf332b10f89394d386d9083f82baf71f40f2da31841a009"
@ -97,7 +113,7 @@
version = "v1.8.0" version = "v1.8.0"
[[projects]] [[projects]]
digest = "1:fcaa0c4871e4b49fb30d986e688c069328c042eae6ef89d0ead9882d2d450648" digest = "1:7496e8dfee311245ba337d464a50a50af13ab59a7fde3c474c9933671c9a6eaa"
name = "github.com/mattermost/mattermost-server" name = "github.com/mattermost/mattermost-server"
packages = [ packages = [
"einterfaces", "einterfaces",
@ -109,8 +125,8 @@
"utils/markdown", "utils/markdown",
] ]
pruneopts = "NUT" pruneopts = "NUT"
revision = "d5b613cb1bbdaa856fa126e7102d94783b9e80b6" revision = "0c1207215852a8726c3f09dea157d597fec368df"
version = "v5.4.0" version = "v5.6.0"
[[projects]] [[projects]]
branch = "mattermost" branch = "mattermost"
@ -277,10 +293,12 @@
[[projects]] [[projects]]
branch = "master" branch = "master"
digest = "1:d39e451e542c7c064d7e29050eb50993a7484d4a3b538387c0f2ac32b5b9cdd8" digest = "1:43144a8b3203f89adbed21f991f29fb5c9fc173b1e8e1c27fc1888f6a25b9618"
name = "golang.org/x/net" name = "golang.org/x/net"
packages = [ packages = [
"context", "context",
"html",
"html/atom",
"http/httpguts", "http/httpguts",
"http2", "http2",
"http2/hpack", "http2/hpack",

View file

@ -5,7 +5,7 @@
[[constraint]] [[constraint]]
name = "github.com/mattermost/mattermost-server" name = "github.com/mattermost/mattermost-server"
version = "~5.4.0" version = "~5.6.0"
[[constraint]] [[constraint]]
name = "github.com/stretchr/testify" name = "github.com/stretchr/testify"