mirror of
https://github.com/cwinfo/matterbridge.git
synced 2025-07-04 05:27:44 +00:00
Update dependencies and remove old matterclient lib (#2067)
This commit is contained in:
36
vendor/github.com/mattermost/logr/.gitignore
generated
vendored
36
vendor/github.com/mattermost/logr/.gitignore
generated
vendored
@ -1,36 +0,0 @@
|
||||
# Binaries for programs and plugins
|
||||
*.exe
|
||||
*.dll
|
||||
*.so
|
||||
*.dylib
|
||||
debug
|
||||
dynip
|
||||
|
||||
# Test binary, build with `go test -c`
|
||||
*.test
|
||||
|
||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||
*.out
|
||||
|
||||
# Output of profiler
|
||||
*.prof
|
||||
|
||||
# Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736
|
||||
.glide/
|
||||
|
||||
# IntelliJ config
|
||||
.idea
|
||||
|
||||
# log files
|
||||
*.log
|
||||
|
||||
# transient directories
|
||||
vendor
|
||||
output
|
||||
build
|
||||
app
|
||||
logs
|
||||
|
||||
# test apps
|
||||
test/cmd/testapp1/testapp1
|
||||
test/cmd/simple/simple
|
4
vendor/github.com/mattermost/logr/.travis.yml
generated
vendored
4
vendor/github.com/mattermost/logr/.travis.yml
generated
vendored
@ -1,4 +0,0 @@
|
||||
language: go
|
||||
sudo: false
|
||||
go:
|
||||
- 1.x
|
21
vendor/github.com/mattermost/logr/LICENSE
generated
vendored
21
vendor/github.com/mattermost/logr/LICENSE
generated
vendored
@ -1,21 +0,0 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 wiggin77
|
||||
|
||||
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.
|
193
vendor/github.com/mattermost/logr/README.md
generated
vendored
193
vendor/github.com/mattermost/logr/README.md
generated
vendored
@ -1,193 +0,0 @@
|
||||
# logr
|
||||
|
||||
[](http://godoc.org/github.com/mattermost/logr)
|
||||
[](https://goreportcard.com/report/github.com/mattermost/logr)
|
||||
|
||||
Logr is a fully asynchronous, contextual logger for Go.
|
||||
|
||||
It is very much inspired by [Logrus](https://github.com/sirupsen/logrus) but addresses two issues:
|
||||
|
||||
1. Logr is fully asynchronous, meaning that all formatting and writing is done in the background. Latency sensitive applications benefit from not waiting for logging to complete.
|
||||
|
||||
2. Logr provides custom filters which provide more flexibility than Trace, Debug, Info... levels. If you need to temporarily increase verbosity of logging while tracking down a problem you can avoid the fire-hose that typically comes from Debug or Trace by using custom filters.
|
||||
|
||||
## Concepts
|
||||
|
||||
<!-- markdownlint-disable MD033 -->
|
||||
| entity | description |
|
||||
| ------ | ----------- |
|
||||
| Logr | Engine instance typically instantiated once; used to configure logging.<br>```lgr := &Logr{}```|
|
||||
| Logger | Provides contextual logging via fields; lightweight, can be created once and accessed globally or create on demand.<br>```logger := lgr.NewLogger()```<br>```logger2 := logger.WithField("user", "Sam")```|
|
||||
| Target | A destination for log items such as console, file, database or just about anything that can be written to. Each target has its own filter/level and formatter, and any number of targets can be added to a Logr. Targets for syslog and any io.Writer are built-in and it is easy to create your own. You can also use any [Logrus hooks](https://github.com/sirupsen/logrus/wiki/Hooks) via a simple [adapter](https://github.com/wiggin77/logrus4logr).|
|
||||
| Filter | Determines which logging calls get written versus filtered out. Also determines which logging calls generate a stack trace.<br>```filter := &logr.StdFilter{Lvl: logr.Warn, Stacktrace: logr.Fatal}```|
|
||||
| Formatter | Formats the output. Logr includes built-in formatters for JSON and plain text with delimiters. It is easy to create your own formatters or you can also use any [Logrus formatters](https://github.com/sirupsen/logrus#formatters) via a simple [adapter](https://github.com/wiggin77/logrus4logr).<br>```formatter := &format.Plain{Delim: " \| "}```|
|
||||
|
||||
## Usage
|
||||
|
||||
```go
|
||||
// Create Logr instance.
|
||||
lgr := &logr.Logr{}
|
||||
|
||||
// Create a filter and formatter. Both can be shared by multiple
|
||||
// targets.
|
||||
filter := &logr.StdFilter{Lvl: logr.Warn, Stacktrace: logr.Error}
|
||||
formatter := &format.Plain{Delim: " | "}
|
||||
|
||||
// WriterTarget outputs to any io.Writer
|
||||
t := target.NewWriterTarget(filter, formatter, os.StdOut, 1000)
|
||||
lgr.AddTarget(t)
|
||||
|
||||
// One or more Loggers can be created, shared, used concurrently,
|
||||
// or created on demand.
|
||||
logger := lgr.NewLogger().WithField("user", "Sarah")
|
||||
|
||||
// Now we can log to the target(s).
|
||||
logger.Debug("login attempt")
|
||||
logger.Error("login failed")
|
||||
|
||||
// Ensure targets are drained before application exit.
|
||||
lgr.Shutdown()
|
||||
```
|
||||
|
||||
## Fields
|
||||
|
||||
Fields allow for contextual logging, meaning information can be added to log statements without changing the statements themselves. Information can be shared across multiple logging statements thus allowing log analysis tools to group them.
|
||||
|
||||
Fields are added via Loggers:
|
||||
|
||||
```go
|
||||
lgr := &Logr{}
|
||||
// ... add targets ...
|
||||
logger := lgr.NewLogger().WithFields(logr.Fields{
|
||||
"user": user,
|
||||
"role": role})
|
||||
logger.Info("login attempt")
|
||||
// ... later ...
|
||||
logger.Info("login successful")
|
||||
```
|
||||
|
||||
`Logger.WithFields` can be used to create additional Loggers that add more fields.
|
||||
|
||||
Logr fields are inspired by and work the same as [Logrus fields](https://github.com/sirupsen/logrus#fields).
|
||||
|
||||
## Filters
|
||||
|
||||
Logr supports the traditional seven log levels via `logr.StdFilter`: Panic, Fatal, Error, Warning, Info, Debug, and Trace.
|
||||
|
||||
```go
|
||||
// When added to a target, this filter will only allow
|
||||
// log statements with level severity Warn or higher.
|
||||
// It will also generate stack traces for Error or higher.
|
||||
filter := &logr.StdFilter{Lvl: logr.Warn, Stacktrace: logr.Error}
|
||||
```
|
||||
|
||||
Logr also supports custom filters (logr.CustomFilter) which allow fine grained inclusion of log items without turning on the fire-hose.
|
||||
|
||||
```go
|
||||
// create custom levels; use IDs > 10.
|
||||
LoginLevel := logr.Level{ID: 100, Name: "login ", Stacktrace: false}
|
||||
LogoutLevel := logr.Level{ID: 101, Name: "logout", Stacktrace: false}
|
||||
|
||||
lgr := &logr.Logr{}
|
||||
|
||||
// create a custom filter with custom levels.
|
||||
filter := &logr.CustomFilter{}
|
||||
filter.Add(LoginLevel, LogoutLevel)
|
||||
|
||||
formatter := &format.Plain{Delim: " | "}
|
||||
tgr := target.NewWriterTarget(filter, formatter, os.StdOut, 1000)
|
||||
lgr.AddTarget(tgr)
|
||||
logger := lgr.NewLogger().WithFields(logr.Fields{"user": "Bob", "role": "admin"})
|
||||
|
||||
logger.Log(LoginLevel, "this item will get logged")
|
||||
logger.Debug("won't be logged since Debug wasn't added to custom filter")
|
||||
```
|
||||
|
||||
Both filter types allow you to determine which levels require a stack trace to be output. Note that generating stack traces cannot happen fully asynchronously and thus add latency to the calling goroutine.
|
||||
|
||||
## Targets
|
||||
|
||||
There are built-in targets for outputting to syslog, file, or any `io.Writer`. More will be added.
|
||||
|
||||
You can use any [Logrus hooks](https://github.com/sirupsen/logrus/wiki/Hooks) via a simple [adapter](https://github.com/wiggin77/logrus4logr).
|
||||
|
||||
You can create your own target by implementing the [Target](./target.go) interface.
|
||||
|
||||
An easier method is to use the [logr.Basic](./target.go) type target and build your functionality on that. Basic handles all the queuing and other plumbing so you only need to implement two methods. Example target that outputs to `io.Writer`:
|
||||
|
||||
```go
|
||||
type Writer struct {
|
||||
logr.Basic
|
||||
out io.Writer
|
||||
}
|
||||
|
||||
func NewWriterTarget(filter logr.Filter, formatter logr.Formatter, out io.Writer, maxQueue int) *Writer {
|
||||
w := &Writer{out: out}
|
||||
w.Basic.Start(w, w, filter, formatter, maxQueue)
|
||||
return w
|
||||
}
|
||||
|
||||
// Write will always be called by a single goroutine, so no locking needed.
|
||||
// Just convert a log record to a []byte using the formatter and output the
|
||||
// bytes to your sink.
|
||||
func (w *Writer) Write(rec *logr.LogRec) error {
|
||||
_, stacktrace := w.IsLevelEnabled(rec.Level())
|
||||
|
||||
// take a buffer from the pool to avoid allocations or just allocate a new one.
|
||||
buf := rec.Logger().Logr().BorrowBuffer()
|
||||
defer rec.Logger().Logr().ReleaseBuffer(buf)
|
||||
|
||||
buf, err := w.Formatter().Format(rec, stacktrace, buf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = w.out.Write(buf.Bytes())
|
||||
return err
|
||||
}
|
||||
```
|
||||
|
||||
## Formatters
|
||||
|
||||
Logr has two built-in formatters, one for JSON and the other plain, delimited text.
|
||||
|
||||
You can use any [Logrus formatters](https://github.com/sirupsen/logrus#formatters) via a simple [adapter](https://github.com/wiggin77/logrus4logr).
|
||||
|
||||
You can create your own formatter by implementing the [Formatter](./formatter.go) interface:
|
||||
|
||||
```go
|
||||
Format(rec *LogRec, stacktrace bool, buf *bytes.Buffer) (*bytes.Buffer, error)
|
||||
```
|
||||
|
||||
## Handlers
|
||||
|
||||
When creating the Logr instance, you can add several handlers that get called when exceptional events occur:
|
||||
|
||||
### ```Logr.OnLoggerError(err error)```
|
||||
|
||||
Called any time an internal logging error occurs. For example, this can happen when a target cannot connect to its data sink.
|
||||
|
||||
It may be tempting to log this error, however there is a danger that logging this will simply generate another error and so on. If you must log it, use a target and custom level specifically for this event and ensure it cannot generate more errors.
|
||||
|
||||
### ```Logr.OnQueueFull func(rec *LogRec, maxQueueSize int) bool```
|
||||
|
||||
Called on an attempt to add a log record to a full Logr queue. This generally means the Logr maximum queue size is too small, or at least one target is very slow. Logr maximum queue size can be changed before adding any targets via:
|
||||
|
||||
```go
|
||||
lgr := logr.Logr{MaxQueueSize: 10000}
|
||||
```
|
||||
|
||||
Returning true will drop the log record. False will block until the log record can be added, which creates a natural throttle at the expense of latency for the calling goroutine. The default is to block.
|
||||
|
||||
### ```Logr.OnTargetQueueFull func(target Target, rec *LogRec, maxQueueSize int) bool```
|
||||
|
||||
Called on an attempt to add a log record to a full target queue. This generally means your target's max queue size is too small, or the target is very slow to output.
|
||||
|
||||
As with the Logr queue, returning true will drop the log record. False will block until the log record can be added, which creates a natural throttle at the expense of latency for the calling goroutine. The default is to block.
|
||||
|
||||
### ```Logr.OnExit func(code int) and Logr.OnPanic func(err interface{})```
|
||||
|
||||
OnExit and OnPanic are called when the Logger.FatalXXX and Logger.PanicXXX functions are called respectively.
|
||||
|
||||
In both cases the default behavior is to shut down gracefully, draining all targets, and calling `os.Exit` or `panic` respectively.
|
||||
|
||||
When adding your own handlers, be sure to call `Logr.Shutdown` before exiting the application to avoid losing log records.
|
11
vendor/github.com/mattermost/logr/config.go
generated
vendored
11
vendor/github.com/mattermost/logr/config.go
generated
vendored
@ -1,11 +0,0 @@
|
||||
package logr
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/wiggin77/cfg"
|
||||
)
|
||||
|
||||
func ConfigLogger(config *cfg.Config) error {
|
||||
return fmt.Errorf("Not implemented yet")
|
||||
}
|
34
vendor/github.com/mattermost/logr/const.go
generated
vendored
34
vendor/github.com/mattermost/logr/const.go
generated
vendored
@ -1,34 +0,0 @@
|
||||
package logr
|
||||
|
||||
import "time"
|
||||
|
||||
// Defaults.
|
||||
const (
|
||||
// DefaultMaxQueueSize is the default maximum queue size for Logr instances.
|
||||
DefaultMaxQueueSize = 1000
|
||||
|
||||
// DefaultMaxStackFrames is the default maximum max number of stack frames collected
|
||||
// when generating stack traces for logging.
|
||||
DefaultMaxStackFrames = 30
|
||||
|
||||
// MaxLevelID is the maximum value of a level ID. Some level cache implementations will
|
||||
// allocate a cache of this size. Cannot exceed uint.
|
||||
MaxLevelID = 256
|
||||
|
||||
// DefaultEnqueueTimeout is the default amount of time a log record can take to be queued.
|
||||
// This only applies to blocking enqueue which happen after `logr.OnQueueFull` is called
|
||||
// and returns false.
|
||||
DefaultEnqueueTimeout = time.Second * 30
|
||||
|
||||
// DefaultShutdownTimeout is the default amount of time `logr.Shutdown` can execute before
|
||||
// timing out.
|
||||
DefaultShutdownTimeout = time.Second * 30
|
||||
|
||||
// DefaultFlushTimeout is the default amount of time `logr.Flush` can execute before
|
||||
// timing out.
|
||||
DefaultFlushTimeout = time.Second * 30
|
||||
|
||||
// DefaultMaxPooledBuffer is the maximum size a pooled buffer can be.
|
||||
// Buffers that grow beyond this size are garbage collected.
|
||||
DefaultMaxPooledBuffer = 1024 * 1024
|
||||
)
|
26
vendor/github.com/mattermost/logr/filter.go
generated
vendored
26
vendor/github.com/mattermost/logr/filter.go
generated
vendored
@ -1,26 +0,0 @@
|
||||
package logr
|
||||
|
||||
// LevelID is the unique id of each level.
|
||||
type LevelID uint
|
||||
|
||||
// Level provides a mechanism to enable/disable specific log lines.
|
||||
type Level struct {
|
||||
ID LevelID
|
||||
Name string
|
||||
Stacktrace bool
|
||||
}
|
||||
|
||||
// String returns the name of this level.
|
||||
func (level Level) String() string {
|
||||
return level.Name
|
||||
}
|
||||
|
||||
// Filter allows targets to determine which Level(s) are active
|
||||
// for logging and which Level(s) require a stack trace to be output.
|
||||
// A default implementation using "panic, fatal..." is provided, and
|
||||
// a more flexible alternative implementation is also provided that
|
||||
// allows any number of custom levels.
|
||||
type Filter interface {
|
||||
IsEnabled(Level) bool
|
||||
IsStacktraceEnabled(Level) bool
|
||||
}
|
273
vendor/github.com/mattermost/logr/format/json.go
generated
vendored
273
vendor/github.com/mattermost/logr/format/json.go
generated
vendored
@ -1,273 +0,0 @@
|
||||
package format
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"runtime"
|
||||
"sort"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/francoispqt/gojay"
|
||||
"github.com/mattermost/logr"
|
||||
)
|
||||
|
||||
// ContextField is a name/value pair within the context fields.
|
||||
type ContextField struct {
|
||||
Key string
|
||||
Val interface{}
|
||||
}
|
||||
|
||||
// JSON formats log records as JSON.
|
||||
type JSON struct {
|
||||
// DisableTimestamp disables output of timestamp field.
|
||||
DisableTimestamp bool
|
||||
// DisableLevel disables output of level field.
|
||||
DisableLevel bool
|
||||
// DisableMsg disables output of msg field.
|
||||
DisableMsg bool
|
||||
// DisableContext disables output of all context fields.
|
||||
DisableContext bool
|
||||
// DisableStacktrace disables output of stack trace.
|
||||
DisableStacktrace bool
|
||||
|
||||
// TimestampFormat is an optional format for timestamps. If empty
|
||||
// then DefTimestampFormat is used.
|
||||
TimestampFormat string
|
||||
|
||||
// Deprecated: this has no effect.
|
||||
Indent string
|
||||
|
||||
// EscapeHTML determines if certain characters (e.g. `<`, `>`, `&`)
|
||||
// are escaped.
|
||||
EscapeHTML bool
|
||||
|
||||
// KeyTimestamp overrides the timestamp field key name.
|
||||
KeyTimestamp string
|
||||
|
||||
// KeyLevel overrides the level field key name.
|
||||
KeyLevel string
|
||||
|
||||
// KeyMsg overrides the msg field key name.
|
||||
KeyMsg string
|
||||
|
||||
// KeyContextFields when not empty will group all context fields
|
||||
// under this key.
|
||||
KeyContextFields string
|
||||
|
||||
// KeyStacktrace overrides the stacktrace field key name.
|
||||
KeyStacktrace string
|
||||
|
||||
// ContextSorter allows custom sorting for the context fields.
|
||||
ContextSorter func(fields logr.Fields) []ContextField
|
||||
|
||||
once sync.Once
|
||||
}
|
||||
|
||||
// Format converts a log record to bytes in JSON format.
|
||||
func (j *JSON) Format(rec *logr.LogRec, stacktrace bool, buf *bytes.Buffer) (*bytes.Buffer, error) {
|
||||
j.once.Do(j.applyDefaultKeyNames)
|
||||
|
||||
if buf == nil {
|
||||
buf = &bytes.Buffer{}
|
||||
}
|
||||
enc := gojay.BorrowEncoder(buf)
|
||||
defer func() {
|
||||
enc.Release()
|
||||
}()
|
||||
|
||||
sorter := j.ContextSorter
|
||||
if sorter == nil {
|
||||
sorter = j.defaultContextSorter
|
||||
}
|
||||
|
||||
jlr := JSONLogRec{
|
||||
LogRec: rec,
|
||||
JSON: j,
|
||||
stacktrace: stacktrace,
|
||||
sorter: sorter,
|
||||
}
|
||||
|
||||
err := enc.EncodeObject(jlr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
buf.WriteByte('\n')
|
||||
return buf, nil
|
||||
}
|
||||
|
||||
func (j *JSON) applyDefaultKeyNames() {
|
||||
if j.KeyTimestamp == "" {
|
||||
j.KeyTimestamp = "timestamp"
|
||||
}
|
||||
if j.KeyLevel == "" {
|
||||
j.KeyLevel = "level"
|
||||
}
|
||||
if j.KeyMsg == "" {
|
||||
j.KeyMsg = "msg"
|
||||
}
|
||||
if j.KeyStacktrace == "" {
|
||||
j.KeyStacktrace = "stacktrace"
|
||||
}
|
||||
}
|
||||
|
||||
// defaultContextSorter sorts the context fields alphabetically by key.
|
||||
func (j *JSON) defaultContextSorter(fields logr.Fields) []ContextField {
|
||||
keys := make([]string, 0, len(fields))
|
||||
for k := range fields {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
|
||||
cf := make([]ContextField, 0, len(keys))
|
||||
for _, k := range keys {
|
||||
cf = append(cf, ContextField{Key: k, Val: fields[k]})
|
||||
}
|
||||
return cf
|
||||
}
|
||||
|
||||
// JSONLogRec decorates a LogRec adding JSON encoding.
|
||||
type JSONLogRec struct {
|
||||
*logr.LogRec
|
||||
*JSON
|
||||
stacktrace bool
|
||||
sorter func(fields logr.Fields) []ContextField
|
||||
}
|
||||
|
||||
// MarshalJSONObject encodes the LogRec as JSON.
|
||||
func (rec JSONLogRec) MarshalJSONObject(enc *gojay.Encoder) {
|
||||
if !rec.DisableTimestamp {
|
||||
timestampFmt := rec.TimestampFormat
|
||||
if timestampFmt == "" {
|
||||
timestampFmt = logr.DefTimestampFormat
|
||||
}
|
||||
time := rec.Time()
|
||||
enc.AddTimeKey(rec.KeyTimestamp, &time, timestampFmt)
|
||||
}
|
||||
if !rec.DisableLevel {
|
||||
enc.AddStringKey(rec.KeyLevel, rec.Level().Name)
|
||||
}
|
||||
if !rec.DisableMsg {
|
||||
enc.AddStringKey(rec.KeyMsg, rec.Msg())
|
||||
}
|
||||
if !rec.DisableContext {
|
||||
ctxFields := rec.sorter(rec.Fields())
|
||||
if rec.KeyContextFields != "" {
|
||||
enc.AddObjectKey(rec.KeyContextFields, jsonFields(ctxFields))
|
||||
} else {
|
||||
if len(ctxFields) > 0 {
|
||||
for _, cf := range ctxFields {
|
||||
key := rec.prefixCollision(cf.Key)
|
||||
encodeField(enc, key, cf.Val)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if rec.stacktrace && !rec.DisableStacktrace {
|
||||
frames := rec.StackFrames()
|
||||
if len(frames) > 0 {
|
||||
enc.AddArrayKey(rec.KeyStacktrace, stackFrames(frames))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// IsNil returns true if the LogRec pointer is nil.
|
||||
func (rec JSONLogRec) IsNil() bool {
|
||||
return rec.LogRec == nil
|
||||
}
|
||||
|
||||
func (rec JSONLogRec) prefixCollision(key string) string {
|
||||
switch key {
|
||||
case rec.KeyTimestamp, rec.KeyLevel, rec.KeyMsg, rec.KeyStacktrace:
|
||||
return rec.prefixCollision("_" + key)
|
||||
}
|
||||
return key
|
||||
}
|
||||
|
||||
type stackFrames []runtime.Frame
|
||||
|
||||
// MarshalJSONArray encodes stackFrames slice as JSON.
|
||||
func (s stackFrames) MarshalJSONArray(enc *gojay.Encoder) {
|
||||
for _, frame := range s {
|
||||
enc.AddObject(stackFrame(frame))
|
||||
}
|
||||
}
|
||||
|
||||
// IsNil returns true if stackFrames is empty slice.
|
||||
func (s stackFrames) IsNil() bool {
|
||||
return len(s) == 0
|
||||
}
|
||||
|
||||
type stackFrame runtime.Frame
|
||||
|
||||
// MarshalJSONArray encodes stackFrame as JSON.
|
||||
func (f stackFrame) MarshalJSONObject(enc *gojay.Encoder) {
|
||||
enc.AddStringKey("Function", f.Function)
|
||||
enc.AddStringKey("File", f.File)
|
||||
enc.AddIntKey("Line", f.Line)
|
||||
}
|
||||
|
||||
func (f stackFrame) IsNil() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
type jsonFields []ContextField
|
||||
|
||||
// MarshalJSONObject encodes Fields map to JSON.
|
||||
func (f jsonFields) MarshalJSONObject(enc *gojay.Encoder) {
|
||||
for _, ctxField := range f {
|
||||
encodeField(enc, ctxField.Key, ctxField.Val)
|
||||
}
|
||||
}
|
||||
|
||||
// IsNil returns true if map is nil.
|
||||
func (f jsonFields) IsNil() bool {
|
||||
return f == nil
|
||||
}
|
||||
|
||||
func encodeField(enc *gojay.Encoder, key string, val interface{}) {
|
||||
switch vt := val.(type) {
|
||||
case gojay.MarshalerJSONObject:
|
||||
enc.AddObjectKey(key, vt)
|
||||
case gojay.MarshalerJSONArray:
|
||||
enc.AddArrayKey(key, vt)
|
||||
case string:
|
||||
enc.AddStringKey(key, vt)
|
||||
case error:
|
||||
enc.AddStringKey(key, vt.Error())
|
||||
case bool:
|
||||
enc.AddBoolKey(key, vt)
|
||||
case int:
|
||||
enc.AddIntKey(key, vt)
|
||||
case int64:
|
||||
enc.AddInt64Key(key, vt)
|
||||
case int32:
|
||||
enc.AddIntKey(key, int(vt))
|
||||
case int16:
|
||||
enc.AddIntKey(key, int(vt))
|
||||
case int8:
|
||||
enc.AddIntKey(key, int(vt))
|
||||
case uint64:
|
||||
enc.AddIntKey(key, int(vt))
|
||||
case uint32:
|
||||
enc.AddIntKey(key, int(vt))
|
||||
case uint16:
|
||||
enc.AddIntKey(key, int(vt))
|
||||
case uint8:
|
||||
enc.AddIntKey(key, int(vt))
|
||||
case float64:
|
||||
enc.AddFloatKey(key, vt)
|
||||
case float32:
|
||||
enc.AddFloat32Key(key, vt)
|
||||
case *gojay.EmbeddedJSON:
|
||||
enc.AddEmbeddedJSONKey(key, vt)
|
||||
case time.Time:
|
||||
enc.AddTimeKey(key, &vt, logr.DefTimestampFormat)
|
||||
case *time.Time:
|
||||
enc.AddTimeKey(key, vt, logr.DefTimestampFormat)
|
||||
default:
|
||||
s := fmt.Sprintf("%v", vt)
|
||||
enc.AddStringKey(key, s)
|
||||
}
|
||||
}
|
75
vendor/github.com/mattermost/logr/format/plain.go
generated
vendored
75
vendor/github.com/mattermost/logr/format/plain.go
generated
vendored
@ -1,75 +0,0 @@
|
||||
package format
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
|
||||
"github.com/mattermost/logr"
|
||||
)
|
||||
|
||||
// Plain is the simplest formatter, outputting only text with
|
||||
// no colors.
|
||||
type Plain struct {
|
||||
// DisableTimestamp disables output of timestamp field.
|
||||
DisableTimestamp bool
|
||||
// DisableLevel disables output of level field.
|
||||
DisableLevel bool
|
||||
// DisableMsg disables output of msg field.
|
||||
DisableMsg bool
|
||||
// DisableContext disables output of all context fields.
|
||||
DisableContext bool
|
||||
// DisableStacktrace disables output of stack trace.
|
||||
DisableStacktrace bool
|
||||
|
||||
// Delim is an optional delimiter output between each log field.
|
||||
// Defaults to a single space.
|
||||
Delim string
|
||||
|
||||
// TimestampFormat is an optional format for timestamps. If empty
|
||||
// then DefTimestampFormat is used.
|
||||
TimestampFormat string
|
||||
}
|
||||
|
||||
// Format converts a log record to bytes.
|
||||
func (p *Plain) Format(rec *logr.LogRec, stacktrace bool, buf *bytes.Buffer) (*bytes.Buffer, error) {
|
||||
delim := p.Delim
|
||||
if delim == "" {
|
||||
delim = " "
|
||||
}
|
||||
if buf == nil {
|
||||
buf = &bytes.Buffer{}
|
||||
}
|
||||
|
||||
timestampFmt := p.TimestampFormat
|
||||
if timestampFmt == "" {
|
||||
timestampFmt = logr.DefTimestampFormat
|
||||
}
|
||||
|
||||
if !p.DisableTimestamp {
|
||||
var arr [128]byte
|
||||
tbuf := rec.Time().AppendFormat(arr[:0], timestampFmt)
|
||||
buf.Write(tbuf)
|
||||
buf.WriteString(delim)
|
||||
}
|
||||
if !p.DisableLevel {
|
||||
fmt.Fprintf(buf, "%v%s", rec.Level().Name, delim)
|
||||
}
|
||||
if !p.DisableMsg {
|
||||
fmt.Fprint(buf, rec.Msg(), delim)
|
||||
}
|
||||
if !p.DisableContext {
|
||||
ctx := rec.Fields()
|
||||
if len(ctx) > 0 {
|
||||
logr.WriteFields(buf, ctx, " ")
|
||||
}
|
||||
}
|
||||
if stacktrace && !p.DisableStacktrace {
|
||||
frames := rec.StackFrames()
|
||||
if len(frames) > 0 {
|
||||
buf.WriteString("\n")
|
||||
logr.WriteStacktrace(buf, rec.StackFrames())
|
||||
}
|
||||
}
|
||||
buf.WriteString("\n")
|
||||
return buf, nil
|
||||
}
|
119
vendor/github.com/mattermost/logr/formatter.go
generated
vendored
119
vendor/github.com/mattermost/logr/formatter.go
generated
vendored
@ -1,119 +0,0 @@
|
||||
package logr
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"runtime"
|
||||
"sort"
|
||||
)
|
||||
|
||||
// Formatter turns a LogRec into a formatted string.
|
||||
type Formatter interface {
|
||||
// Format converts a log record to bytes. If buf is not nil then it will be
|
||||
// be filled with the formatted results, otherwise a new buffer will be allocated.
|
||||
Format(rec *LogRec, stacktrace bool, buf *bytes.Buffer) (*bytes.Buffer, error)
|
||||
}
|
||||
|
||||
const (
|
||||
// DefTimestampFormat is the default time stamp format used by
|
||||
// Plain formatter and others.
|
||||
DefTimestampFormat = "2006-01-02 15:04:05.000 Z07:00"
|
||||
)
|
||||
|
||||
// DefaultFormatter is the default formatter, outputting only text with
|
||||
// no colors and a space delimiter. Use `format.Plain` instead.
|
||||
type DefaultFormatter struct {
|
||||
}
|
||||
|
||||
// Format converts a log record to bytes.
|
||||
func (p *DefaultFormatter) Format(rec *LogRec, stacktrace bool, buf *bytes.Buffer) (*bytes.Buffer, error) {
|
||||
if buf == nil {
|
||||
buf = &bytes.Buffer{}
|
||||
}
|
||||
delim := " "
|
||||
timestampFmt := DefTimestampFormat
|
||||
|
||||
fmt.Fprintf(buf, "%s%s", rec.Time().Format(timestampFmt), delim)
|
||||
fmt.Fprintf(buf, "%v%s", rec.Level(), delim)
|
||||
fmt.Fprint(buf, rec.Msg(), delim)
|
||||
|
||||
ctx := rec.Fields()
|
||||
if len(ctx) > 0 {
|
||||
WriteFields(buf, ctx, " ")
|
||||
}
|
||||
|
||||
if stacktrace {
|
||||
frames := rec.StackFrames()
|
||||
if len(frames) > 0 {
|
||||
buf.WriteString("\n")
|
||||
WriteStacktrace(buf, rec.StackFrames())
|
||||
}
|
||||
}
|
||||
buf.WriteString("\n")
|
||||
|
||||
return buf, nil
|
||||
}
|
||||
|
||||
// WriteFields writes zero or more name value pairs to the io.Writer.
|
||||
// The pairs are sorted by key name and output in key=value format
|
||||
// with optional separator between fields.
|
||||
func WriteFields(w io.Writer, flds Fields, separator string) {
|
||||
keys := make([]string, 0, len(flds))
|
||||
for k := range flds {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
sep := ""
|
||||
for _, key := range keys {
|
||||
writeField(w, key, flds[key], sep)
|
||||
sep = separator
|
||||
}
|
||||
}
|
||||
|
||||
func writeField(w io.Writer, key string, val interface{}, sep string) {
|
||||
var template string
|
||||
switch v := val.(type) {
|
||||
case error:
|
||||
val := v.Error()
|
||||
if shouldQuote(val) {
|
||||
template = "%s%s=%q"
|
||||
} else {
|
||||
template = "%s%s=%s"
|
||||
}
|
||||
case string:
|
||||
if shouldQuote(v) {
|
||||
template = "%s%s=%q"
|
||||
} else {
|
||||
template = "%s%s=%s"
|
||||
}
|
||||
default:
|
||||
template = "%s%s=%v"
|
||||
}
|
||||
fmt.Fprintf(w, template, sep, key, val)
|
||||
}
|
||||
|
||||
// shouldQuote returns true if val contains any characters that might be unsafe
|
||||
// when injecting log output into an aggregator, viewer or report.
|
||||
func shouldQuote(val string) bool {
|
||||
for _, c := range val {
|
||||
if !((c >= '0' && c <= '9') ||
|
||||
(c >= 'a' && c <= 'z') ||
|
||||
(c >= 'A' && c <= 'Z')) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// WriteStacktrace formats and outputs a stack trace to an io.Writer.
|
||||
func WriteStacktrace(w io.Writer, frames []runtime.Frame) {
|
||||
for _, frame := range frames {
|
||||
if frame.Function != "" {
|
||||
fmt.Fprintf(w, " %s\n", frame.Function)
|
||||
}
|
||||
if frame.File != "" {
|
||||
fmt.Fprintf(w, " %s:%d\n", frame.File, frame.Line)
|
||||
}
|
||||
}
|
||||
}
|
98
vendor/github.com/mattermost/logr/levelcache.go
generated
vendored
98
vendor/github.com/mattermost/logr/levelcache.go
generated
vendored
@ -1,98 +0,0 @@
|
||||
package logr
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// LevelStatus represents whether a level is enabled and
|
||||
// requires a stack trace.
|
||||
type LevelStatus struct {
|
||||
Enabled bool
|
||||
Stacktrace bool
|
||||
empty bool
|
||||
}
|
||||
|
||||
type levelCache interface {
|
||||
setup()
|
||||
get(id LevelID) (LevelStatus, bool)
|
||||
put(id LevelID, status LevelStatus) error
|
||||
clear()
|
||||
}
|
||||
|
||||
// syncMapLevelCache uses sync.Map which may better handle large concurrency
|
||||
// scenarios.
|
||||
type syncMapLevelCache struct {
|
||||
m sync.Map
|
||||
}
|
||||
|
||||
func (c *syncMapLevelCache) setup() {
|
||||
c.clear()
|
||||
}
|
||||
|
||||
func (c *syncMapLevelCache) get(id LevelID) (LevelStatus, bool) {
|
||||
if id > MaxLevelID {
|
||||
return LevelStatus{}, false
|
||||
}
|
||||
s, _ := c.m.Load(id)
|
||||
status := s.(LevelStatus)
|
||||
return status, !status.empty
|
||||
}
|
||||
|
||||
func (c *syncMapLevelCache) put(id LevelID, status LevelStatus) error {
|
||||
if id > MaxLevelID {
|
||||
return fmt.Errorf("level id cannot exceed MaxLevelID (%d)", MaxLevelID)
|
||||
}
|
||||
c.m.Store(id, status)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *syncMapLevelCache) clear() {
|
||||
var i LevelID
|
||||
for i = 0; i < MaxLevelID; i++ {
|
||||
c.m.Store(i, LevelStatus{empty: true})
|
||||
}
|
||||
}
|
||||
|
||||
// arrayLevelCache using array and a mutex.
|
||||
type arrayLevelCache struct {
|
||||
arr [MaxLevelID + 1]LevelStatus
|
||||
mux sync.RWMutex
|
||||
}
|
||||
|
||||
func (c *arrayLevelCache) setup() {
|
||||
c.clear()
|
||||
}
|
||||
|
||||
//var dummy = LevelStatus{}
|
||||
|
||||
func (c *arrayLevelCache) get(id LevelID) (LevelStatus, bool) {
|
||||
if id > MaxLevelID {
|
||||
return LevelStatus{}, false
|
||||
}
|
||||
c.mux.RLock()
|
||||
status := c.arr[id]
|
||||
ok := !status.empty
|
||||
c.mux.RUnlock()
|
||||
return status, ok
|
||||
}
|
||||
|
||||
func (c *arrayLevelCache) put(id LevelID, status LevelStatus) error {
|
||||
if id > MaxLevelID {
|
||||
return fmt.Errorf("level id cannot exceed MaxLevelID (%d)", MaxLevelID)
|
||||
}
|
||||
c.mux.Lock()
|
||||
defer c.mux.Unlock()
|
||||
|
||||
c.arr[id] = status
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *arrayLevelCache) clear() {
|
||||
c.mux.Lock()
|
||||
defer c.mux.Unlock()
|
||||
|
||||
for i := range c.arr {
|
||||
c.arr[i] = LevelStatus{empty: true}
|
||||
}
|
||||
}
|
45
vendor/github.com/mattermost/logr/levelcustom.go
generated
vendored
45
vendor/github.com/mattermost/logr/levelcustom.go
generated
vendored
@ -1,45 +0,0 @@
|
||||
package logr
|
||||
|
||||
import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
// CustomFilter allows targets to enable logging via a list of levels.
|
||||
type CustomFilter struct {
|
||||
mux sync.RWMutex
|
||||
levels map[LevelID]Level
|
||||
}
|
||||
|
||||
// IsEnabled returns true if the specified Level exists in this list.
|
||||
func (st *CustomFilter) IsEnabled(level Level) bool {
|
||||
st.mux.RLock()
|
||||
defer st.mux.RUnlock()
|
||||
_, ok := st.levels[level.ID]
|
||||
return ok
|
||||
}
|
||||
|
||||
// IsStacktraceEnabled returns true if the specified Level requires a stack trace.
|
||||
func (st *CustomFilter) IsStacktraceEnabled(level Level) bool {
|
||||
st.mux.RLock()
|
||||
defer st.mux.RUnlock()
|
||||
lvl, ok := st.levels[level.ID]
|
||||
if ok {
|
||||
return lvl.Stacktrace
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Add adds one or more levels to the list. Adding a level enables logging for
|
||||
// that level on any targets using this CustomFilter.
|
||||
func (st *CustomFilter) Add(levels ...Level) {
|
||||
st.mux.Lock()
|
||||
defer st.mux.Unlock()
|
||||
|
||||
if st.levels == nil {
|
||||
st.levels = make(map[LevelID]Level)
|
||||
}
|
||||
|
||||
for _, s := range levels {
|
||||
st.levels[s.ID] = s
|
||||
}
|
||||
}
|
37
vendor/github.com/mattermost/logr/levelstd.go
generated
vendored
37
vendor/github.com/mattermost/logr/levelstd.go
generated
vendored
@ -1,37 +0,0 @@
|
||||
package logr
|
||||
|
||||
// StdFilter allows targets to filter via classic log levels where any level
|
||||
// beyond a certain verbosity/severity is enabled.
|
||||
type StdFilter struct {
|
||||
Lvl Level
|
||||
Stacktrace Level
|
||||
}
|
||||
|
||||
// IsEnabled returns true if the specified Level is at or above this verbosity. Also
|
||||
// determines if a stack trace is required.
|
||||
func (lt StdFilter) IsEnabled(level Level) bool {
|
||||
return level.ID <= lt.Lvl.ID
|
||||
}
|
||||
|
||||
// IsStacktraceEnabled returns true if the specified Level requires a stack trace.
|
||||
func (lt StdFilter) IsStacktraceEnabled(level Level) bool {
|
||||
return level.ID <= lt.Stacktrace.ID
|
||||
}
|
||||
|
||||
var (
|
||||
// Panic is the highest level of severity. Logs the message and then panics.
|
||||
Panic = Level{ID: 0, Name: "panic"}
|
||||
// Fatal designates a catastrophic error. Logs the message and then calls
|
||||
// `logr.Exit(1)`.
|
||||
Fatal = Level{ID: 1, Name: "fatal"}
|
||||
// Error designates a serious but possibly recoverable error.
|
||||
Error = Level{ID: 2, Name: "error"}
|
||||
// Warn designates non-critical error.
|
||||
Warn = Level{ID: 3, Name: "warn"}
|
||||
// Info designates information regarding application events.
|
||||
Info = Level{ID: 4, Name: "info"}
|
||||
// Debug designates verbose information typically used for debugging.
|
||||
Debug = Level{ID: 5, Name: "debug"}
|
||||
// Trace designates the highest verbosity of log output.
|
||||
Trace = Level{ID: 6, Name: "trace"}
|
||||
)
|
218
vendor/github.com/mattermost/logr/logger.go
generated
vendored
218
vendor/github.com/mattermost/logr/logger.go
generated
vendored
@ -1,218 +0,0 @@
|
||||
package logr
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// Fields type, used to pass to `WithFields`.
|
||||
type Fields map[string]interface{}
|
||||
|
||||
// Logger provides context for logging via fields.
|
||||
type Logger struct {
|
||||
logr *Logr
|
||||
fields Fields
|
||||
}
|
||||
|
||||
// Logr returns the `Logr` instance that created this `Logger`.
|
||||
func (logger Logger) Logr() *Logr {
|
||||
return logger.logr
|
||||
}
|
||||
|
||||
// WithField creates a new `Logger` with any existing fields
|
||||
// plus the new one.
|
||||
func (logger Logger) WithField(key string, value interface{}) Logger {
|
||||
return logger.WithFields(Fields{key: value})
|
||||
}
|
||||
|
||||
// WithFields creates a new `Logger` with any existing fields
|
||||
// plus the new ones.
|
||||
func (logger Logger) WithFields(fields Fields) Logger {
|
||||
l := Logger{logr: logger.logr}
|
||||
// if parent has no fields then avoid creating a new map.
|
||||
oldLen := len(logger.fields)
|
||||
if oldLen == 0 {
|
||||
l.fields = fields
|
||||
return l
|
||||
}
|
||||
|
||||
l.fields = make(Fields, len(fields)+oldLen)
|
||||
for k, v := range logger.fields {
|
||||
l.fields[k] = v
|
||||
}
|
||||
for k, v := range fields {
|
||||
l.fields[k] = v
|
||||
}
|
||||
return l
|
||||
}
|
||||
|
||||
// Log checks that the level matches one or more targets, and
|
||||
// if so, generates a log record that is added to the Logr queue.
|
||||
// Arguments are handled in the manner of fmt.Print.
|
||||
func (logger Logger) Log(lvl Level, args ...interface{}) {
|
||||
status := logger.logr.IsLevelEnabled(lvl)
|
||||
if status.Enabled {
|
||||
rec := NewLogRec(lvl, logger, "", args, status.Stacktrace)
|
||||
logger.logr.enqueue(rec)
|
||||
}
|
||||
}
|
||||
|
||||
// Trace is a convenience method equivalent to `Log(TraceLevel, args...)`.
|
||||
func (logger Logger) Trace(args ...interface{}) {
|
||||
logger.Log(Trace, args...)
|
||||
}
|
||||
|
||||
// Debug is a convenience method equivalent to `Log(DebugLevel, args...)`.
|
||||
func (logger Logger) Debug(args ...interface{}) {
|
||||
logger.Log(Debug, args...)
|
||||
}
|
||||
|
||||
// Print ensures compatibility with std lib logger.
|
||||
func (logger Logger) Print(args ...interface{}) {
|
||||
logger.Info(args...)
|
||||
}
|
||||
|
||||
// Info is a convenience method equivalent to `Log(InfoLevel, args...)`.
|
||||
func (logger Logger) Info(args ...interface{}) {
|
||||
logger.Log(Info, args...)
|
||||
}
|
||||
|
||||
// Warn is a convenience method equivalent to `Log(WarnLevel, args...)`.
|
||||
func (logger Logger) Warn(args ...interface{}) {
|
||||
logger.Log(Warn, args...)
|
||||
}
|
||||
|
||||
// Error is a convenience method equivalent to `Log(ErrorLevel, args...)`.
|
||||
func (logger Logger) Error(args ...interface{}) {
|
||||
logger.Log(Error, args...)
|
||||
}
|
||||
|
||||
// Fatal is a convenience method equivalent to `Log(FatalLevel, args...)`
|
||||
// followed by a call to os.Exit(1).
|
||||
func (logger Logger) Fatal(args ...interface{}) {
|
||||
logger.Log(Fatal, args...)
|
||||
logger.logr.exit(1)
|
||||
}
|
||||
|
||||
// Panic is a convenience method equivalent to `Log(PanicLevel, args...)`
|
||||
// followed by a call to panic().
|
||||
func (logger Logger) Panic(args ...interface{}) {
|
||||
logger.Log(Panic, args...)
|
||||
panic(fmt.Sprint(args...))
|
||||
}
|
||||
|
||||
//
|
||||
// Printf style
|
||||
//
|
||||
|
||||
// Logf checks that the level matches one or more targets, and
|
||||
// if so, generates a log record that is added to the main
|
||||
// queue (channel). Arguments are handled in the manner of fmt.Printf.
|
||||
func (logger Logger) Logf(lvl Level, format string, args ...interface{}) {
|
||||
status := logger.logr.IsLevelEnabled(lvl)
|
||||
if status.Enabled {
|
||||
rec := NewLogRec(lvl, logger, format, args, status.Stacktrace)
|
||||
logger.logr.enqueue(rec)
|
||||
}
|
||||
}
|
||||
|
||||
// Tracef is a convenience method equivalent to `Logf(TraceLevel, args...)`.
|
||||
func (logger Logger) Tracef(format string, args ...interface{}) {
|
||||
logger.Logf(Trace, format, args...)
|
||||
}
|
||||
|
||||
// Debugf is a convenience method equivalent to `Logf(DebugLevel, args...)`.
|
||||
func (logger Logger) Debugf(format string, args ...interface{}) {
|
||||
logger.Logf(Debug, format, args...)
|
||||
}
|
||||
|
||||
// Infof is a convenience method equivalent to `Logf(InfoLevel, args...)`.
|
||||
func (logger Logger) Infof(format string, args ...interface{}) {
|
||||
logger.Logf(Info, format, args...)
|
||||
}
|
||||
|
||||
// Printf ensures compatibility with std lib logger.
|
||||
func (logger Logger) Printf(format string, args ...interface{}) {
|
||||
logger.Infof(format, args...)
|
||||
}
|
||||
|
||||
// Warnf is a convenience method equivalent to `Logf(WarnLevel, args...)`.
|
||||
func (logger Logger) Warnf(format string, args ...interface{}) {
|
||||
logger.Logf(Warn, format, args...)
|
||||
}
|
||||
|
||||
// Errorf is a convenience method equivalent to `Logf(ErrorLevel, args...)`.
|
||||
func (logger Logger) Errorf(format string, args ...interface{}) {
|
||||
logger.Logf(Error, format, args...)
|
||||
}
|
||||
|
||||
// Fatalf is a convenience method equivalent to `Logf(FatalLevel, args...)`
|
||||
// followed by a call to os.Exit(1).
|
||||
func (logger Logger) Fatalf(format string, args ...interface{}) {
|
||||
logger.Logf(Fatal, format, args...)
|
||||
logger.logr.exit(1)
|
||||
}
|
||||
|
||||
// Panicf is a convenience method equivalent to `Logf(PanicLevel, args...)`
|
||||
// followed by a call to panic().
|
||||
func (logger Logger) Panicf(format string, args ...interface{}) {
|
||||
logger.Logf(Panic, format, args...)
|
||||
}
|
||||
|
||||
//
|
||||
// Println style
|
||||
//
|
||||
|
||||
// Logln checks that the level matches one or more targets, and
|
||||
// if so, generates a log record that is added to the main
|
||||
// queue (channel). Arguments are handled in the manner of fmt.Println.
|
||||
func (logger Logger) Logln(lvl Level, args ...interface{}) {
|
||||
status := logger.logr.IsLevelEnabled(lvl)
|
||||
if status.Enabled {
|
||||
rec := NewLogRec(lvl, logger, "", args, status.Stacktrace)
|
||||
rec.newline = true
|
||||
logger.logr.enqueue(rec)
|
||||
}
|
||||
}
|
||||
|
||||
// Traceln is a convenience method equivalent to `Logln(TraceLevel, args...)`.
|
||||
func (logger Logger) Traceln(args ...interface{}) {
|
||||
logger.Logln(Trace, args...)
|
||||
}
|
||||
|
||||
// Debugln is a convenience method equivalent to `Logln(DebugLevel, args...)`.
|
||||
func (logger Logger) Debugln(args ...interface{}) {
|
||||
logger.Logln(Debug, args...)
|
||||
}
|
||||
|
||||
// Infoln is a convenience method equivalent to `Logln(InfoLevel, args...)`.
|
||||
func (logger Logger) Infoln(args ...interface{}) {
|
||||
logger.Logln(Info, args...)
|
||||
}
|
||||
|
||||
// Println ensures compatibility with std lib logger.
|
||||
func (logger Logger) Println(args ...interface{}) {
|
||||
logger.Infoln(args...)
|
||||
}
|
||||
|
||||
// Warnln is a convenience method equivalent to `Logln(WarnLevel, args...)`.
|
||||
func (logger Logger) Warnln(args ...interface{}) {
|
||||
logger.Logln(Warn, args...)
|
||||
}
|
||||
|
||||
// Errorln is a convenience method equivalent to `Logln(ErrorLevel, args...)`.
|
||||
func (logger Logger) Errorln(args ...interface{}) {
|
||||
logger.Logln(Error, args...)
|
||||
}
|
||||
|
||||
// Fatalln is a convenience method equivalent to `Logln(FatalLevel, args...)`
|
||||
// followed by a call to os.Exit(1).
|
||||
func (logger Logger) Fatalln(args ...interface{}) {
|
||||
logger.Logln(Fatal, args...)
|
||||
logger.logr.exit(1)
|
||||
}
|
||||
|
||||
// Panicln is a convenience method equivalent to `Logln(PanicLevel, args...)`
|
||||
// followed by a call to panic().
|
||||
func (logger Logger) Panicln(args ...interface{}) {
|
||||
logger.Logln(Panic, args...)
|
||||
}
|
664
vendor/github.com/mattermost/logr/logr.go
generated
vendored
664
vendor/github.com/mattermost/logr/logr.go
generated
vendored
@ -1,664 +0,0 @@
|
||||
package logr
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/wiggin77/cfg"
|
||||
"github.com/wiggin77/merror"
|
||||
)
|
||||
|
||||
// Logr maintains a list of log targets and accepts incoming
|
||||
// log records.
|
||||
type Logr struct {
|
||||
tmux sync.RWMutex // target mutex
|
||||
targets []Target
|
||||
|
||||
mux sync.RWMutex
|
||||
maxQueueSizeActual int
|
||||
in chan *LogRec
|
||||
done chan struct{}
|
||||
once sync.Once
|
||||
shutdown bool
|
||||
lvlCache levelCache
|
||||
|
||||
metricsInitOnce sync.Once
|
||||
metricsCloseOnce sync.Once
|
||||
metricsDone chan struct{}
|
||||
metrics MetricsCollector
|
||||
queueSizeGauge Gauge
|
||||
loggedCounter Counter
|
||||
errorCounter Counter
|
||||
|
||||
bufferPool sync.Pool
|
||||
|
||||
// MaxQueueSize is the maximum number of log records that can be queued.
|
||||
// If exceeded, `OnQueueFull` is called which determines if the log
|
||||
// record will be dropped or block until add is successful.
|
||||
// If this is modified, it must be done before `Configure` or
|
||||
// `AddTarget`. Defaults to DefaultMaxQueueSize.
|
||||
MaxQueueSize int
|
||||
|
||||
// OnLoggerError, when not nil, is called any time an internal
|
||||
// logging error occurs. For example, this can happen when a
|
||||
// target cannot connect to its data sink.
|
||||
OnLoggerError func(error)
|
||||
|
||||
// OnQueueFull, when not nil, is called on an attempt to add
|
||||
// a log record to a full Logr queue.
|
||||
// `MaxQueueSize` can be used to modify the maximum queue size.
|
||||
// This function should return quickly, with a bool indicating whether
|
||||
// the log record should be dropped (true) or block until the log record
|
||||
// is successfully added (false). If nil then blocking (false) is assumed.
|
||||
OnQueueFull func(rec *LogRec, maxQueueSize int) bool
|
||||
|
||||
// OnTargetQueueFull, when not nil, is called on an attempt to add
|
||||
// a log record to a full target queue provided the target supports reporting
|
||||
// this condition.
|
||||
// This function should return quickly, with a bool indicating whether
|
||||
// the log record should be dropped (true) or block until the log record
|
||||
// is successfully added (false). If nil then blocking (false) is assumed.
|
||||
OnTargetQueueFull func(target Target, rec *LogRec, maxQueueSize int) bool
|
||||
|
||||
// OnExit, when not nil, is called when a FatalXXX style log API is called.
|
||||
// When nil, then the default behavior is to cleanly shut down this Logr and
|
||||
// call `os.Exit(code)`.
|
||||
OnExit func(code int)
|
||||
|
||||
// OnPanic, when not nil, is called when a PanicXXX style log API is called.
|
||||
// When nil, then the default behavior is to cleanly shut down this Logr and
|
||||
// call `panic(err)`.
|
||||
OnPanic func(err interface{})
|
||||
|
||||
// EnqueueTimeout is the amount of time a log record can take to be queued.
|
||||
// This only applies to blocking enqueue which happen after `logr.OnQueueFull`
|
||||
// is called and returns false.
|
||||
EnqueueTimeout time.Duration
|
||||
|
||||
// ShutdownTimeout is the amount of time `logr.Shutdown` can execute before
|
||||
// timing out.
|
||||
ShutdownTimeout time.Duration
|
||||
|
||||
// FlushTimeout is the amount of time `logr.Flush` can execute before
|
||||
// timing out.
|
||||
FlushTimeout time.Duration
|
||||
|
||||
// UseSyncMapLevelCache can be set to true before the first target is added
|
||||
// when high concurrency (e.g. >32 cores) is expected. This may improve
|
||||
// performance with large numbers of cores - benchmark for your use case.
|
||||
UseSyncMapLevelCache bool
|
||||
|
||||
// MaxPooledFormatBuffer determines the maximum size of a buffer that can be
|
||||
// pooled. To reduce allocations, the buffers needed during formatting (etc)
|
||||
// are pooled. A very large log item will grow a buffer that could stay in
|
||||
// memory indefinitely. This settings lets you control how big a pooled buffer
|
||||
// can be - anything larger will be garbage collected after use.
|
||||
// Defaults to 1MB.
|
||||
MaxPooledBuffer int
|
||||
|
||||
// DisableBufferPool when true disables the buffer pool. See MaxPooledBuffer.
|
||||
DisableBufferPool bool
|
||||
|
||||
// MetricsUpdateFreqMillis determines how often polled metrics are updated
|
||||
// when metrics are enabled.
|
||||
MetricsUpdateFreqMillis int64
|
||||
}
|
||||
|
||||
// Configure adds/removes targets via the supplied `Config`.
|
||||
func (logr *Logr) Configure(config *cfg.Config) error {
|
||||
// TODO
|
||||
return fmt.Errorf("not implemented yet")
|
||||
}
|
||||
|
||||
func (logr *Logr) ensureInit() {
|
||||
logr.once.Do(func() {
|
||||
defer func() {
|
||||
go logr.start()
|
||||
}()
|
||||
|
||||
logr.mux.Lock()
|
||||
defer logr.mux.Unlock()
|
||||
|
||||
logr.maxQueueSizeActual = logr.MaxQueueSize
|
||||
if logr.maxQueueSizeActual == 0 {
|
||||
logr.maxQueueSizeActual = DefaultMaxQueueSize
|
||||
}
|
||||
|
||||
if logr.maxQueueSizeActual < 0 {
|
||||
logr.maxQueueSizeActual = 0
|
||||
}
|
||||
|
||||
logr.in = make(chan *LogRec, logr.maxQueueSizeActual)
|
||||
logr.done = make(chan struct{})
|
||||
|
||||
if logr.UseSyncMapLevelCache {
|
||||
logr.lvlCache = &syncMapLevelCache{}
|
||||
} else {
|
||||
logr.lvlCache = &arrayLevelCache{}
|
||||
}
|
||||
|
||||
if logr.MaxPooledBuffer == 0 {
|
||||
logr.MaxPooledBuffer = DefaultMaxPooledBuffer
|
||||
}
|
||||
logr.bufferPool = sync.Pool{
|
||||
New: func() interface{} {
|
||||
return new(bytes.Buffer)
|
||||
},
|
||||
}
|
||||
|
||||
logr.lvlCache.setup()
|
||||
})
|
||||
}
|
||||
|
||||
// AddTarget adds one or more targets to the logger which will receive
|
||||
// log records for outputting.
|
||||
func (logr *Logr) AddTarget(targets ...Target) error {
|
||||
if logr.IsShutdown() {
|
||||
return fmt.Errorf("AddTarget called after Logr shut down")
|
||||
}
|
||||
|
||||
logr.ensureInit()
|
||||
metrics := logr.getMetricsCollector()
|
||||
defer logr.ResetLevelCache() // call this after tmux is released
|
||||
|
||||
logr.tmux.Lock()
|
||||
defer logr.tmux.Unlock()
|
||||
|
||||
errs := merror.New()
|
||||
for _, t := range targets {
|
||||
if t == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
logr.targets = append(logr.targets, t)
|
||||
if metrics != nil {
|
||||
if tm, ok := t.(TargetWithMetrics); ok {
|
||||
if err := tm.EnableMetrics(metrics, logr.MetricsUpdateFreqMillis); err != nil {
|
||||
errs.Append(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return errs.ErrorOrNil()
|
||||
}
|
||||
|
||||
// NewLogger creates a Logger using defaults. A `Logger` is light-weight
|
||||
// enough to create on-demand, but typically one or more Loggers are
|
||||
// created and re-used.
|
||||
func (logr *Logr) NewLogger() Logger {
|
||||
logger := Logger{logr: logr}
|
||||
return logger
|
||||
}
|
||||
|
||||
var levelStatusDisabled = LevelStatus{}
|
||||
|
||||
// IsLevelEnabled returns true if at least one target has the specified
|
||||
// level enabled. The result is cached so that subsequent checks are fast.
|
||||
func (logr *Logr) IsLevelEnabled(lvl Level) LevelStatus {
|
||||
status, ok := logr.isLevelEnabledFromCache(lvl)
|
||||
if ok {
|
||||
return status
|
||||
}
|
||||
|
||||
// Check each target.
|
||||
logr.tmux.RLock()
|
||||
for _, t := range logr.targets {
|
||||
e, s := t.IsLevelEnabled(lvl)
|
||||
if e {
|
||||
status.Enabled = true
|
||||
if s {
|
||||
status.Stacktrace = true
|
||||
break // if both enabled then no sense checking more targets
|
||||
}
|
||||
}
|
||||
}
|
||||
logr.tmux.RUnlock()
|
||||
|
||||
// Cache and return the result.
|
||||
if err := logr.updateLevelCache(lvl.ID, status); err != nil {
|
||||
logr.ReportError(err)
|
||||
return LevelStatus{}
|
||||
}
|
||||
return status
|
||||
}
|
||||
|
||||
func (logr *Logr) isLevelEnabledFromCache(lvl Level) (LevelStatus, bool) {
|
||||
logr.mux.RLock()
|
||||
defer logr.mux.RUnlock()
|
||||
|
||||
// Don't accept new log records after shutdown.
|
||||
if logr.shutdown {
|
||||
return levelStatusDisabled, true
|
||||
}
|
||||
|
||||
// Check cache. lvlCache may still be nil if no targets added.
|
||||
if logr.lvlCache == nil {
|
||||
return levelStatusDisabled, true
|
||||
}
|
||||
status, ok := logr.lvlCache.get(lvl.ID)
|
||||
if ok {
|
||||
return status, true
|
||||
}
|
||||
return LevelStatus{}, false
|
||||
}
|
||||
|
||||
func (logr *Logr) updateLevelCache(id LevelID, status LevelStatus) error {
|
||||
logr.mux.RLock()
|
||||
defer logr.mux.RUnlock()
|
||||
if logr.lvlCache != nil {
|
||||
return logr.lvlCache.put(id, status)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// HasTargets returns true only if at least one target exists within the Logr.
|
||||
func (logr *Logr) HasTargets() bool {
|
||||
logr.tmux.RLock()
|
||||
defer logr.tmux.RUnlock()
|
||||
return len(logr.targets) > 0
|
||||
}
|
||||
|
||||
// TargetInfo provides name and type for a Target.
|
||||
type TargetInfo struct {
|
||||
Name string
|
||||
Type string
|
||||
}
|
||||
|
||||
// TargetInfos enumerates all the targets added to this Logr.
|
||||
// The resulting slice represents a snapshot at time of calling.
|
||||
func (logr *Logr) TargetInfos() []TargetInfo {
|
||||
logr.tmux.RLock()
|
||||
defer logr.tmux.RUnlock()
|
||||
|
||||
infos := make([]TargetInfo, 0)
|
||||
|
||||
for _, t := range logr.targets {
|
||||
inf := TargetInfo{
|
||||
Name: fmt.Sprintf("%v", t),
|
||||
Type: fmt.Sprintf("%T", t),
|
||||
}
|
||||
infos = append(infos, inf)
|
||||
}
|
||||
return infos
|
||||
}
|
||||
|
||||
// RemoveTargets safely removes one or more targets based on the filtering method.
|
||||
// f should return true to delete the target, false to keep it.
|
||||
// When removing a target, best effort is made to write any queued log records before
|
||||
// closing, with cxt determining how much time can be spent in total.
|
||||
// Note, keep the timeout short since this method blocks certain logging operations.
|
||||
func (logr *Logr) RemoveTargets(cxt context.Context, f func(ti TargetInfo) bool) error {
|
||||
var removed bool
|
||||
defer func() {
|
||||
if removed {
|
||||
// call this after tmux is released since
|
||||
// it will lock mux and we don't want to
|
||||
// introduce possible deadlock.
|
||||
logr.ResetLevelCache()
|
||||
}
|
||||
}()
|
||||
|
||||
errs := merror.New()
|
||||
|
||||
logr.tmux.Lock()
|
||||
defer logr.tmux.Unlock()
|
||||
|
||||
cp := make([]Target, 0)
|
||||
|
||||
for _, t := range logr.targets {
|
||||
inf := TargetInfo{
|
||||
Name: fmt.Sprintf("%v", t),
|
||||
Type: fmt.Sprintf("%T", t),
|
||||
}
|
||||
if f(inf) {
|
||||
if err := t.Shutdown(cxt); err != nil {
|
||||
errs.Append(err)
|
||||
}
|
||||
removed = true
|
||||
} else {
|
||||
cp = append(cp, t)
|
||||
}
|
||||
}
|
||||
logr.targets = cp
|
||||
return errs.ErrorOrNil()
|
||||
}
|
||||
|
||||
// ResetLevelCache resets the cached results of `IsLevelEnabled`. This is
|
||||
// called any time a Target is added or a target's level is changed.
|
||||
func (logr *Logr) ResetLevelCache() {
|
||||
// Write lock so that new cache entries cannot be stored while we
|
||||
// clear the cache.
|
||||
logr.mux.Lock()
|
||||
defer logr.mux.Unlock()
|
||||
logr.resetLevelCache()
|
||||
}
|
||||
|
||||
// resetLevelCache empties the level cache without locking.
|
||||
// mux.Lock must be held before calling this function.
|
||||
func (logr *Logr) resetLevelCache() {
|
||||
// lvlCache may still be nil if no targets added.
|
||||
if logr.lvlCache != nil {
|
||||
logr.lvlCache.clear()
|
||||
}
|
||||
}
|
||||
|
||||
// enqueue adds a log record to the logr queue. If the queue is full then
|
||||
// this function either blocks or the log record is dropped, depending on
|
||||
// the result of calling `OnQueueFull`.
|
||||
func (logr *Logr) enqueue(rec *LogRec) {
|
||||
if logr.in == nil {
|
||||
logr.ReportError(fmt.Errorf("AddTarget or Configure must be called before enqueue"))
|
||||
}
|
||||
|
||||
select {
|
||||
case logr.in <- rec:
|
||||
default:
|
||||
if logr.OnQueueFull != nil && logr.OnQueueFull(rec, logr.maxQueueSizeActual) {
|
||||
return // drop the record
|
||||
}
|
||||
select {
|
||||
case <-time.After(logr.enqueueTimeout()):
|
||||
logr.ReportError(fmt.Errorf("enqueue timed out for log rec [%v]", rec))
|
||||
case logr.in <- rec: // block until success or timeout
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// exit is called by one of the FatalXXX style APIS. If `logr.OnExit` is not nil
|
||||
// then that method is called, otherwise the default behavior is to shut down this
|
||||
// Logr cleanly then call `os.Exit(code)`.
|
||||
func (logr *Logr) exit(code int) {
|
||||
if logr.OnExit != nil {
|
||||
logr.OnExit(code)
|
||||
return
|
||||
}
|
||||
|
||||
if err := logr.Shutdown(); err != nil {
|
||||
logr.ReportError(err)
|
||||
}
|
||||
os.Exit(code)
|
||||
}
|
||||
|
||||
// panic is called by one of the PanicXXX style APIS. If `logr.OnPanic` is not nil
|
||||
// then that method is called, otherwise the default behavior is to shut down this
|
||||
// Logr cleanly then call `panic(err)`.
|
||||
func (logr *Logr) panic(err interface{}) {
|
||||
if logr.OnPanic != nil {
|
||||
logr.OnPanic(err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := logr.Shutdown(); err != nil {
|
||||
logr.ReportError(err)
|
||||
}
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Flush blocks while flushing the logr queue and all target queues, by
|
||||
// writing existing log records to valid targets.
|
||||
// Any attempts to add new log records will block until flush is complete.
|
||||
// `logr.FlushTimeout` determines how long flush can execute before
|
||||
// timing out. Use `IsTimeoutError` to determine if the returned error is
|
||||
// due to a timeout.
|
||||
func (logr *Logr) Flush() error {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), logr.flushTimeout())
|
||||
defer cancel()
|
||||
return logr.FlushWithTimeout(ctx)
|
||||
}
|
||||
|
||||
// Flush blocks while flushing the logr queue and all target queues, by
|
||||
// writing existing log records to valid targets.
|
||||
// Any attempts to add new log records will block until flush is complete.
|
||||
// Use `IsTimeoutError` to determine if the returned error is
|
||||
// due to a timeout.
|
||||
func (logr *Logr) FlushWithTimeout(ctx context.Context) error {
|
||||
if !logr.HasTargets() {
|
||||
return nil
|
||||
}
|
||||
|
||||
if logr.IsShutdown() {
|
||||
return errors.New("Flush called on shut down Logr")
|
||||
}
|
||||
|
||||
rec := newFlushLogRec(logr.NewLogger())
|
||||
logr.enqueue(rec)
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return newTimeoutError("logr queue shutdown timeout")
|
||||
case <-rec.flush:
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsShutdown returns true if this Logr instance has been shut down.
|
||||
// No further log records can be enqueued and no targets added after
|
||||
// shutdown.
|
||||
func (logr *Logr) IsShutdown() bool {
|
||||
logr.mux.Lock()
|
||||
defer logr.mux.Unlock()
|
||||
return logr.shutdown
|
||||
}
|
||||
|
||||
// Shutdown cleanly stops the logging engine after making best efforts
|
||||
// to flush all targets. Call this function right before application
|
||||
// exit - logr cannot be restarted once shut down.
|
||||
// `logr.ShutdownTimeout` determines how long shutdown can execute before
|
||||
// timing out. Use `IsTimeoutError` to determine if the returned error is
|
||||
// due to a timeout.
|
||||
func (logr *Logr) Shutdown() error {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), logr.shutdownTimeout())
|
||||
defer cancel()
|
||||
return logr.ShutdownWithTimeout(ctx)
|
||||
}
|
||||
|
||||
// Shutdown cleanly stops the logging engine after making best efforts
|
||||
// to flush all targets. Call this function right before application
|
||||
// exit - logr cannot be restarted once shut down.
|
||||
// Use `IsTimeoutError` to determine if the returned error is due to a
|
||||
// timeout.
|
||||
func (logr *Logr) ShutdownWithTimeout(ctx context.Context) error {
|
||||
logr.mux.Lock()
|
||||
if logr.shutdown {
|
||||
logr.mux.Unlock()
|
||||
return errors.New("Shutdown called again after shut down")
|
||||
}
|
||||
logr.shutdown = true
|
||||
logr.resetLevelCache()
|
||||
logr.mux.Unlock()
|
||||
|
||||
logr.metricsCloseOnce.Do(func() {
|
||||
if logr.metricsDone != nil {
|
||||
close(logr.metricsDone)
|
||||
}
|
||||
})
|
||||
|
||||
errs := merror.New()
|
||||
|
||||
// close the incoming channel and wait for read loop to exit.
|
||||
if logr.in != nil {
|
||||
close(logr.in)
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
errs.Append(newTimeoutError("logr queue shutdown timeout"))
|
||||
case <-logr.done:
|
||||
}
|
||||
}
|
||||
|
||||
// logr.in channel should now be drained to targets and no more log records
|
||||
// can be added.
|
||||
logr.tmux.RLock()
|
||||
defer logr.tmux.RUnlock()
|
||||
for _, t := range logr.targets {
|
||||
err := t.Shutdown(ctx)
|
||||
if err != nil {
|
||||
errs.Append(err)
|
||||
}
|
||||
}
|
||||
return errs.ErrorOrNil()
|
||||
}
|
||||
|
||||
// ReportError is used to notify the host application of any internal logging errors.
|
||||
// If `OnLoggerError` is not nil, it is called with the error, otherwise the error is
|
||||
// output to `os.Stderr`.
|
||||
func (logr *Logr) ReportError(err interface{}) {
|
||||
logr.incErrorCounter()
|
||||
|
||||
if logr.OnLoggerError == nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
return
|
||||
}
|
||||
logr.OnLoggerError(fmt.Errorf("%v", err))
|
||||
}
|
||||
|
||||
// BorrowBuffer borrows a buffer from the pool. Release the buffer to reduce garbage collection.
|
||||
func (logr *Logr) BorrowBuffer() *bytes.Buffer {
|
||||
if logr.DisableBufferPool {
|
||||
return &bytes.Buffer{}
|
||||
}
|
||||
return logr.bufferPool.Get().(*bytes.Buffer)
|
||||
}
|
||||
|
||||
// ReleaseBuffer returns a buffer to the pool to reduce garbage collection. The buffer is only
|
||||
// retained if less than MaxPooledBuffer.
|
||||
func (logr *Logr) ReleaseBuffer(buf *bytes.Buffer) {
|
||||
if !logr.DisableBufferPool && buf.Cap() < logr.MaxPooledBuffer {
|
||||
buf.Reset()
|
||||
logr.bufferPool.Put(buf)
|
||||
}
|
||||
}
|
||||
|
||||
// enqueueTimeout returns amount of time a log record can take to be queued.
|
||||
// This only applies to blocking enqueue which happen after `logr.OnQueueFull` is called
|
||||
// and returns false.
|
||||
func (logr *Logr) enqueueTimeout() time.Duration {
|
||||
if logr.EnqueueTimeout == 0 {
|
||||
return DefaultEnqueueTimeout
|
||||
}
|
||||
return logr.EnqueueTimeout
|
||||
}
|
||||
|
||||
// shutdownTimeout returns the timeout duration for `logr.Shutdown`.
|
||||
func (logr *Logr) shutdownTimeout() time.Duration {
|
||||
if logr.ShutdownTimeout == 0 {
|
||||
return DefaultShutdownTimeout
|
||||
}
|
||||
return logr.ShutdownTimeout
|
||||
}
|
||||
|
||||
// flushTimeout returns the timeout duration for `logr.Flush`.
|
||||
func (logr *Logr) flushTimeout() time.Duration {
|
||||
if logr.FlushTimeout == 0 {
|
||||
return DefaultFlushTimeout
|
||||
}
|
||||
return logr.FlushTimeout
|
||||
}
|
||||
|
||||
// start selects on incoming log records until done channel signals.
|
||||
// Incoming log records are fanned out to all log targets.
|
||||
func (logr *Logr) start() {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
logr.ReportError(r)
|
||||
go logr.start()
|
||||
}
|
||||
}()
|
||||
|
||||
for rec := range logr.in {
|
||||
if rec.flush != nil {
|
||||
logr.flush(rec.flush)
|
||||
} else {
|
||||
rec.prep()
|
||||
logr.fanout(rec)
|
||||
}
|
||||
}
|
||||
close(logr.done)
|
||||
}
|
||||
|
||||
// startMetricsUpdater updates the metrics for any polled values every `MetricsUpdateFreqSecs` seconds until
|
||||
// logr is closed.
|
||||
func (logr *Logr) startMetricsUpdater() {
|
||||
for {
|
||||
updateFreq := logr.getMetricsUpdateFreqMillis()
|
||||
if updateFreq == 0 {
|
||||
updateFreq = DefMetricsUpdateFreqMillis
|
||||
}
|
||||
if updateFreq < 250 {
|
||||
updateFreq = 250 // don't peg the CPU
|
||||
}
|
||||
|
||||
select {
|
||||
case <-logr.metricsDone:
|
||||
return
|
||||
case <-time.After(time.Duration(updateFreq) * time.Millisecond):
|
||||
logr.setQueueSizeGauge(float64(len(logr.in)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (logr *Logr) getMetricsUpdateFreqMillis() int64 {
|
||||
logr.mux.RLock()
|
||||
defer logr.mux.RUnlock()
|
||||
return logr.MetricsUpdateFreqMillis
|
||||
}
|
||||
|
||||
// fanout pushes a LogRec to all targets.
|
||||
func (logr *Logr) fanout(rec *LogRec) {
|
||||
var target Target
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
logr.ReportError(fmt.Errorf("fanout failed for target %s, %v", target, r))
|
||||
}
|
||||
}()
|
||||
|
||||
var logged bool
|
||||
defer func() {
|
||||
if logged {
|
||||
logr.incLoggedCounter() // call this after tmux is released
|
||||
}
|
||||
}()
|
||||
|
||||
logr.tmux.RLock()
|
||||
defer logr.tmux.RUnlock()
|
||||
for _, target = range logr.targets {
|
||||
if enabled, _ := target.IsLevelEnabled(rec.Level()); enabled {
|
||||
target.Log(rec)
|
||||
logged = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// flush drains the queue and notifies when done.
|
||||
func (logr *Logr) flush(done chan<- struct{}) {
|
||||
// first drain the logr queue.
|
||||
loop:
|
||||
for {
|
||||
var rec *LogRec
|
||||
select {
|
||||
case rec = <-logr.in:
|
||||
if rec.flush == nil {
|
||||
rec.prep()
|
||||
logr.fanout(rec)
|
||||
}
|
||||
default:
|
||||
break loop
|
||||
}
|
||||
}
|
||||
|
||||
logger := logr.NewLogger()
|
||||
|
||||
// drain all the targets; block until finished.
|
||||
logr.tmux.RLock()
|
||||
defer logr.tmux.RUnlock()
|
||||
for _, target := range logr.targets {
|
||||
rec := newFlushLogRec(logger)
|
||||
target.Log(rec)
|
||||
<-rec.flush
|
||||
}
|
||||
done <- struct{}{}
|
||||
}
|
189
vendor/github.com/mattermost/logr/logrec.go
generated
vendored
189
vendor/github.com/mattermost/logr/logrec.go
generated
vendored
@ -1,189 +0,0 @@
|
||||
package logr
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
logrPkg string
|
||||
)
|
||||
|
||||
func init() {
|
||||
// Calc current package name
|
||||
pcs := make([]uintptr, 2)
|
||||
_ = runtime.Callers(0, pcs)
|
||||
tmp := runtime.FuncForPC(pcs[1]).Name()
|
||||
logrPkg = getPackageName(tmp)
|
||||
}
|
||||
|
||||
// LogRec collects raw, unformatted data to be logged.
|
||||
// TODO: pool these? how to reliably know when targets are done with them? Copy for each target?
|
||||
type LogRec struct {
|
||||
mux sync.RWMutex
|
||||
time time.Time
|
||||
|
||||
level Level
|
||||
logger Logger
|
||||
|
||||
template string
|
||||
newline bool
|
||||
args []interface{}
|
||||
|
||||
stackPC []uintptr
|
||||
stackCount int
|
||||
|
||||
// flushes Logr and target queues when not nil.
|
||||
flush chan struct{}
|
||||
|
||||
// remaining fields calculated by `prep`
|
||||
msg string
|
||||
frames []runtime.Frame
|
||||
}
|
||||
|
||||
// NewLogRec creates a new LogRec with the current time and optional stack trace.
|
||||
func NewLogRec(lvl Level, logger Logger, template string, args []interface{}, incStacktrace bool) *LogRec {
|
||||
rec := &LogRec{time: time.Now(), logger: logger, level: lvl, template: template, args: args}
|
||||
if incStacktrace {
|
||||
rec.stackPC = make([]uintptr, DefaultMaxStackFrames)
|
||||
rec.stackCount = runtime.Callers(2, rec.stackPC)
|
||||
}
|
||||
return rec
|
||||
}
|
||||
|
||||
// newFlushLogRec creates a LogRec that flushes the Logr queue and
|
||||
// any target queues that support flushing.
|
||||
func newFlushLogRec(logger Logger) *LogRec {
|
||||
return &LogRec{logger: logger, flush: make(chan struct{})}
|
||||
}
|
||||
|
||||
// prep resolves all args and field values to strings, and
|
||||
// resolves stack trace to frames.
|
||||
func (rec *LogRec) prep() {
|
||||
rec.mux.Lock()
|
||||
defer rec.mux.Unlock()
|
||||
|
||||
// resolve args
|
||||
if rec.template == "" {
|
||||
if rec.newline {
|
||||
rec.msg = fmt.Sprintln(rec.args...)
|
||||
} else {
|
||||
rec.msg = fmt.Sprint(rec.args...)
|
||||
}
|
||||
} else {
|
||||
rec.msg = fmt.Sprintf(rec.template, rec.args...)
|
||||
}
|
||||
|
||||
// resolve stack trace
|
||||
if rec.stackCount > 0 {
|
||||
frames := runtime.CallersFrames(rec.stackPC[:rec.stackCount])
|
||||
for {
|
||||
f, more := frames.Next()
|
||||
rec.frames = append(rec.frames, f)
|
||||
if !more {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// remove leading logr package entries.
|
||||
var start int
|
||||
for i, frame := range rec.frames {
|
||||
pkg := getPackageName(frame.Function)
|
||||
if pkg != "" && pkg != logrPkg {
|
||||
start = i
|
||||
break
|
||||
}
|
||||
}
|
||||
rec.frames = rec.frames[start:]
|
||||
}
|
||||
}
|
||||
|
||||
// WithTime returns a shallow copy of the log record while replacing
|
||||
// the time. This can be used by targets and formatters to adjust
|
||||
// the time, or take ownership of the log record.
|
||||
func (rec *LogRec) WithTime(time time.Time) *LogRec {
|
||||
rec.mux.RLock()
|
||||
defer rec.mux.RUnlock()
|
||||
|
||||
return &LogRec{
|
||||
time: time,
|
||||
level: rec.level,
|
||||
logger: rec.logger,
|
||||
template: rec.template,
|
||||
newline: rec.newline,
|
||||
args: rec.args,
|
||||
msg: rec.msg,
|
||||
stackPC: rec.stackPC,
|
||||
stackCount: rec.stackCount,
|
||||
frames: rec.frames,
|
||||
}
|
||||
}
|
||||
|
||||
// Logger returns the `Logger` that created this `LogRec`.
|
||||
func (rec *LogRec) Logger() Logger {
|
||||
return rec.logger
|
||||
}
|
||||
|
||||
// Time returns this log record's time stamp.
|
||||
func (rec *LogRec) Time() time.Time {
|
||||
// no locking needed as this field is not mutated.
|
||||
return rec.time
|
||||
}
|
||||
|
||||
// Level returns this log record's Level.
|
||||
func (rec *LogRec) Level() Level {
|
||||
// no locking needed as this field is not mutated.
|
||||
return rec.level
|
||||
}
|
||||
|
||||
// Fields returns this log record's Fields.
|
||||
func (rec *LogRec) Fields() Fields {
|
||||
// no locking needed as this field is not mutated.
|
||||
return rec.logger.fields
|
||||
}
|
||||
|
||||
// Msg returns this log record's message text.
|
||||
func (rec *LogRec) Msg() string {
|
||||
rec.mux.RLock()
|
||||
defer rec.mux.RUnlock()
|
||||
return rec.msg
|
||||
}
|
||||
|
||||
// StackFrames returns this log record's stack frames or
|
||||
// nil if no stack trace was required.
|
||||
func (rec *LogRec) StackFrames() []runtime.Frame {
|
||||
rec.mux.RLock()
|
||||
defer rec.mux.RUnlock()
|
||||
return rec.frames
|
||||
}
|
||||
|
||||
// String returns a string representation of this log record.
|
||||
func (rec *LogRec) String() string {
|
||||
if rec.flush != nil {
|
||||
return "[flusher]"
|
||||
}
|
||||
|
||||
f := &DefaultFormatter{}
|
||||
buf := rec.logger.logr.BorrowBuffer()
|
||||
defer rec.logger.logr.ReleaseBuffer(buf)
|
||||
buf, _ = f.Format(rec, true, buf)
|
||||
return strings.TrimSpace(buf.String())
|
||||
}
|
||||
|
||||
// getPackageName reduces a fully qualified function name to the package name
|
||||
// By sirupsen: https://github.com/sirupsen/logrus/blob/master/entry.go
|
||||
func getPackageName(f string) string {
|
||||
for {
|
||||
lastPeriod := strings.LastIndex(f, ".")
|
||||
lastSlash := strings.LastIndex(f, "/")
|
||||
if lastPeriod > lastSlash {
|
||||
f = f[:lastPeriod]
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
return f
|
||||
}
|
117
vendor/github.com/mattermost/logr/metrics.go
generated
vendored
117
vendor/github.com/mattermost/logr/metrics.go
generated
vendored
@ -1,117 +0,0 @@
|
||||
package logr
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/wiggin77/merror"
|
||||
)
|
||||
|
||||
const (
|
||||
DefMetricsUpdateFreqMillis = 15000 // 15 seconds
|
||||
)
|
||||
|
||||
// Counter is a simple metrics sink that can only increment a value.
|
||||
// Implementations are external to Logr and provided via `MetricsCollector`.
|
||||
type Counter interface {
|
||||
// Inc increments the counter by 1. Use Add to increment it by arbitrary non-negative values.
|
||||
Inc()
|
||||
// Add adds the given value to the counter. It panics if the value is < 0.
|
||||
Add(float64)
|
||||
}
|
||||
|
||||
// Gauge is a simple metrics sink that can receive values and increase or decrease.
|
||||
// Implementations are external to Logr and provided via `MetricsCollector`.
|
||||
type Gauge interface {
|
||||
// Set sets the Gauge to an arbitrary value.
|
||||
Set(float64)
|
||||
// Add adds the given value to the Gauge. (The value can be negative, resulting in a decrease of the Gauge.)
|
||||
Add(float64)
|
||||
// Sub subtracts the given value from the Gauge. (The value can be negative, resulting in an increase of the Gauge.)
|
||||
Sub(float64)
|
||||
}
|
||||
|
||||
// MetricsCollector provides a way for users of this Logr package to have metrics pushed
|
||||
// in an efficient way to any backend, e.g. Prometheus.
|
||||
// For each target added to Logr, the supplied MetricsCollector will provide a Gauge
|
||||
// and Counters that will be called frequently as logging occurs.
|
||||
type MetricsCollector interface {
|
||||
// QueueSizeGauge returns a Gauge that will be updated by the named target.
|
||||
QueueSizeGauge(target string) (Gauge, error)
|
||||
// LoggedCounter returns a Counter that will be incremented by the named target.
|
||||
LoggedCounter(target string) (Counter, error)
|
||||
// ErrorCounter returns a Counter that will be incremented by the named target.
|
||||
ErrorCounter(target string) (Counter, error)
|
||||
// DroppedCounter returns a Counter that will be incremented by the named target.
|
||||
DroppedCounter(target string) (Counter, error)
|
||||
// BlockedCounter returns a Counter that will be incremented by the named target.
|
||||
BlockedCounter(target string) (Counter, error)
|
||||
}
|
||||
|
||||
// TargetWithMetrics is a target that provides metrics.
|
||||
type TargetWithMetrics interface {
|
||||
EnableMetrics(collector MetricsCollector, updateFreqMillis int64) error
|
||||
}
|
||||
|
||||
func (logr *Logr) getMetricsCollector() MetricsCollector {
|
||||
logr.mux.RLock()
|
||||
defer logr.mux.RUnlock()
|
||||
return logr.metrics
|
||||
}
|
||||
|
||||
// SetMetricsCollector enables metrics collection by supplying a MetricsCollector.
|
||||
// The MetricsCollector provides counters and gauges that are updated by log targets.
|
||||
func (logr *Logr) SetMetricsCollector(collector MetricsCollector) error {
|
||||
if collector == nil {
|
||||
return errors.New("collector cannot be nil")
|
||||
}
|
||||
|
||||
logr.mux.Lock()
|
||||
logr.metrics = collector
|
||||
logr.queueSizeGauge, _ = collector.QueueSizeGauge("_logr")
|
||||
logr.loggedCounter, _ = collector.LoggedCounter("_logr")
|
||||
logr.errorCounter, _ = collector.ErrorCounter("_logr")
|
||||
logr.mux.Unlock()
|
||||
|
||||
logr.metricsInitOnce.Do(func() {
|
||||
logr.metricsDone = make(chan struct{})
|
||||
go logr.startMetricsUpdater()
|
||||
})
|
||||
|
||||
merr := merror.New()
|
||||
|
||||
logr.tmux.RLock()
|
||||
defer logr.tmux.RUnlock()
|
||||
for _, target := range logr.targets {
|
||||
if tm, ok := target.(TargetWithMetrics); ok {
|
||||
if err := tm.EnableMetrics(collector, logr.MetricsUpdateFreqMillis); err != nil {
|
||||
merr.Append(err)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return merr.ErrorOrNil()
|
||||
}
|
||||
|
||||
func (logr *Logr) setQueueSizeGauge(val float64) {
|
||||
logr.mux.RLock()
|
||||
defer logr.mux.RUnlock()
|
||||
if logr.queueSizeGauge != nil {
|
||||
logr.queueSizeGauge.Set(val)
|
||||
}
|
||||
}
|
||||
|
||||
func (logr *Logr) incLoggedCounter() {
|
||||
logr.mux.RLock()
|
||||
defer logr.mux.RUnlock()
|
||||
if logr.loggedCounter != nil {
|
||||
logr.loggedCounter.Inc()
|
||||
}
|
||||
}
|
||||
|
||||
func (logr *Logr) incErrorCounter() {
|
||||
logr.mux.RLock()
|
||||
defer logr.mux.RUnlock()
|
||||
if logr.errorCounter != nil {
|
||||
logr.errorCounter.Inc()
|
||||
}
|
||||
}
|
299
vendor/github.com/mattermost/logr/target.go
generated
vendored
299
vendor/github.com/mattermost/logr/target.go
generated
vendored
@ -1,299 +0,0 @@
|
||||
package logr
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Target represents a destination for log records such as file,
|
||||
// database, TCP socket, etc.
|
||||
type Target interface {
|
||||
// SetName provides an optional name for the target.
|
||||
SetName(name string)
|
||||
|
||||
// IsLevelEnabled returns true if this target should emit
|
||||
// logs for the specified level. Also determines if
|
||||
// a stack trace is required.
|
||||
IsLevelEnabled(Level) (enabled bool, stacktrace bool)
|
||||
|
||||
// Formatter returns the Formatter associated with this Target.
|
||||
Formatter() Formatter
|
||||
|
||||
// Log outputs the log record to this target's destination.
|
||||
Log(rec *LogRec)
|
||||
|
||||
// Shutdown makes best effort to flush target queue and
|
||||
// frees/closes all resources.
|
||||
Shutdown(ctx context.Context) error
|
||||
}
|
||||
|
||||
// RecordWriter can convert a LogRecord to bytes and output to some data sink.
|
||||
type RecordWriter interface {
|
||||
Write(rec *LogRec) error
|
||||
}
|
||||
|
||||
// Basic provides the basic functionality of a Target that can be used
|
||||
// to more easily compose your own Targets. To use, just embed Basic
|
||||
// in your target type, implement `RecordWriter`, and call `(*Basic).Start`.
|
||||
type Basic struct {
|
||||
target Target
|
||||
|
||||
filter Filter
|
||||
formatter Formatter
|
||||
|
||||
in chan *LogRec
|
||||
done chan struct{}
|
||||
w RecordWriter
|
||||
|
||||
mux sync.RWMutex
|
||||
name string
|
||||
|
||||
metrics bool
|
||||
queueSizeGauge Gauge
|
||||
loggedCounter Counter
|
||||
errorCounter Counter
|
||||
droppedCounter Counter
|
||||
blockedCounter Counter
|
||||
|
||||
metricsUpdateFreqMillis int64
|
||||
}
|
||||
|
||||
// Start initializes this target helper and starts accepting log records for processing.
|
||||
func (b *Basic) Start(target Target, rw RecordWriter, filter Filter, formatter Formatter, maxQueued int) {
|
||||
if filter == nil {
|
||||
filter = &StdFilter{Lvl: Fatal}
|
||||
}
|
||||
if formatter == nil {
|
||||
formatter = &DefaultFormatter{}
|
||||
}
|
||||
|
||||
b.target = target
|
||||
b.filter = filter
|
||||
b.formatter = formatter
|
||||
b.in = make(chan *LogRec, maxQueued)
|
||||
b.done = make(chan struct{}, 1)
|
||||
b.w = rw
|
||||
go b.start()
|
||||
|
||||
if b.hasMetrics() {
|
||||
go b.startMetricsUpdater()
|
||||
}
|
||||
}
|
||||
|
||||
func (b *Basic) SetName(name string) {
|
||||
b.mux.Lock()
|
||||
defer b.mux.Unlock()
|
||||
b.name = name
|
||||
}
|
||||
|
||||
// IsLevelEnabled returns true if this target should emit
|
||||
// logs for the specified level. Also determines if
|
||||
// a stack trace is required.
|
||||
func (b *Basic) IsLevelEnabled(lvl Level) (enabled bool, stacktrace bool) {
|
||||
return b.filter.IsEnabled(lvl), b.filter.IsStacktraceEnabled(lvl)
|
||||
}
|
||||
|
||||
// Formatter returns the Formatter associated with this Target.
|
||||
func (b *Basic) Formatter() Formatter {
|
||||
return b.formatter
|
||||
}
|
||||
|
||||
// Shutdown stops processing log records after making best
|
||||
// effort to flush queue.
|
||||
func (b *Basic) Shutdown(ctx context.Context) error {
|
||||
// close the incoming channel and wait for read loop to exit.
|
||||
close(b.in)
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
case <-b.done:
|
||||
}
|
||||
|
||||
// b.in channel should now be drained.
|
||||
return nil
|
||||
}
|
||||
|
||||
// Log outputs the log record to this targets destination.
|
||||
func (b *Basic) Log(rec *LogRec) {
|
||||
lgr := rec.Logger().Logr()
|
||||
select {
|
||||
case b.in <- rec:
|
||||
default:
|
||||
handler := lgr.OnTargetQueueFull
|
||||
if handler != nil && handler(b.target, rec, cap(b.in)) {
|
||||
b.incDroppedCounter()
|
||||
return // drop the record
|
||||
}
|
||||
b.incBlockedCounter()
|
||||
|
||||
select {
|
||||
case <-time.After(lgr.enqueueTimeout()):
|
||||
lgr.ReportError(fmt.Errorf("target enqueue timeout for log rec [%v]", rec))
|
||||
case b.in <- rec: // block until success or timeout
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Metrics enables metrics collection using the provided MetricsCollector.
|
||||
func (b *Basic) EnableMetrics(collector MetricsCollector, updateFreqMillis int64) error {
|
||||
name := fmt.Sprintf("%v", b)
|
||||
|
||||
b.mux.Lock()
|
||||
defer b.mux.Unlock()
|
||||
|
||||
b.metrics = true
|
||||
b.metricsUpdateFreqMillis = updateFreqMillis
|
||||
|
||||
var err error
|
||||
|
||||
if b.queueSizeGauge, err = collector.QueueSizeGauge(name); err != nil {
|
||||
return err
|
||||
}
|
||||
if b.loggedCounter, err = collector.LoggedCounter(name); err != nil {
|
||||
return err
|
||||
}
|
||||
if b.errorCounter, err = collector.ErrorCounter(name); err != nil {
|
||||
return err
|
||||
}
|
||||
if b.droppedCounter, err = collector.DroppedCounter(name); err != nil {
|
||||
return err
|
||||
}
|
||||
if b.blockedCounter, err = collector.BlockedCounter(name); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *Basic) hasMetrics() bool {
|
||||
b.mux.RLock()
|
||||
defer b.mux.RUnlock()
|
||||
return b.metrics
|
||||
}
|
||||
|
||||
func (b *Basic) setQueueSizeGauge(val float64) {
|
||||
b.mux.RLock()
|
||||
defer b.mux.RUnlock()
|
||||
if b.queueSizeGauge != nil {
|
||||
b.queueSizeGauge.Set(val)
|
||||
}
|
||||
}
|
||||
|
||||
func (b *Basic) incLoggedCounter() {
|
||||
b.mux.RLock()
|
||||
defer b.mux.RUnlock()
|
||||
if b.loggedCounter != nil {
|
||||
b.loggedCounter.Inc()
|
||||
}
|
||||
}
|
||||
|
||||
func (b *Basic) incErrorCounter() {
|
||||
b.mux.RLock()
|
||||
defer b.mux.RUnlock()
|
||||
if b.errorCounter != nil {
|
||||
b.errorCounter.Inc()
|
||||
}
|
||||
}
|
||||
|
||||
func (b *Basic) incDroppedCounter() {
|
||||
b.mux.RLock()
|
||||
defer b.mux.RUnlock()
|
||||
if b.droppedCounter != nil {
|
||||
b.droppedCounter.Inc()
|
||||
}
|
||||
}
|
||||
|
||||
func (b *Basic) incBlockedCounter() {
|
||||
b.mux.RLock()
|
||||
defer b.mux.RUnlock()
|
||||
if b.blockedCounter != nil {
|
||||
b.blockedCounter.Inc()
|
||||
}
|
||||
}
|
||||
|
||||
// String returns a name for this target. Use `SetName` to specify a name.
|
||||
func (b *Basic) String() string {
|
||||
b.mux.RLock()
|
||||
defer b.mux.RUnlock()
|
||||
|
||||
if b.name != "" {
|
||||
return b.name
|
||||
}
|
||||
return fmt.Sprintf("%T", b.target)
|
||||
}
|
||||
|
||||
// Start accepts log records via In channel and writes to the
|
||||
// supplied writer, until Done channel signaled.
|
||||
func (b *Basic) start() {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
fmt.Fprintln(os.Stderr, "Basic.start -- ", r)
|
||||
go b.start()
|
||||
}
|
||||
}()
|
||||
|
||||
for rec := range b.in {
|
||||
if rec.flush != nil {
|
||||
b.flush(rec.flush)
|
||||
} else {
|
||||
err := b.w.Write(rec)
|
||||
if err != nil {
|
||||
b.incErrorCounter()
|
||||
rec.Logger().Logr().ReportError(err)
|
||||
} else {
|
||||
b.incLoggedCounter()
|
||||
}
|
||||
}
|
||||
}
|
||||
close(b.done)
|
||||
}
|
||||
|
||||
// startMetricsUpdater updates the metrics for any polled values every `MetricsUpdateFreqSecs` seconds until
|
||||
// target is closed.
|
||||
func (b *Basic) startMetricsUpdater() {
|
||||
for {
|
||||
updateFreq := b.getMetricsUpdateFreqMillis()
|
||||
if updateFreq == 0 {
|
||||
updateFreq = DefMetricsUpdateFreqMillis
|
||||
}
|
||||
if updateFreq < 250 {
|
||||
updateFreq = 250 // don't peg the CPU
|
||||
}
|
||||
|
||||
select {
|
||||
case <-b.done:
|
||||
return
|
||||
case <-time.After(time.Duration(updateFreq) * time.Millisecond):
|
||||
b.setQueueSizeGauge(float64(len(b.in)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (b *Basic) getMetricsUpdateFreqMillis() int64 {
|
||||
b.mux.RLock()
|
||||
defer b.mux.RUnlock()
|
||||
return b.metricsUpdateFreqMillis
|
||||
}
|
||||
|
||||
// flush drains the queue and notifies when done.
|
||||
func (b *Basic) flush(done chan<- struct{}) {
|
||||
for {
|
||||
var rec *LogRec
|
||||
var err error
|
||||
select {
|
||||
case rec = <-b.in:
|
||||
// ignore any redundant flush records.
|
||||
if rec.flush == nil {
|
||||
err = b.w.Write(rec)
|
||||
if err != nil {
|
||||
b.incErrorCounter()
|
||||
rec.Logger().Logr().ReportError(err)
|
||||
}
|
||||
}
|
||||
default:
|
||||
done <- struct{}{}
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
87
vendor/github.com/mattermost/logr/target/file.go
generated
vendored
87
vendor/github.com/mattermost/logr/target/file.go
generated
vendored
@ -1,87 +0,0 @@
|
||||
package target
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
|
||||
"github.com/mattermost/logr"
|
||||
"github.com/wiggin77/merror"
|
||||
"gopkg.in/natefinch/lumberjack.v2"
|
||||
)
|
||||
|
||||
type FileOptions struct {
|
||||
// Filename is the file to write logs to. Backup log files will be retained
|
||||
// in the same directory. It uses <processname>-lumberjack.log in
|
||||
// os.TempDir() if empty.
|
||||
Filename string
|
||||
|
||||
// MaxSize is the maximum size in megabytes of the log file before it gets
|
||||
// rotated. It defaults to 100 megabytes.
|
||||
MaxSize int
|
||||
|
||||
// MaxAge is the maximum number of days to retain old log files based on the
|
||||
// timestamp encoded in their filename. Note that a day is defined as 24
|
||||
// hours and may not exactly correspond to calendar days due to daylight
|
||||
// savings, leap seconds, etc. The default is not to remove old log files
|
||||
// based on age.
|
||||
MaxAge int
|
||||
|
||||
// MaxBackups is the maximum number of old log files to retain. The default
|
||||
// is to retain all old log files (though MaxAge may still cause them to get
|
||||
// deleted.)
|
||||
MaxBackups int
|
||||
|
||||
// Compress determines if the rotated log files should be compressed
|
||||
// using gzip. The default is not to perform compression.
|
||||
Compress bool
|
||||
}
|
||||
|
||||
// File outputs log records to a file which can be log rotated based on size or age.
|
||||
// Uses `https://github.com/natefinch/lumberjack` for rotation.
|
||||
type File struct {
|
||||
logr.Basic
|
||||
out io.WriteCloser
|
||||
}
|
||||
|
||||
// NewFileTarget creates a target capable of outputting log records to a rotated file.
|
||||
func NewFileTarget(filter logr.Filter, formatter logr.Formatter, opts FileOptions, maxQueue int) *File {
|
||||
lumber := &lumberjack.Logger{
|
||||
Filename: opts.Filename,
|
||||
MaxSize: opts.MaxSize,
|
||||
MaxBackups: opts.MaxBackups,
|
||||
MaxAge: opts.MaxAge,
|
||||
Compress: opts.Compress,
|
||||
}
|
||||
f := &File{out: lumber}
|
||||
f.Basic.Start(f, f, filter, formatter, maxQueue)
|
||||
return f
|
||||
}
|
||||
|
||||
// Write converts the log record to bytes, via the Formatter,
|
||||
// and outputs to a file.
|
||||
func (f *File) Write(rec *logr.LogRec) error {
|
||||
_, stacktrace := f.IsLevelEnabled(rec.Level())
|
||||
|
||||
buf := rec.Logger().Logr().BorrowBuffer()
|
||||
defer rec.Logger().Logr().ReleaseBuffer(buf)
|
||||
|
||||
buf, err := f.Formatter().Format(rec, stacktrace, buf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = f.out.Write(buf.Bytes())
|
||||
return err
|
||||
}
|
||||
|
||||
// Shutdown flushes any remaining log records and closes the file.
|
||||
func (f *File) Shutdown(ctx context.Context) error {
|
||||
errs := merror.New()
|
||||
|
||||
err := f.Basic.Shutdown(ctx)
|
||||
errs.Append(err)
|
||||
|
||||
err = f.out.Close()
|
||||
errs.Append(err)
|
||||
|
||||
return errs.ErrorOrNil()
|
||||
}
|
89
vendor/github.com/mattermost/logr/target/syslog.go
generated
vendored
89
vendor/github.com/mattermost/logr/target/syslog.go
generated
vendored
@ -1,89 +0,0 @@
|
||||
// +build !windows,!nacl,!plan9
|
||||
|
||||
package target
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log/syslog"
|
||||
|
||||
"github.com/mattermost/logr"
|
||||
"github.com/wiggin77/merror"
|
||||
)
|
||||
|
||||
// Syslog outputs log records to local or remote syslog.
|
||||
type Syslog struct {
|
||||
logr.Basic
|
||||
w *syslog.Writer
|
||||
}
|
||||
|
||||
// SyslogParams provides parameters for dialing a syslog daemon.
|
||||
type SyslogParams struct {
|
||||
Network string
|
||||
Raddr string
|
||||
Priority syslog.Priority
|
||||
Tag string
|
||||
}
|
||||
|
||||
// NewSyslogTarget creates a target capable of outputting log records to remote or local syslog.
|
||||
func NewSyslogTarget(filter logr.Filter, formatter logr.Formatter, params *SyslogParams, maxQueue int) (*Syslog, error) {
|
||||
writer, err := syslog.Dial(params.Network, params.Raddr, params.Priority, params.Tag)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s := &Syslog{w: writer}
|
||||
s.Basic.Start(s, s, filter, formatter, maxQueue)
|
||||
|
||||
return s, nil
|
||||
}
|
||||
|
||||
// Shutdown stops processing log records after making best
|
||||
// effort to flush queue.
|
||||
func (s *Syslog) Shutdown(ctx context.Context) error {
|
||||
errs := merror.New()
|
||||
|
||||
err := s.Basic.Shutdown(ctx)
|
||||
errs.Append(err)
|
||||
|
||||
err = s.w.Close()
|
||||
errs.Append(err)
|
||||
|
||||
return errs.ErrorOrNil()
|
||||
}
|
||||
|
||||
// Write converts the log record to bytes, via the Formatter,
|
||||
// and outputs to syslog.
|
||||
func (s *Syslog) Write(rec *logr.LogRec) error {
|
||||
_, stacktrace := s.IsLevelEnabled(rec.Level())
|
||||
|
||||
buf := rec.Logger().Logr().BorrowBuffer()
|
||||
defer rec.Logger().Logr().ReleaseBuffer(buf)
|
||||
|
||||
buf, err := s.Formatter().Format(rec, stacktrace, buf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
txt := buf.String()
|
||||
|
||||
switch rec.Level() {
|
||||
case logr.Panic, logr.Fatal:
|
||||
err = s.w.Crit(txt)
|
||||
case logr.Error:
|
||||
err = s.w.Err(txt)
|
||||
case logr.Warn:
|
||||
err = s.w.Warning(txt)
|
||||
case logr.Debug, logr.Trace:
|
||||
err = s.w.Debug(txt)
|
||||
default:
|
||||
// logr.Info plus all custom levels.
|
||||
err = s.w.Info(txt)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
reporter := rec.Logger().Logr().ReportError
|
||||
reporter(fmt.Errorf("syslog write fail: %w", err))
|
||||
// syslog writer will try to reconnect.
|
||||
}
|
||||
return err
|
||||
}
|
40
vendor/github.com/mattermost/logr/target/writer.go
generated
vendored
40
vendor/github.com/mattermost/logr/target/writer.go
generated
vendored
@ -1,40 +0,0 @@
|
||||
package target
|
||||
|
||||
import (
|
||||
"io"
|
||||
"io/ioutil"
|
||||
|
||||
"github.com/mattermost/logr"
|
||||
)
|
||||
|
||||
// Writer outputs log records to any `io.Writer`.
|
||||
type Writer struct {
|
||||
logr.Basic
|
||||
out io.Writer
|
||||
}
|
||||
|
||||
// NewWriterTarget creates a target capable of outputting log records to an io.Writer.
|
||||
func NewWriterTarget(filter logr.Filter, formatter logr.Formatter, out io.Writer, maxQueue int) *Writer {
|
||||
if out == nil {
|
||||
out = ioutil.Discard
|
||||
}
|
||||
w := &Writer{out: out}
|
||||
w.Basic.Start(w, w, filter, formatter, maxQueue)
|
||||
return w
|
||||
}
|
||||
|
||||
// Write converts the log record to bytes, via the Formatter,
|
||||
// and outputs to the io.Writer.
|
||||
func (w *Writer) Write(rec *logr.LogRec) error {
|
||||
_, stacktrace := w.IsLevelEnabled(rec.Level())
|
||||
|
||||
buf := rec.Logger().Logr().BorrowBuffer()
|
||||
defer rec.Logger().Logr().ReleaseBuffer(buf)
|
||||
|
||||
buf, err := w.Formatter().Format(rec, stacktrace, buf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = w.out.Write(buf.Bytes())
|
||||
return err
|
||||
}
|
34
vendor/github.com/mattermost/logr/timeout.go
generated
vendored
34
vendor/github.com/mattermost/logr/timeout.go
generated
vendored
@ -1,34 +0,0 @@
|
||||
package logr
|
||||
|
||||
import "github.com/wiggin77/merror"
|
||||
|
||||
// timeoutError is returned from functions that can timeout.
|
||||
type timeoutError struct {
|
||||
text string
|
||||
}
|
||||
|
||||
// newTimeoutError returns a TimeoutError.
|
||||
func newTimeoutError(text string) timeoutError {
|
||||
return timeoutError{text: text}
|
||||
}
|
||||
|
||||
// IsTimeoutError returns true if err is a TimeoutError.
|
||||
func IsTimeoutError(err error) bool {
|
||||
if _, ok := err.(timeoutError); ok {
|
||||
return true
|
||||
}
|
||||
// if a multi-error, return true if any of the errors
|
||||
// are TimeoutError
|
||||
if merr, ok := err.(*merror.MError); ok {
|
||||
for _, e := range merr.Errors() {
|
||||
if IsTimeoutError(e) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (err timeoutError) Error() string {
|
||||
return err.text
|
||||
}
|
897
vendor/github.com/mattermost/mattermost-server/v5/LICENSE.txt
generated
vendored
897
vendor/github.com/mattermost/mattermost-server/v5/LICENSE.txt
generated
vendored
@ -1,897 +0,0 @@
|
||||
Mattermost Licensing
|
||||
|
||||
SOFTWARE LICENSING
|
||||
|
||||
You are licensed to use compiled versions of the Mattermost platform produced by Mattermost, Inc. under an MIT LICENSE
|
||||
|
||||
- See MIT-COMPILED-LICENSE.md included in compiled versions for details
|
||||
|
||||
You may be licensed to use source code to create compiled versions not produced by Mattermost, Inc. in one of two ways:
|
||||
|
||||
1. Under the Free Software Foundation’s GNU AGPL v.3.0, subject to the exceptions outlined in this policy; or
|
||||
2. Under a commercial license available from Mattermost, Inc. by contacting commercial@mattermost.com
|
||||
|
||||
You are licensed to use the source code in Admin Tools and Configuration Files (templates/, config/default.json, i18n/, model/,
|
||||
plugin/ and all subdirectories thereof) under the Apache License v2.0.
|
||||
|
||||
We promise that we will not enforce the copyleft provisions in AGPL v3.0 against you if your application (a) does not
|
||||
link to the Mattermost Platform directly, but exclusively uses the Mattermost Admin Tools and Configuration Files, and
|
||||
(b) you have not modified, added to or adapted the source code of Mattermost in a way that results in the creation of
|
||||
a “modified version” or “work based on” Mattermost as these terms are defined in the AGPL v3.0 license.
|
||||
|
||||
MATTERMOST TRADEMARK GUIDELINES
|
||||
|
||||
Your use of the mark Mattermost is subject to Mattermost, Inc's prior written approval and our organization’s Trademark
|
||||
Standards of Use at http://www.mattermost.org/trademark-standards-of-use/. For trademark approval or any questions
|
||||
you have about using these trademarks, please email trademark@mattermost.com
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
The software is released under the terms of the GNU Affero General Public
|
||||
License, version 3.
|
||||
|
||||
GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
Version 3, 19 November 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU Affero General Public License is a free, copyleft license for
|
||||
software and other kinds of works, specifically designed to ensure
|
||||
cooperation with the community in the case of network server software.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
our General Public Licenses are intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
Developers that use our General Public Licenses protect your rights
|
||||
with two steps: (1) assert copyright on the software, and (2) offer
|
||||
you this License which gives you legal permission to copy, distribute
|
||||
and/or modify the software.
|
||||
|
||||
A secondary benefit of defending all users' freedom is that
|
||||
improvements made in alternate versions of the program, if they
|
||||
receive widespread use, become available for other developers to
|
||||
incorporate. Many developers of free software are heartened and
|
||||
encouraged by the resulting cooperation. However, in the case of
|
||||
software used on network servers, this result may fail to come about.
|
||||
The GNU General Public License permits making a modified version and
|
||||
letting the public access it on a server without ever releasing its
|
||||
source code to the public.
|
||||
|
||||
The GNU Affero General Public License is designed specifically to
|
||||
ensure that, in such cases, the modified source code becomes available
|
||||
to the community. It requires the operator of a network server to
|
||||
provide the source code of the modified version running there to the
|
||||
users of that server. Therefore, public use of a modified version, on
|
||||
a publicly accessible server, gives the public access to the source
|
||||
code of the modified version.
|
||||
|
||||
An older license, called the Affero General Public License and
|
||||
published by Affero, was designed to accomplish similar goals. This is
|
||||
a different license, not a version of the Affero GPL, but Affero has
|
||||
released a new version of the Affero GPL which permits relicensing under
|
||||
this license.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU Affero General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Remote Network Interaction; Use with the GNU General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, if you modify the
|
||||
Program, your modified version must prominently offer all users
|
||||
interacting with it remotely through a computer network (if your version
|
||||
supports such interaction) an opportunity to receive the Corresponding
|
||||
Source of your version by providing access to the Corresponding Source
|
||||
from a network server at no charge, through some standard or customary
|
||||
means of facilitating copying of software. This Corresponding Source
|
||||
shall include the Corresponding Source for any work covered by version 3
|
||||
of the GNU General Public License that is incorporated pursuant to the
|
||||
following paragraph.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the work with which it is combined will remain governed by version
|
||||
3 of the GNU General Public License.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU Affero General Public License from time to time. Such new versions
|
||||
will be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU Affero General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU Affero General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU Affero General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If your software can interact with users remotely through a computer
|
||||
network, you should also make sure that it provides a way for users to
|
||||
get its source. For example, if your program is a web application, its
|
||||
interface could display a "Source" link that leads users to an archive
|
||||
of the code. There are many ways you could offer source, and different
|
||||
solutions will be better for different programs; see section 13 for the
|
||||
specific requirements.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU AGPL, see
|
||||
<http://www.gnu.org/licenses/>.
|
4844
vendor/github.com/mattermost/mattermost-server/v5/NOTICE.txt
generated
vendored
4844
vendor/github.com/mattermost/mattermost-server/v5/NOTICE.txt
generated
vendored
File diff suppressed because it is too large
Load Diff
97
vendor/github.com/mattermost/mattermost-server/v5/model/access.go
generated
vendored
97
vendor/github.com/mattermost/mattermost-server/v5/model/access.go
generated
vendored
@ -1,97 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
const (
|
||||
ACCESS_TOKEN_GRANT_TYPE = "authorization_code"
|
||||
ACCESS_TOKEN_TYPE = "bearer"
|
||||
REFRESH_TOKEN_GRANT_TYPE = "refresh_token"
|
||||
)
|
||||
|
||||
type AccessData struct {
|
||||
ClientId string `json:"client_id"`
|
||||
UserId string `json:"user_id"`
|
||||
Token string `json:"token"`
|
||||
RefreshToken string `json:"refresh_token"`
|
||||
RedirectUri string `json:"redirect_uri"`
|
||||
ExpiresAt int64 `json:"expires_at"`
|
||||
Scope string `json:"scope"`
|
||||
}
|
||||
|
||||
type AccessResponse struct {
|
||||
AccessToken string `json:"access_token"`
|
||||
TokenType string `json:"token_type"`
|
||||
ExpiresIn int32 `json:"expires_in"`
|
||||
Scope string `json:"scope"`
|
||||
RefreshToken string `json:"refresh_token"`
|
||||
IdToken string `json:"id_token"`
|
||||
}
|
||||
|
||||
// IsValid validates the AccessData and returns an error if it isn't configured
|
||||
// correctly.
|
||||
func (ad *AccessData) IsValid() *AppError {
|
||||
|
||||
if ad.ClientId == "" || len(ad.ClientId) > 26 {
|
||||
return NewAppError("AccessData.IsValid", "model.access.is_valid.client_id.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if ad.UserId == "" || len(ad.UserId) > 26 {
|
||||
return NewAppError("AccessData.IsValid", "model.access.is_valid.user_id.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if len(ad.Token) != 26 {
|
||||
return NewAppError("AccessData.IsValid", "model.access.is_valid.access_token.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if len(ad.RefreshToken) > 26 {
|
||||
return NewAppError("AccessData.IsValid", "model.access.is_valid.refresh_token.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if ad.RedirectUri == "" || len(ad.RedirectUri) > 256 || !IsValidHttpUrl(ad.RedirectUri) {
|
||||
return NewAppError("AccessData.IsValid", "model.access.is_valid.redirect_uri.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ad *AccessData) IsExpired() bool {
|
||||
|
||||
if ad.ExpiresAt <= 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
if GetMillis() > ad.ExpiresAt {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (ad *AccessData) ToJson() string {
|
||||
b, _ := json.Marshal(ad)
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func AccessDataFromJson(data io.Reader) *AccessData {
|
||||
var ad *AccessData
|
||||
json.NewDecoder(data).Decode(&ad)
|
||||
return ad
|
||||
}
|
||||
|
||||
func (ar *AccessResponse) ToJson() string {
|
||||
b, _ := json.Marshal(ar)
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func AccessResponseFromJson(data io.Reader) *AccessResponse {
|
||||
var ar *AccessResponse
|
||||
json.NewDecoder(data).Decode(&ar)
|
||||
return ar
|
||||
}
|
41
vendor/github.com/mattermost/mattermost-server/v5/model/analytics_row.go
generated
vendored
41
vendor/github.com/mattermost/mattermost-server/v5/model/analytics_row.go
generated
vendored
@ -1,41 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
)
|
||||
|
||||
type AnalyticsRow struct {
|
||||
Name string `json:"name"`
|
||||
Value float64 `json:"value"`
|
||||
}
|
||||
|
||||
type AnalyticsRows []*AnalyticsRow
|
||||
|
||||
func (ar *AnalyticsRow) ToJson() string {
|
||||
b, _ := json.Marshal(ar)
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func AnalyticsRowFromJson(data io.Reader) *AnalyticsRow {
|
||||
var ar *AnalyticsRow
|
||||
json.NewDecoder(data).Decode(&ar)
|
||||
return ar
|
||||
}
|
||||
|
||||
func (ar AnalyticsRows) ToJson() string {
|
||||
b, err := json.Marshal(ar)
|
||||
if err != nil {
|
||||
return "[]"
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func AnalyticsRowsFromJson(data io.Reader) AnalyticsRows {
|
||||
var ar AnalyticsRows
|
||||
json.NewDecoder(data).Decode(&ar)
|
||||
return ar
|
||||
}
|
47
vendor/github.com/mattermost/mattermost-server/v5/model/at_mentions.go
generated
vendored
47
vendor/github.com/mattermost/mattermost-server/v5/model/at_mentions.go
generated
vendored
@ -1,47 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var atMentionRegexp = regexp.MustCompile(`\B@[[:alnum:]][[:alnum:]\.\-_:]*`)
|
||||
|
||||
const usernameSpecialChars = ".-_"
|
||||
|
||||
// PossibleAtMentions returns all substrings in message that look like valid @
|
||||
// mentions.
|
||||
func PossibleAtMentions(message string) []string {
|
||||
var names []string
|
||||
|
||||
if !strings.Contains(message, "@") {
|
||||
return names
|
||||
}
|
||||
|
||||
alreadyMentioned := make(map[string]bool)
|
||||
for _, match := range atMentionRegexp.FindAllString(message, -1) {
|
||||
name := NormalizeUsername(match[1:])
|
||||
if !alreadyMentioned[name] && IsValidUsernameAllowRemote(name) {
|
||||
names = append(names, name)
|
||||
alreadyMentioned[name] = true
|
||||
}
|
||||
}
|
||||
|
||||
return names
|
||||
}
|
||||
|
||||
// TrimUsernameSpecialChar tries to remove the last character from word if it
|
||||
// is a special character for usernames (dot, dash or underscore). If not, it
|
||||
// returns the same string.
|
||||
func TrimUsernameSpecialChar(word string) (string, bool) {
|
||||
len := len(word)
|
||||
|
||||
if len > 0 && strings.LastIndexAny(word, usernameSpecialChars) == (len-1) {
|
||||
return word[:len-1], true
|
||||
}
|
||||
|
||||
return word, false
|
||||
}
|
30
vendor/github.com/mattermost/mattermost-server/v5/model/audit.go
generated
vendored
30
vendor/github.com/mattermost/mattermost-server/v5/model/audit.go
generated
vendored
@ -1,30 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
)
|
||||
|
||||
type Audit struct {
|
||||
Id string `json:"id"`
|
||||
CreateAt int64 `json:"create_at"`
|
||||
UserId string `json:"user_id"`
|
||||
Action string `json:"action"`
|
||||
ExtraInfo string `json:"extra_info"`
|
||||
IpAddress string `json:"ip_address"`
|
||||
SessionId string `json:"session_id"`
|
||||
}
|
||||
|
||||
func (o *Audit) ToJson() string {
|
||||
b, _ := json.Marshal(o)
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func AuditFromJson(data io.Reader) *Audit {
|
||||
var o *Audit
|
||||
json.NewDecoder(data).Decode(&o)
|
||||
return o
|
||||
}
|
713
vendor/github.com/mattermost/mattermost-server/v5/model/auditconv.go
generated
vendored
713
vendor/github.com/mattermost/mattermost-server/v5/model/auditconv.go
generated
vendored
@ -1,713 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/francoispqt/gojay"
|
||||
)
|
||||
|
||||
// AuditModelTypeConv converts key model types to something better suited for audit output.
|
||||
func AuditModelTypeConv(val interface{}) (newVal interface{}, converted bool) {
|
||||
if val == nil {
|
||||
return nil, false
|
||||
}
|
||||
switch v := val.(type) {
|
||||
case *Channel:
|
||||
return newAuditChannel(v), true
|
||||
case *Team:
|
||||
return newAuditTeam(v), true
|
||||
case *User:
|
||||
return newAuditUser(v), true
|
||||
case *Command:
|
||||
return newAuditCommand(v), true
|
||||
case *CommandArgs:
|
||||
return newAuditCommandArgs(v), true
|
||||
case *Bot:
|
||||
return newAuditBot(v), true
|
||||
case *ChannelModerationPatch:
|
||||
return newAuditChannelModerationPatch(v), true
|
||||
case *Emoji:
|
||||
return newAuditEmoji(v), true
|
||||
case *FileInfo:
|
||||
return newAuditFileInfo(v), true
|
||||
case *Group:
|
||||
return newAuditGroup(v), true
|
||||
case *Job:
|
||||
return newAuditJob(v), true
|
||||
case *OAuthApp:
|
||||
return newAuditOAuthApp(v), true
|
||||
case *Post:
|
||||
return newAuditPost(v), true
|
||||
case *Role:
|
||||
return newAuditRole(v), true
|
||||
case *Scheme:
|
||||
return newAuditScheme(v), true
|
||||
case *SchemeRoles:
|
||||
return newAuditSchemeRoles(v), true
|
||||
case *Session:
|
||||
return newAuditSession(v), true
|
||||
case *IncomingWebhook:
|
||||
return newAuditIncomingWebhook(v), true
|
||||
case *OutgoingWebhook:
|
||||
return newAuditOutgoingWebhook(v), true
|
||||
case *RemoteCluster:
|
||||
return newRemoteCluster(v), true
|
||||
}
|
||||
return val, false
|
||||
}
|
||||
|
||||
type auditChannel struct {
|
||||
ID string
|
||||
Name string
|
||||
Type string
|
||||
}
|
||||
|
||||
// newAuditChannel creates a simplified representation of Channel for output to audit log.
|
||||
func newAuditChannel(c *Channel) auditChannel {
|
||||
var channel auditChannel
|
||||
if c != nil {
|
||||
channel.ID = c.Id
|
||||
channel.Name = c.Name
|
||||
channel.Type = c.Type
|
||||
}
|
||||
return channel
|
||||
}
|
||||
|
||||
func (c auditChannel) MarshalJSONObject(enc *gojay.Encoder) {
|
||||
enc.StringKey("id", c.ID)
|
||||
enc.StringKey("name", c.Name)
|
||||
enc.StringKey("type", c.Type)
|
||||
}
|
||||
|
||||
func (c auditChannel) IsNil() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
type auditTeam struct {
|
||||
ID string
|
||||
Name string
|
||||
Type string
|
||||
}
|
||||
|
||||
// newAuditTeam creates a simplified representation of Team for output to audit log.
|
||||
func newAuditTeam(t *Team) auditTeam {
|
||||
var team auditTeam
|
||||
if t != nil {
|
||||
team.ID = t.Id
|
||||
team.Name = t.Name
|
||||
team.Type = t.Type
|
||||
}
|
||||
return team
|
||||
}
|
||||
|
||||
func (t auditTeam) MarshalJSONObject(enc *gojay.Encoder) {
|
||||
enc.StringKey("id", t.ID)
|
||||
enc.StringKey("name", t.Name)
|
||||
enc.StringKey("type", t.Type)
|
||||
}
|
||||
|
||||
func (t auditTeam) IsNil() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
type auditUser struct {
|
||||
ID string
|
||||
Name string
|
||||
Roles string
|
||||
}
|
||||
|
||||
// newAuditUser creates a simplified representation of User for output to audit log.
|
||||
func newAuditUser(u *User) auditUser {
|
||||
var user auditUser
|
||||
if u != nil {
|
||||
user.ID = u.Id
|
||||
user.Name = u.Username
|
||||
user.Roles = u.Roles
|
||||
}
|
||||
return user
|
||||
}
|
||||
|
||||
func (u auditUser) MarshalJSONObject(enc *gojay.Encoder) {
|
||||
enc.StringKey("id", u.ID)
|
||||
enc.StringKey("name", u.Name)
|
||||
enc.StringKey("roles", u.Roles)
|
||||
}
|
||||
|
||||
func (u auditUser) IsNil() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
type auditCommand struct {
|
||||
ID string
|
||||
CreatorID string
|
||||
TeamID string
|
||||
Trigger string
|
||||
Method string
|
||||
Username string
|
||||
IconURL string
|
||||
AutoComplete bool
|
||||
AutoCompleteDesc string
|
||||
AutoCompleteHint string
|
||||
DisplayName string
|
||||
Description string
|
||||
URL string
|
||||
}
|
||||
|
||||
// newAuditCommand creates a simplified representation of Command for output to audit log.
|
||||
func newAuditCommand(c *Command) auditCommand {
|
||||
var cmd auditCommand
|
||||
if c != nil {
|
||||
cmd.ID = c.Id
|
||||
cmd.CreatorID = c.CreatorId
|
||||
cmd.TeamID = c.TeamId
|
||||
cmd.Trigger = c.Trigger
|
||||
cmd.Method = c.Method
|
||||
cmd.Username = c.Username
|
||||
cmd.IconURL = c.IconURL
|
||||
cmd.AutoComplete = c.AutoComplete
|
||||
cmd.AutoCompleteDesc = c.AutoCompleteDesc
|
||||
cmd.AutoCompleteHint = c.AutoCompleteHint
|
||||
cmd.DisplayName = c.DisplayName
|
||||
cmd.Description = c.Description
|
||||
cmd.URL = c.URL
|
||||
}
|
||||
return cmd
|
||||
}
|
||||
|
||||
func (cmd auditCommand) MarshalJSONObject(enc *gojay.Encoder) {
|
||||
enc.StringKey("id", cmd.ID)
|
||||
enc.StringKey("creator_id", cmd.CreatorID)
|
||||
enc.StringKey("team_id", cmd.TeamID)
|
||||
enc.StringKey("trigger", cmd.Trigger)
|
||||
enc.StringKey("method", cmd.Method)
|
||||
enc.StringKey("username", cmd.Username)
|
||||
enc.StringKey("icon_url", cmd.IconURL)
|
||||
enc.BoolKey("auto_complete", cmd.AutoComplete)
|
||||
enc.StringKey("auto_complete_desc", cmd.AutoCompleteDesc)
|
||||
enc.StringKey("auto_complete_hint", cmd.AutoCompleteHint)
|
||||
enc.StringKey("display", cmd.DisplayName)
|
||||
enc.StringKey("desc", cmd.Description)
|
||||
enc.StringKey("url", cmd.URL)
|
||||
}
|
||||
|
||||
func (cmd auditCommand) IsNil() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
type auditCommandArgs struct {
|
||||
ChannelID string
|
||||
TeamID string
|
||||
TriggerID string
|
||||
Command string
|
||||
}
|
||||
|
||||
// newAuditCommandArgs creates a simplified representation of CommandArgs for output to audit log.
|
||||
func newAuditCommandArgs(ca *CommandArgs) auditCommandArgs {
|
||||
var cmdargs auditCommandArgs
|
||||
if ca != nil {
|
||||
cmdargs.ChannelID = ca.ChannelId
|
||||
cmdargs.TeamID = ca.TeamId
|
||||
cmdargs.TriggerID = ca.TriggerId
|
||||
cmdargs.Command = ca.Command
|
||||
}
|
||||
return cmdargs
|
||||
}
|
||||
|
||||
func (ca auditCommandArgs) MarshalJSONObject(enc *gojay.Encoder) {
|
||||
enc.StringKey("channel_id", ca.ChannelID)
|
||||
enc.StringKey("team_id", ca.TriggerID)
|
||||
enc.StringKey("trigger_id", ca.TeamID)
|
||||
enc.StringKey("command", ca.Command)
|
||||
}
|
||||
|
||||
func (ca auditCommandArgs) IsNil() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
type auditBot struct {
|
||||
UserID string
|
||||
Username string
|
||||
Displayname string
|
||||
}
|
||||
|
||||
// newAuditBot creates a simplified representation of Bot for output to audit log.
|
||||
func newAuditBot(b *Bot) auditBot {
|
||||
var bot auditBot
|
||||
if b != nil {
|
||||
bot.UserID = b.UserId
|
||||
bot.Username = b.Username
|
||||
bot.Displayname = b.DisplayName
|
||||
}
|
||||
return bot
|
||||
}
|
||||
|
||||
func (b auditBot) MarshalJSONObject(enc *gojay.Encoder) {
|
||||
enc.StringKey("user_id", b.UserID)
|
||||
enc.StringKey("username", b.Username)
|
||||
enc.StringKey("display", b.Displayname)
|
||||
}
|
||||
|
||||
func (b auditBot) IsNil() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
type auditChannelModerationPatch struct {
|
||||
Name string
|
||||
RoleGuests bool
|
||||
RoleMembers bool
|
||||
}
|
||||
|
||||
// newAuditChannelModerationPatch creates a simplified representation of ChannelModerationPatch for output to audit log.
|
||||
func newAuditChannelModerationPatch(p *ChannelModerationPatch) auditChannelModerationPatch {
|
||||
var patch auditChannelModerationPatch
|
||||
if p != nil {
|
||||
if p.Name != nil {
|
||||
patch.Name = *p.Name
|
||||
}
|
||||
if p.Roles.Guests != nil {
|
||||
patch.RoleGuests = *p.Roles.Guests
|
||||
}
|
||||
if p.Roles.Members != nil {
|
||||
patch.RoleMembers = *p.Roles.Members
|
||||
}
|
||||
}
|
||||
return patch
|
||||
}
|
||||
|
||||
func (p auditChannelModerationPatch) MarshalJSONObject(enc *gojay.Encoder) {
|
||||
enc.StringKey("name", p.Name)
|
||||
enc.BoolKey("role_guests", p.RoleGuests)
|
||||
enc.BoolKey("role_members", p.RoleMembers)
|
||||
}
|
||||
|
||||
func (p auditChannelModerationPatch) IsNil() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
type auditEmoji struct {
|
||||
ID string
|
||||
Name string
|
||||
}
|
||||
|
||||
// newAuditEmoji creates a simplified representation of Emoji for output to audit log.
|
||||
func newAuditEmoji(e *Emoji) auditEmoji {
|
||||
var emoji auditEmoji
|
||||
if e != nil {
|
||||
emoji.ID = e.Id
|
||||
emoji.Name = e.Name
|
||||
}
|
||||
return emoji
|
||||
}
|
||||
|
||||
func (e auditEmoji) MarshalJSONObject(enc *gojay.Encoder) {
|
||||
enc.StringKey("id", e.ID)
|
||||
enc.StringKey("name", e.Name)
|
||||
}
|
||||
|
||||
func (e auditEmoji) IsNil() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
type auditFileInfo struct {
|
||||
ID string
|
||||
PostID string
|
||||
Path string
|
||||
Name string
|
||||
Extension string
|
||||
Size int64
|
||||
}
|
||||
|
||||
// newAuditFileInfo creates a simplified representation of FileInfo for output to audit log.
|
||||
func newAuditFileInfo(f *FileInfo) auditFileInfo {
|
||||
var fi auditFileInfo
|
||||
if f != nil {
|
||||
fi.ID = f.Id
|
||||
fi.PostID = f.PostId
|
||||
fi.Path = f.Path
|
||||
fi.Name = f.Name
|
||||
fi.Extension = f.Extension
|
||||
fi.Size = f.Size
|
||||
}
|
||||
return fi
|
||||
}
|
||||
|
||||
func (fi auditFileInfo) MarshalJSONObject(enc *gojay.Encoder) {
|
||||
enc.StringKey("id", fi.ID)
|
||||
enc.StringKey("post_id", fi.PostID)
|
||||
enc.StringKey("path", fi.Path)
|
||||
enc.StringKey("name", fi.Name)
|
||||
enc.StringKey("ext", fi.Extension)
|
||||
enc.Int64Key("size", fi.Size)
|
||||
}
|
||||
|
||||
func (fi auditFileInfo) IsNil() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
type auditGroup struct {
|
||||
ID string
|
||||
Name string
|
||||
DisplayName string
|
||||
Description string
|
||||
}
|
||||
|
||||
// newAuditGroup creates a simplified representation of Group for output to audit log.
|
||||
func newAuditGroup(g *Group) auditGroup {
|
||||
var group auditGroup
|
||||
if g != nil {
|
||||
group.ID = g.Id
|
||||
if g.Name == nil {
|
||||
group.Name = ""
|
||||
} else {
|
||||
group.Name = *g.Name
|
||||
}
|
||||
group.DisplayName = g.DisplayName
|
||||
group.Description = g.Description
|
||||
}
|
||||
return group
|
||||
}
|
||||
|
||||
func (g auditGroup) MarshalJSONObject(enc *gojay.Encoder) {
|
||||
enc.StringKey("id", g.ID)
|
||||
enc.StringKey("name", g.Name)
|
||||
enc.StringKey("display", g.DisplayName)
|
||||
enc.StringKey("desc", g.Description)
|
||||
}
|
||||
|
||||
func (g auditGroup) IsNil() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
type auditJob struct {
|
||||
ID string
|
||||
Type string
|
||||
Priority int64
|
||||
StartAt int64
|
||||
}
|
||||
|
||||
// newAuditJob creates a simplified representation of Job for output to audit log.
|
||||
func newAuditJob(j *Job) auditJob {
|
||||
var job auditJob
|
||||
if j != nil {
|
||||
job.ID = j.Id
|
||||
job.Type = j.Type
|
||||
job.Priority = j.Priority
|
||||
job.StartAt = j.StartAt
|
||||
}
|
||||
return job
|
||||
}
|
||||
|
||||
func (j auditJob) MarshalJSONObject(enc *gojay.Encoder) {
|
||||
enc.StringKey("id", j.ID)
|
||||
enc.StringKey("type", j.Type)
|
||||
enc.Int64Key("priority", j.Priority)
|
||||
enc.Int64Key("start_at", j.StartAt)
|
||||
}
|
||||
|
||||
func (j auditJob) IsNil() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
type auditOAuthApp struct {
|
||||
ID string
|
||||
CreatorID string
|
||||
Name string
|
||||
Description string
|
||||
IsTrusted bool
|
||||
}
|
||||
|
||||
// newAuditOAuthApp creates a simplified representation of OAuthApp for output to audit log.
|
||||
func newAuditOAuthApp(o *OAuthApp) auditOAuthApp {
|
||||
var oauth auditOAuthApp
|
||||
if o != nil {
|
||||
oauth.ID = o.Id
|
||||
oauth.CreatorID = o.CreatorId
|
||||
oauth.Name = o.Name
|
||||
oauth.Description = o.Description
|
||||
oauth.IsTrusted = o.IsTrusted
|
||||
}
|
||||
return oauth
|
||||
}
|
||||
|
||||
func (o auditOAuthApp) MarshalJSONObject(enc *gojay.Encoder) {
|
||||
enc.StringKey("id", o.ID)
|
||||
enc.StringKey("creator_id", o.CreatorID)
|
||||
enc.StringKey("name", o.Name)
|
||||
enc.StringKey("desc", o.Description)
|
||||
enc.BoolKey("trusted", o.IsTrusted)
|
||||
}
|
||||
|
||||
func (o auditOAuthApp) IsNil() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
type auditPost struct {
|
||||
ID string
|
||||
ChannelID string
|
||||
Type string
|
||||
IsPinned bool
|
||||
}
|
||||
|
||||
// newAuditPost creates a simplified representation of Post for output to audit log.
|
||||
func newAuditPost(p *Post) auditPost {
|
||||
var post auditPost
|
||||
if p != nil {
|
||||
post.ID = p.Id
|
||||
post.ChannelID = p.ChannelId
|
||||
post.Type = p.Type
|
||||
post.IsPinned = p.IsPinned
|
||||
}
|
||||
return post
|
||||
}
|
||||
|
||||
func (p auditPost) MarshalJSONObject(enc *gojay.Encoder) {
|
||||
enc.StringKey("id", p.ID)
|
||||
enc.StringKey("channel_id", p.ChannelID)
|
||||
enc.StringKey("type", p.Type)
|
||||
enc.BoolKey("pinned", p.IsPinned)
|
||||
}
|
||||
|
||||
func (p auditPost) IsNil() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
type auditRole struct {
|
||||
ID string
|
||||
Name string
|
||||
DisplayName string
|
||||
Permissions []string
|
||||
SchemeManaged bool
|
||||
BuiltIn bool
|
||||
}
|
||||
|
||||
// newAuditRole creates a simplified representation of Role for output to audit log.
|
||||
func newAuditRole(r *Role) auditRole {
|
||||
var role auditRole
|
||||
if r != nil {
|
||||
role.ID = r.Id
|
||||
role.Name = r.Name
|
||||
role.DisplayName = r.DisplayName
|
||||
role.Permissions = append(role.Permissions, r.Permissions...)
|
||||
role.SchemeManaged = r.SchemeManaged
|
||||
role.BuiltIn = r.BuiltIn
|
||||
}
|
||||
return role
|
||||
}
|
||||
|
||||
func (r auditRole) MarshalJSONObject(enc *gojay.Encoder) {
|
||||
enc.StringKey("id", r.ID)
|
||||
enc.StringKey("name", r.Name)
|
||||
enc.StringKey("display", r.DisplayName)
|
||||
enc.SliceStringKey("perms", r.Permissions)
|
||||
enc.BoolKey("schemeManaged", r.SchemeManaged)
|
||||
enc.BoolKey("builtin", r.BuiltIn)
|
||||
}
|
||||
|
||||
func (r auditRole) IsNil() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
type auditScheme struct {
|
||||
ID string
|
||||
Name string
|
||||
DisplayName string
|
||||
Scope string
|
||||
}
|
||||
|
||||
// newAuditScheme creates a simplified representation of Scheme for output to audit log.
|
||||
func newAuditScheme(s *Scheme) auditScheme {
|
||||
var scheme auditScheme
|
||||
if s != nil {
|
||||
scheme.ID = s.Id
|
||||
scheme.Name = s.Name
|
||||
scheme.DisplayName = s.DisplayName
|
||||
scheme.Scope = s.Scope
|
||||
}
|
||||
return scheme
|
||||
}
|
||||
|
||||
func (s auditScheme) MarshalJSONObject(enc *gojay.Encoder) {
|
||||
enc.StringKey("id", s.ID)
|
||||
enc.StringKey("name", s.Name)
|
||||
enc.StringKey("display", s.DisplayName)
|
||||
enc.StringKey("scope", s.Scope)
|
||||
}
|
||||
|
||||
func (s auditScheme) IsNil() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
type auditSchemeRoles struct {
|
||||
SchemeAdmin bool
|
||||
SchemeUser bool
|
||||
SchemeGuest bool
|
||||
}
|
||||
|
||||
// newAuditSchemeRoles creates a simplified representation of SchemeRoles for output to audit log.
|
||||
func newAuditSchemeRoles(s *SchemeRoles) auditSchemeRoles {
|
||||
var roles auditSchemeRoles
|
||||
if s != nil {
|
||||
roles.SchemeAdmin = s.SchemeAdmin
|
||||
roles.SchemeUser = s.SchemeUser
|
||||
roles.SchemeGuest = s.SchemeGuest
|
||||
}
|
||||
return roles
|
||||
}
|
||||
|
||||
func (s auditSchemeRoles) MarshalJSONObject(enc *gojay.Encoder) {
|
||||
enc.BoolKey("admin", s.SchemeAdmin)
|
||||
enc.BoolKey("user", s.SchemeUser)
|
||||
enc.BoolKey("guest", s.SchemeGuest)
|
||||
}
|
||||
|
||||
func (s auditSchemeRoles) IsNil() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
type auditSession struct {
|
||||
ID string
|
||||
UserId string
|
||||
DeviceId string
|
||||
}
|
||||
|
||||
// newAuditSession creates a simplified representation of Session for output to audit log.
|
||||
func newAuditSession(s *Session) auditSession {
|
||||
var session auditSession
|
||||
if s != nil {
|
||||
session.ID = s.Id
|
||||
session.UserId = s.UserId
|
||||
session.DeviceId = s.DeviceId
|
||||
}
|
||||
return session
|
||||
}
|
||||
|
||||
func (s auditSession) MarshalJSONObject(enc *gojay.Encoder) {
|
||||
enc.StringKey("id", s.ID)
|
||||
enc.StringKey("user_id", s.UserId)
|
||||
enc.StringKey("device_id", s.DeviceId)
|
||||
}
|
||||
|
||||
func (s auditSession) IsNil() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
type auditIncomingWebhook struct {
|
||||
ID string
|
||||
ChannelID string
|
||||
TeamId string
|
||||
DisplayName string
|
||||
Description string
|
||||
}
|
||||
|
||||
// newAuditIncomingWebhook creates a simplified representation of IncomingWebhook for output to audit log.
|
||||
func newAuditIncomingWebhook(h *IncomingWebhook) auditIncomingWebhook {
|
||||
var hook auditIncomingWebhook
|
||||
if h != nil {
|
||||
hook.ID = h.Id
|
||||
hook.ChannelID = h.ChannelId
|
||||
hook.TeamId = h.TeamId
|
||||
hook.DisplayName = h.DisplayName
|
||||
hook.Description = h.Description
|
||||
}
|
||||
return hook
|
||||
}
|
||||
|
||||
func (h auditIncomingWebhook) MarshalJSONObject(enc *gojay.Encoder) {
|
||||
enc.StringKey("id", h.ID)
|
||||
enc.StringKey("channel_id", h.ChannelID)
|
||||
enc.StringKey("team_id", h.TeamId)
|
||||
enc.StringKey("display", h.DisplayName)
|
||||
enc.StringKey("desc", h.Description)
|
||||
}
|
||||
|
||||
func (h auditIncomingWebhook) IsNil() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
type auditOutgoingWebhook struct {
|
||||
ID string
|
||||
ChannelID string
|
||||
TeamID string
|
||||
TriggerWords StringArray
|
||||
TriggerWhen int
|
||||
DisplayName string
|
||||
Description string
|
||||
ContentType string
|
||||
Username string
|
||||
}
|
||||
|
||||
// newAuditOutgoingWebhook creates a simplified representation of OutgoingWebhook for output to audit log.
|
||||
func newAuditOutgoingWebhook(h *OutgoingWebhook) auditOutgoingWebhook {
|
||||
var hook auditOutgoingWebhook
|
||||
if h != nil {
|
||||
hook.ID = h.Id
|
||||
hook.ChannelID = h.ChannelId
|
||||
hook.TeamID = h.TeamId
|
||||
hook.TriggerWords = h.TriggerWords
|
||||
hook.TriggerWhen = h.TriggerWhen
|
||||
hook.DisplayName = h.DisplayName
|
||||
hook.Description = h.Description
|
||||
hook.ContentType = h.ContentType
|
||||
hook.Username = h.Username
|
||||
}
|
||||
return hook
|
||||
}
|
||||
|
||||
func (h auditOutgoingWebhook) MarshalJSONObject(enc *gojay.Encoder) {
|
||||
enc.StringKey("id", h.ID)
|
||||
enc.StringKey("channel_id", h.ChannelID)
|
||||
enc.StringKey("team_id", h.TeamID)
|
||||
enc.SliceStringKey("trigger_words", h.TriggerWords)
|
||||
enc.IntKey("trigger_when", h.TriggerWhen)
|
||||
enc.StringKey("display", h.DisplayName)
|
||||
enc.StringKey("desc", h.Description)
|
||||
enc.StringKey("content_type", h.ContentType)
|
||||
enc.StringKey("username", h.Username)
|
||||
}
|
||||
|
||||
func (h auditOutgoingWebhook) IsNil() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
type auditRemoteCluster struct {
|
||||
RemoteId string
|
||||
RemoteTeamId string
|
||||
Name string
|
||||
DisplayName string
|
||||
SiteURL string
|
||||
CreateAt int64
|
||||
LastPingAt int64
|
||||
CreatorId string
|
||||
}
|
||||
|
||||
// newRemoteCluster creates a simplified representation of RemoteCluster for output to audit log.
|
||||
func newRemoteCluster(r *RemoteCluster) auditRemoteCluster {
|
||||
var rc auditRemoteCluster
|
||||
if r != nil {
|
||||
rc.RemoteId = r.RemoteId
|
||||
rc.RemoteTeamId = r.RemoteTeamId
|
||||
rc.Name = r.Name
|
||||
rc.DisplayName = r.DisplayName
|
||||
rc.SiteURL = r.SiteURL
|
||||
rc.CreateAt = r.CreateAt
|
||||
rc.LastPingAt = r.LastPingAt
|
||||
rc.CreatorId = r.CreatorId
|
||||
}
|
||||
return rc
|
||||
}
|
||||
|
||||
func (r auditRemoteCluster) MarshalJSONObject(enc *gojay.Encoder) {
|
||||
enc.StringKey("remote_id", r.RemoteId)
|
||||
enc.StringKey("remote_team_id", r.RemoteTeamId)
|
||||
enc.StringKey("name", r.Name)
|
||||
enc.StringKey("display_name", r.DisplayName)
|
||||
enc.StringKey("site_url", r.SiteURL)
|
||||
enc.Int64Key("create_at", r.CreateAt)
|
||||
enc.Int64Key("last_ping_at", r.LastPingAt)
|
||||
enc.StringKey("creator_id", r.CreatorId)
|
||||
}
|
||||
|
||||
func (r auditRemoteCluster) IsNil() bool {
|
||||
return false
|
||||
}
|
33
vendor/github.com/mattermost/mattermost-server/v5/model/audits.go
generated
vendored
33
vendor/github.com/mattermost/mattermost-server/v5/model/audits.go
generated
vendored
@ -1,33 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
)
|
||||
|
||||
type Audits []Audit
|
||||
|
||||
func (o Audits) Etag() string {
|
||||
if len(o) > 0 {
|
||||
// the first in the list is always the most current
|
||||
return Etag(o[0].CreateAt)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (o Audits) ToJson() string {
|
||||
b, err := json.Marshal(o)
|
||||
if err != nil {
|
||||
return "[]"
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func AuditsFromJson(data io.Reader) Audits {
|
||||
var o Audits
|
||||
json.NewDecoder(data).Decode(&o)
|
||||
return o
|
||||
}
|
142
vendor/github.com/mattermost/mattermost-server/v5/model/authorize.go
generated
vendored
142
vendor/github.com/mattermost/mattermost-server/v5/model/authorize.go
generated
vendored
@ -1,142 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
const (
|
||||
AUTHCODE_EXPIRE_TIME = 60 * 10 // 10 minutes
|
||||
AUTHCODE_RESPONSE_TYPE = "code"
|
||||
IMPLICIT_RESPONSE_TYPE = "token"
|
||||
DEFAULT_SCOPE = "user"
|
||||
)
|
||||
|
||||
type AuthData struct {
|
||||
ClientId string `json:"client_id"`
|
||||
UserId string `json:"user_id"`
|
||||
Code string `json:"code"`
|
||||
ExpiresIn int32 `json:"expires_in"`
|
||||
CreateAt int64 `json:"create_at"`
|
||||
RedirectUri string `json:"redirect_uri"`
|
||||
State string `json:"state"`
|
||||
Scope string `json:"scope"`
|
||||
}
|
||||
|
||||
type AuthorizeRequest struct {
|
||||
ResponseType string `json:"response_type"`
|
||||
ClientId string `json:"client_id"`
|
||||
RedirectUri string `json:"redirect_uri"`
|
||||
Scope string `json:"scope"`
|
||||
State string `json:"state"`
|
||||
}
|
||||
|
||||
// IsValid validates the AuthData and returns an error if it isn't configured
|
||||
// correctly.
|
||||
func (ad *AuthData) IsValid() *AppError {
|
||||
|
||||
if !IsValidId(ad.ClientId) {
|
||||
return NewAppError("AuthData.IsValid", "model.authorize.is_valid.client_id.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if !IsValidId(ad.UserId) {
|
||||
return NewAppError("AuthData.IsValid", "model.authorize.is_valid.user_id.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if ad.Code == "" || len(ad.Code) > 128 {
|
||||
return NewAppError("AuthData.IsValid", "model.authorize.is_valid.auth_code.app_error", nil, "client_id="+ad.ClientId, http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if ad.ExpiresIn == 0 {
|
||||
return NewAppError("AuthData.IsValid", "model.authorize.is_valid.expires.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if ad.CreateAt <= 0 {
|
||||
return NewAppError("AuthData.IsValid", "model.authorize.is_valid.create_at.app_error", nil, "client_id="+ad.ClientId, http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if len(ad.RedirectUri) > 256 || !IsValidHttpUrl(ad.RedirectUri) {
|
||||
return NewAppError("AuthData.IsValid", "model.authorize.is_valid.redirect_uri.app_error", nil, "client_id="+ad.ClientId, http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if len(ad.State) > 1024 {
|
||||
return NewAppError("AuthData.IsValid", "model.authorize.is_valid.state.app_error", nil, "client_id="+ad.ClientId, http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if len(ad.Scope) > 128 {
|
||||
return NewAppError("AuthData.IsValid", "model.authorize.is_valid.scope.app_error", nil, "client_id="+ad.ClientId, http.StatusBadRequest)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsValid validates the AuthorizeRequest and returns an error if it isn't configured
|
||||
// correctly.
|
||||
func (ar *AuthorizeRequest) IsValid() *AppError {
|
||||
|
||||
if !IsValidId(ar.ClientId) {
|
||||
return NewAppError("AuthData.IsValid", "model.authorize.is_valid.client_id.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if ar.ResponseType == "" {
|
||||
return NewAppError("AuthData.IsValid", "model.authorize.is_valid.response_type.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if ar.RedirectUri == "" || len(ar.RedirectUri) > 256 || !IsValidHttpUrl(ar.RedirectUri) {
|
||||
return NewAppError("AuthData.IsValid", "model.authorize.is_valid.redirect_uri.app_error", nil, "client_id="+ar.ClientId, http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if len(ar.State) > 1024 {
|
||||
return NewAppError("AuthData.IsValid", "model.authorize.is_valid.state.app_error", nil, "client_id="+ar.ClientId, http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if len(ar.Scope) > 128 {
|
||||
return NewAppError("AuthData.IsValid", "model.authorize.is_valid.scope.app_error", nil, "client_id="+ar.ClientId, http.StatusBadRequest)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ad *AuthData) PreSave() {
|
||||
if ad.ExpiresIn == 0 {
|
||||
ad.ExpiresIn = AUTHCODE_EXPIRE_TIME
|
||||
}
|
||||
|
||||
if ad.CreateAt == 0 {
|
||||
ad.CreateAt = GetMillis()
|
||||
}
|
||||
|
||||
if ad.Scope == "" {
|
||||
ad.Scope = DEFAULT_SCOPE
|
||||
}
|
||||
}
|
||||
|
||||
func (ad *AuthData) ToJson() string {
|
||||
b, _ := json.Marshal(ad)
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func AuthDataFromJson(data io.Reader) *AuthData {
|
||||
var ad *AuthData
|
||||
json.NewDecoder(data).Decode(&ad)
|
||||
return ad
|
||||
}
|
||||
|
||||
func (ar *AuthorizeRequest) ToJson() string {
|
||||
b, _ := json.Marshal(ar)
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func AuthorizeRequestFromJson(data io.Reader) *AuthorizeRequest {
|
||||
var ar *AuthorizeRequest
|
||||
json.NewDecoder(data).Decode(&ar)
|
||||
return ar
|
||||
}
|
||||
|
||||
func (ad *AuthData) IsExpired() bool {
|
||||
return GetMillis() > ad.CreateAt+int64(ad.ExpiresIn*1000)
|
||||
}
|
254
vendor/github.com/mattermost/mattermost-server/v5/model/bot.go
generated
vendored
254
vendor/github.com/mattermost/mattermost-server/v5/model/bot.go
generated
vendored
@ -1,254 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
const (
|
||||
BOT_DISPLAY_NAME_MAX_RUNES = USER_FIRST_NAME_MAX_RUNES
|
||||
BOT_DESCRIPTION_MAX_RUNES = 1024
|
||||
BOT_CREATOR_ID_MAX_RUNES = KEY_VALUE_PLUGIN_ID_MAX_RUNES // UserId or PluginId
|
||||
BOT_WARN_METRIC_BOT_USERNAME = "mattermost-advisor"
|
||||
BOT_SYSTEM_BOT_USERNAME = "system-bot"
|
||||
)
|
||||
|
||||
// Bot is a special type of User meant for programmatic interactions.
|
||||
// Note that the primary key of a bot is the UserId, and matches the primary key of the
|
||||
// corresponding user.
|
||||
type Bot struct {
|
||||
UserId string `json:"user_id"`
|
||||
Username string `json:"username"`
|
||||
DisplayName string `json:"display_name,omitempty"`
|
||||
Description string `json:"description,omitempty"`
|
||||
OwnerId string `json:"owner_id"`
|
||||
LastIconUpdate int64 `json:"last_icon_update,omitempty"`
|
||||
CreateAt int64 `json:"create_at"`
|
||||
UpdateAt int64 `json:"update_at"`
|
||||
DeleteAt int64 `json:"delete_at"`
|
||||
}
|
||||
|
||||
// BotPatch is a description of what fields to update on an existing bot.
|
||||
type BotPatch struct {
|
||||
Username *string `json:"username"`
|
||||
DisplayName *string `json:"display_name"`
|
||||
Description *string `json:"description"`
|
||||
}
|
||||
|
||||
// BotGetOptions acts as a filter on bulk bot fetching queries.
|
||||
type BotGetOptions struct {
|
||||
OwnerId string
|
||||
IncludeDeleted bool
|
||||
OnlyOrphaned bool
|
||||
Page int
|
||||
PerPage int
|
||||
}
|
||||
|
||||
// BotList is a list of bots.
|
||||
type BotList []*Bot
|
||||
|
||||
// Trace describes the minimum information required to identify a bot for the purpose of logging.
|
||||
func (b *Bot) Trace() map[string]interface{} {
|
||||
return map[string]interface{}{"user_id": b.UserId}
|
||||
}
|
||||
|
||||
// Clone returns a shallow copy of the bot.
|
||||
func (b *Bot) Clone() *Bot {
|
||||
copy := *b
|
||||
return ©
|
||||
}
|
||||
|
||||
// IsValid validates the bot and returns an error if it isn't configured correctly.
|
||||
func (b *Bot) IsValid() *AppError {
|
||||
if !IsValidId(b.UserId) {
|
||||
return NewAppError("Bot.IsValid", "model.bot.is_valid.user_id.app_error", b.Trace(), "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if !IsValidUsername(b.Username) {
|
||||
return NewAppError("Bot.IsValid", "model.bot.is_valid.username.app_error", b.Trace(), "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if utf8.RuneCountInString(b.DisplayName) > BOT_DISPLAY_NAME_MAX_RUNES {
|
||||
return NewAppError("Bot.IsValid", "model.bot.is_valid.user_id.app_error", b.Trace(), "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if utf8.RuneCountInString(b.Description) > BOT_DESCRIPTION_MAX_RUNES {
|
||||
return NewAppError("Bot.IsValid", "model.bot.is_valid.description.app_error", b.Trace(), "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if b.OwnerId == "" || utf8.RuneCountInString(b.OwnerId) > BOT_CREATOR_ID_MAX_RUNES {
|
||||
return NewAppError("Bot.IsValid", "model.bot.is_valid.creator_id.app_error", b.Trace(), "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if b.CreateAt == 0 {
|
||||
return NewAppError("Bot.IsValid", "model.bot.is_valid.create_at.app_error", b.Trace(), "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if b.UpdateAt == 0 {
|
||||
return NewAppError("Bot.IsValid", "model.bot.is_valid.update_at.app_error", b.Trace(), "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// PreSave should be run before saving a new bot to the database.
|
||||
func (b *Bot) PreSave() {
|
||||
b.CreateAt = GetMillis()
|
||||
b.UpdateAt = b.CreateAt
|
||||
b.DeleteAt = 0
|
||||
}
|
||||
|
||||
// PreUpdate should be run before saving an updated bot to the database.
|
||||
func (b *Bot) PreUpdate() {
|
||||
b.UpdateAt = GetMillis()
|
||||
}
|
||||
|
||||
// Etag generates an etag for caching.
|
||||
func (b *Bot) Etag() string {
|
||||
return Etag(b.UserId, b.UpdateAt)
|
||||
}
|
||||
|
||||
// ToJson serializes the bot to json.
|
||||
func (b *Bot) ToJson() []byte {
|
||||
data, _ := json.Marshal(b)
|
||||
return data
|
||||
}
|
||||
|
||||
// BotFromJson deserializes a bot from json.
|
||||
func BotFromJson(data io.Reader) *Bot {
|
||||
var bot *Bot
|
||||
json.NewDecoder(data).Decode(&bot)
|
||||
return bot
|
||||
}
|
||||
|
||||
// Patch modifies an existing bot with optional fields from the given patch.
|
||||
// TODO 6.0: consider returning a boolean to indicate whether or not the patch
|
||||
// applied any changes.
|
||||
func (b *Bot) Patch(patch *BotPatch) {
|
||||
if patch.Username != nil {
|
||||
b.Username = *patch.Username
|
||||
}
|
||||
|
||||
if patch.DisplayName != nil {
|
||||
b.DisplayName = *patch.DisplayName
|
||||
}
|
||||
|
||||
if patch.Description != nil {
|
||||
b.Description = *patch.Description
|
||||
}
|
||||
}
|
||||
|
||||
// WouldPatch returns whether or not the given patch would be applied or not.
|
||||
func (b *Bot) WouldPatch(patch *BotPatch) bool {
|
||||
if patch == nil {
|
||||
return false
|
||||
}
|
||||
if patch.Username != nil && *patch.Username != b.Username {
|
||||
return true
|
||||
}
|
||||
if patch.DisplayName != nil && *patch.DisplayName != b.DisplayName {
|
||||
return true
|
||||
}
|
||||
if patch.Description != nil && *patch.Description != b.Description {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// ToJson serializes the bot patch to json.
|
||||
func (b *BotPatch) ToJson() []byte {
|
||||
data, err := json.Marshal(b)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return data
|
||||
}
|
||||
|
||||
// BotPatchFromJson deserializes a bot patch from json.
|
||||
func BotPatchFromJson(data io.Reader) *BotPatch {
|
||||
decoder := json.NewDecoder(data)
|
||||
var botPatch BotPatch
|
||||
err := decoder.Decode(&botPatch)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return &botPatch
|
||||
}
|
||||
|
||||
// UserFromBot returns a user model describing the bot fields stored in the User store.
|
||||
func UserFromBot(b *Bot) *User {
|
||||
return &User{
|
||||
Id: b.UserId,
|
||||
Username: b.Username,
|
||||
Email: NormalizeEmail(fmt.Sprintf("%s@localhost", b.Username)),
|
||||
FirstName: b.DisplayName,
|
||||
Roles: SYSTEM_USER_ROLE_ID,
|
||||
}
|
||||
}
|
||||
|
||||
// BotFromUser returns a bot model given a user model
|
||||
func BotFromUser(u *User) *Bot {
|
||||
return &Bot{
|
||||
OwnerId: u.Id,
|
||||
UserId: u.Id,
|
||||
Username: u.Username,
|
||||
DisplayName: u.GetDisplayName(SHOW_USERNAME),
|
||||
}
|
||||
}
|
||||
|
||||
// BotListFromJson deserializes a list of bots from json.
|
||||
func BotListFromJson(data io.Reader) BotList {
|
||||
var bots BotList
|
||||
json.NewDecoder(data).Decode(&bots)
|
||||
return bots
|
||||
}
|
||||
|
||||
// ToJson serializes a list of bots to json.
|
||||
func (l *BotList) ToJson() []byte {
|
||||
b, _ := json.Marshal(l)
|
||||
return b
|
||||
}
|
||||
|
||||
// Etag computes the etag for a list of bots.
|
||||
func (l *BotList) Etag() string {
|
||||
id := "0"
|
||||
var t int64 = 0
|
||||
var delta int64 = 0
|
||||
|
||||
for _, v := range *l {
|
||||
if v.UpdateAt > t {
|
||||
t = v.UpdateAt
|
||||
id = v.UserId
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return Etag(id, t, delta, len(*l))
|
||||
}
|
||||
|
||||
// MakeBotNotFoundError creates the error returned when a bot does not exist, or when the user isn't allowed to query the bot.
|
||||
// The errors must the same in both cases to avoid leaking that a user is a bot.
|
||||
func MakeBotNotFoundError(userId string) *AppError {
|
||||
return NewAppError("SqlBotStore.Get", "store.sql_bot.get.missing.app_error", map[string]interface{}{"user_id": userId}, "", http.StatusNotFound)
|
||||
}
|
||||
|
||||
func IsBotDMChannel(channel *Channel, botUserID string) bool {
|
||||
if channel.Type != CHANNEL_DIRECT {
|
||||
return false
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(channel.Name, botUserID+"__") && !strings.HasSuffix(channel.Name, "__"+botUserID) {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
9
vendor/github.com/mattermost/mattermost-server/v5/model/builtin.go
generated
vendored
9
vendor/github.com/mattermost/mattermost-server/v5/model/builtin.go
generated
vendored
@ -1,9 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
func NewBool(b bool) *bool { return &b }
|
||||
func NewInt(n int) *int { return &n }
|
||||
func NewInt64(n int64) *int64 { return &n }
|
||||
func NewString(s string) *string { return &s }
|
34
vendor/github.com/mattermost/mattermost-server/v5/model/bundle_info.go
generated
vendored
34
vendor/github.com/mattermost/mattermost-server/v5/model/bundle_info.go
generated
vendored
@ -1,34 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/mattermost/mattermost-server/v5/shared/mlog"
|
||||
)
|
||||
|
||||
type BundleInfo struct {
|
||||
Path string
|
||||
|
||||
Manifest *Manifest
|
||||
ManifestPath string
|
||||
ManifestError error
|
||||
}
|
||||
|
||||
func (b *BundleInfo) WrapLogger(logger *mlog.Logger) *mlog.Logger {
|
||||
if b.Manifest != nil {
|
||||
return logger.With(mlog.String("plugin_id", b.Manifest.Id))
|
||||
}
|
||||
return logger.With(mlog.String("plugin_path", b.Path))
|
||||
}
|
||||
|
||||
// Returns bundle info for the given path. The return value is never nil.
|
||||
func BundleInfoForPath(path string) *BundleInfo {
|
||||
m, mpath, err := FindManifest(path)
|
||||
return &BundleInfo{
|
||||
Path: path,
|
||||
Manifest: m,
|
||||
ManifestPath: mpath,
|
||||
ManifestError: err,
|
||||
}
|
||||
}
|
387
vendor/github.com/mattermost/mattermost-server/v5/model/channel.go
generated
vendored
387
vendor/github.com/mattermost/mattermost-server/v5/model/channel.go
generated
vendored
@ -1,387 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"crypto/sha1"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"sort"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
const (
|
||||
CHANNEL_OPEN = "O"
|
||||
CHANNEL_PRIVATE = "P"
|
||||
CHANNEL_DIRECT = "D"
|
||||
CHANNEL_GROUP = "G"
|
||||
CHANNEL_GROUP_MAX_USERS = 8
|
||||
CHANNEL_GROUP_MIN_USERS = 3
|
||||
DEFAULT_CHANNEL = "town-square"
|
||||
CHANNEL_DISPLAY_NAME_MAX_RUNES = 64
|
||||
CHANNEL_NAME_MIN_LENGTH = 2
|
||||
CHANNEL_NAME_MAX_LENGTH = 64
|
||||
CHANNEL_HEADER_MAX_RUNES = 1024
|
||||
CHANNEL_PURPOSE_MAX_RUNES = 250
|
||||
CHANNEL_CACHE_SIZE = 25000
|
||||
|
||||
CHANNEL_SORT_BY_USERNAME = "username"
|
||||
CHANNEL_SORT_BY_STATUS = "status"
|
||||
)
|
||||
|
||||
type Channel struct {
|
||||
Id string `json:"id"`
|
||||
CreateAt int64 `json:"create_at"`
|
||||
UpdateAt int64 `json:"update_at"`
|
||||
DeleteAt int64 `json:"delete_at"`
|
||||
TeamId string `json:"team_id"`
|
||||
Type string `json:"type"`
|
||||
DisplayName string `json:"display_name"`
|
||||
Name string `json:"name"`
|
||||
Header string `json:"header"`
|
||||
Purpose string `json:"purpose"`
|
||||
LastPostAt int64 `json:"last_post_at"`
|
||||
TotalMsgCount int64 `json:"total_msg_count"`
|
||||
ExtraUpdateAt int64 `json:"extra_update_at"`
|
||||
CreatorId string `json:"creator_id"`
|
||||
SchemeId *string `json:"scheme_id"`
|
||||
Props map[string]interface{} `json:"props" db:"-"`
|
||||
GroupConstrained *bool `json:"group_constrained"`
|
||||
Shared *bool `json:"shared"`
|
||||
TotalMsgCountRoot int64 `json:"total_msg_count_root"`
|
||||
PolicyID *string `json:"policy_id" db:"-"`
|
||||
}
|
||||
|
||||
type ChannelWithTeamData struct {
|
||||
Channel
|
||||
TeamDisplayName string `json:"team_display_name"`
|
||||
TeamName string `json:"team_name"`
|
||||
TeamUpdateAt int64 `json:"team_update_at"`
|
||||
}
|
||||
|
||||
type ChannelsWithCount struct {
|
||||
Channels *ChannelListWithTeamData `json:"channels"`
|
||||
TotalCount int64 `json:"total_count"`
|
||||
}
|
||||
|
||||
type ChannelPatch struct {
|
||||
DisplayName *string `json:"display_name"`
|
||||
Name *string `json:"name"`
|
||||
Header *string `json:"header"`
|
||||
Purpose *string `json:"purpose"`
|
||||
GroupConstrained *bool `json:"group_constrained"`
|
||||
}
|
||||
|
||||
type ChannelForExport struct {
|
||||
Channel
|
||||
TeamName string
|
||||
SchemeName *string
|
||||
}
|
||||
|
||||
type DirectChannelForExport struct {
|
||||
Channel
|
||||
Members *[]string
|
||||
}
|
||||
|
||||
type ChannelModeration struct {
|
||||
Name string `json:"name"`
|
||||
Roles *ChannelModeratedRoles `json:"roles"`
|
||||
}
|
||||
|
||||
type ChannelModeratedRoles struct {
|
||||
Guests *ChannelModeratedRole `json:"guests"`
|
||||
Members *ChannelModeratedRole `json:"members"`
|
||||
}
|
||||
|
||||
type ChannelModeratedRole struct {
|
||||
Value bool `json:"value"`
|
||||
Enabled bool `json:"enabled"`
|
||||
}
|
||||
|
||||
type ChannelModerationPatch struct {
|
||||
Name *string `json:"name"`
|
||||
Roles *ChannelModeratedRolesPatch `json:"roles"`
|
||||
}
|
||||
|
||||
type ChannelModeratedRolesPatch struct {
|
||||
Guests *bool `json:"guests"`
|
||||
Members *bool `json:"members"`
|
||||
}
|
||||
|
||||
// ChannelSearchOpts contains options for searching channels.
|
||||
//
|
||||
// NotAssociatedToGroup will exclude channels that have associated, active GroupChannels records.
|
||||
// ExcludeDefaultChannels will exclude the configured default channels (ex 'town-square' and 'off-topic').
|
||||
// IncludeDeleted will include channel records where DeleteAt != 0.
|
||||
// ExcludeChannelNames will exclude channels from the results by name.
|
||||
// Paginate whether to paginate the results.
|
||||
// Page page requested, if results are paginated.
|
||||
// PerPage number of results per page, if paginated.
|
||||
//
|
||||
type ChannelSearchOpts struct {
|
||||
NotAssociatedToGroup string
|
||||
ExcludeDefaultChannels bool
|
||||
IncludeDeleted bool
|
||||
Deleted bool
|
||||
ExcludeChannelNames []string
|
||||
TeamIds []string
|
||||
GroupConstrained bool
|
||||
ExcludeGroupConstrained bool
|
||||
PolicyID string
|
||||
ExcludePolicyConstrained bool
|
||||
IncludePolicyID bool
|
||||
Public bool
|
||||
Private bool
|
||||
Page *int
|
||||
PerPage *int
|
||||
}
|
||||
|
||||
type ChannelMemberCountByGroup struct {
|
||||
GroupId string `db:"-" json:"group_id"`
|
||||
ChannelMemberCount int64 `db:"-" json:"channel_member_count"`
|
||||
ChannelMemberTimezonesCount int64 `db:"-" json:"channel_member_timezones_count"`
|
||||
}
|
||||
|
||||
type ChannelOption func(channel *Channel)
|
||||
|
||||
func WithID(ID string) ChannelOption {
|
||||
return func(channel *Channel) {
|
||||
channel.Id = ID
|
||||
}
|
||||
}
|
||||
|
||||
func (o *Channel) DeepCopy() *Channel {
|
||||
copy := *o
|
||||
if copy.SchemeId != nil {
|
||||
copy.SchemeId = NewString(*o.SchemeId)
|
||||
}
|
||||
return ©
|
||||
}
|
||||
|
||||
func (o *Channel) ToJson() string {
|
||||
b, _ := json.Marshal(o)
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func (o *ChannelPatch) ToJson() string {
|
||||
b, _ := json.Marshal(o)
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func (o *ChannelsWithCount) ToJson() []byte {
|
||||
b, _ := json.Marshal(o)
|
||||
return b
|
||||
}
|
||||
|
||||
func ChannelsWithCountFromJson(data io.Reader) *ChannelsWithCount {
|
||||
var o *ChannelsWithCount
|
||||
json.NewDecoder(data).Decode(&o)
|
||||
return o
|
||||
}
|
||||
|
||||
func ChannelFromJson(data io.Reader) *Channel {
|
||||
var o *Channel
|
||||
json.NewDecoder(data).Decode(&o)
|
||||
return o
|
||||
}
|
||||
|
||||
func ChannelPatchFromJson(data io.Reader) *ChannelPatch {
|
||||
var o *ChannelPatch
|
||||
json.NewDecoder(data).Decode(&o)
|
||||
return o
|
||||
}
|
||||
|
||||
func ChannelModerationsFromJson(data io.Reader) []*ChannelModeration {
|
||||
var o []*ChannelModeration
|
||||
json.NewDecoder(data).Decode(&o)
|
||||
return o
|
||||
}
|
||||
|
||||
func ChannelModerationsPatchFromJson(data io.Reader) []*ChannelModerationPatch {
|
||||
var o []*ChannelModerationPatch
|
||||
json.NewDecoder(data).Decode(&o)
|
||||
return o
|
||||
}
|
||||
|
||||
func ChannelMemberCountsByGroupFromJson(data io.Reader) []*ChannelMemberCountByGroup {
|
||||
var o []*ChannelMemberCountByGroup
|
||||
json.NewDecoder(data).Decode(&o)
|
||||
return o
|
||||
}
|
||||
|
||||
func (o *Channel) Etag() string {
|
||||
return Etag(o.Id, o.UpdateAt)
|
||||
}
|
||||
|
||||
func (o *Channel) IsValid() *AppError {
|
||||
if !IsValidId(o.Id) {
|
||||
return NewAppError("Channel.IsValid", "model.channel.is_valid.id.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if o.CreateAt == 0 {
|
||||
return NewAppError("Channel.IsValid", "model.channel.is_valid.create_at.app_error", nil, "id="+o.Id, http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if o.UpdateAt == 0 {
|
||||
return NewAppError("Channel.IsValid", "model.channel.is_valid.update_at.app_error", nil, "id="+o.Id, http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if utf8.RuneCountInString(o.DisplayName) > CHANNEL_DISPLAY_NAME_MAX_RUNES {
|
||||
return NewAppError("Channel.IsValid", "model.channel.is_valid.display_name.app_error", nil, "id="+o.Id, http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if !IsValidChannelIdentifier(o.Name) {
|
||||
return NewAppError("Channel.IsValid", "model.channel.is_valid.2_or_more.app_error", nil, "id="+o.Id, http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if !(o.Type == CHANNEL_OPEN || o.Type == CHANNEL_PRIVATE || o.Type == CHANNEL_DIRECT || o.Type == CHANNEL_GROUP) {
|
||||
return NewAppError("Channel.IsValid", "model.channel.is_valid.type.app_error", nil, "id="+o.Id, http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if utf8.RuneCountInString(o.Header) > CHANNEL_HEADER_MAX_RUNES {
|
||||
return NewAppError("Channel.IsValid", "model.channel.is_valid.header.app_error", nil, "id="+o.Id, http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if utf8.RuneCountInString(o.Purpose) > CHANNEL_PURPOSE_MAX_RUNES {
|
||||
return NewAppError("Channel.IsValid", "model.channel.is_valid.purpose.app_error", nil, "id="+o.Id, http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if len(o.CreatorId) > 26 {
|
||||
return NewAppError("Channel.IsValid", "model.channel.is_valid.creator_id.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
userIds := strings.Split(o.Name, "__")
|
||||
if o.Type != CHANNEL_DIRECT && len(userIds) == 2 && IsValidId(userIds[0]) && IsValidId(userIds[1]) {
|
||||
return NewAppError("Channel.IsValid", "model.channel.is_valid.name.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *Channel) PreSave() {
|
||||
if o.Id == "" {
|
||||
o.Id = NewId()
|
||||
}
|
||||
|
||||
o.Name = SanitizeUnicode(o.Name)
|
||||
o.DisplayName = SanitizeUnicode(o.DisplayName)
|
||||
|
||||
o.CreateAt = GetMillis()
|
||||
o.UpdateAt = o.CreateAt
|
||||
o.ExtraUpdateAt = 0
|
||||
}
|
||||
|
||||
func (o *Channel) PreUpdate() {
|
||||
o.UpdateAt = GetMillis()
|
||||
o.Name = SanitizeUnicode(o.Name)
|
||||
o.DisplayName = SanitizeUnicode(o.DisplayName)
|
||||
}
|
||||
|
||||
func (o *Channel) IsGroupOrDirect() bool {
|
||||
return o.Type == CHANNEL_DIRECT || o.Type == CHANNEL_GROUP
|
||||
}
|
||||
|
||||
func (o *Channel) IsOpen() bool {
|
||||
return o.Type == CHANNEL_OPEN
|
||||
}
|
||||
|
||||
func (o *Channel) Patch(patch *ChannelPatch) {
|
||||
if patch.DisplayName != nil {
|
||||
o.DisplayName = *patch.DisplayName
|
||||
}
|
||||
|
||||
if patch.Name != nil {
|
||||
o.Name = *patch.Name
|
||||
}
|
||||
|
||||
if patch.Header != nil {
|
||||
o.Header = *patch.Header
|
||||
}
|
||||
|
||||
if patch.Purpose != nil {
|
||||
o.Purpose = *patch.Purpose
|
||||
}
|
||||
|
||||
if patch.GroupConstrained != nil {
|
||||
o.GroupConstrained = patch.GroupConstrained
|
||||
}
|
||||
}
|
||||
|
||||
func (o *Channel) MakeNonNil() {
|
||||
if o.Props == nil {
|
||||
o.Props = make(map[string]interface{})
|
||||
}
|
||||
}
|
||||
|
||||
func (o *Channel) AddProp(key string, value interface{}) {
|
||||
o.MakeNonNil()
|
||||
|
||||
o.Props[key] = value
|
||||
}
|
||||
|
||||
func (o *Channel) IsGroupConstrained() bool {
|
||||
return o.GroupConstrained != nil && *o.GroupConstrained
|
||||
}
|
||||
|
||||
func (o *Channel) IsShared() bool {
|
||||
return o.Shared != nil && *o.Shared
|
||||
}
|
||||
|
||||
func (o *Channel) GetOtherUserIdForDM(userId string) string {
|
||||
if o.Type != CHANNEL_DIRECT {
|
||||
return ""
|
||||
}
|
||||
|
||||
userIds := strings.Split(o.Name, "__")
|
||||
|
||||
var otherUserId string
|
||||
|
||||
if userIds[0] != userIds[1] {
|
||||
if userIds[0] == userId {
|
||||
otherUserId = userIds[1]
|
||||
} else {
|
||||
otherUserId = userIds[0]
|
||||
}
|
||||
}
|
||||
|
||||
return otherUserId
|
||||
}
|
||||
|
||||
func GetDMNameFromIds(userId1, userId2 string) string {
|
||||
if userId1 > userId2 {
|
||||
return userId2 + "__" + userId1
|
||||
}
|
||||
return userId1 + "__" + userId2
|
||||
}
|
||||
|
||||
func GetGroupDisplayNameFromUsers(users []*User, truncate bool) string {
|
||||
usernames := make([]string, len(users))
|
||||
for index, user := range users {
|
||||
usernames[index] = user.Username
|
||||
}
|
||||
|
||||
sort.Strings(usernames)
|
||||
|
||||
name := strings.Join(usernames, ", ")
|
||||
|
||||
if truncate && len(name) > CHANNEL_NAME_MAX_LENGTH {
|
||||
name = name[:CHANNEL_NAME_MAX_LENGTH]
|
||||
}
|
||||
|
||||
return name
|
||||
}
|
||||
|
||||
func GetGroupNameFromUserIds(userIds []string) string {
|
||||
sort.Strings(userIds)
|
||||
|
||||
h := sha1.New()
|
||||
for _, id := range userIds {
|
||||
io.WriteString(h, id)
|
||||
}
|
||||
|
||||
return hex.EncodeToString(h.Sum(nil))
|
||||
}
|
55
vendor/github.com/mattermost/mattermost-server/v5/model/channel_count.go
generated
vendored
55
vendor/github.com/mattermost/mattermost-server/v5/model/channel_count.go
generated
vendored
@ -1,55 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"sort"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type ChannelCounts struct {
|
||||
Counts map[string]int64 `json:"counts"`
|
||||
CountsRoot map[string]int64 `json:"counts_root"`
|
||||
UpdateTimes map[string]int64 `json:"update_times"`
|
||||
}
|
||||
|
||||
func (o *ChannelCounts) Etag() string {
|
||||
// we don't include CountsRoot in ETag calculation, since it's a deriviative
|
||||
ids := []string{}
|
||||
for id := range o.Counts {
|
||||
ids = append(ids, id)
|
||||
}
|
||||
sort.Strings(ids)
|
||||
|
||||
str := ""
|
||||
for _, id := range ids {
|
||||
str += id + strconv.FormatInt(o.Counts[id], 10)
|
||||
}
|
||||
|
||||
md5Counts := fmt.Sprintf("%x", md5.Sum([]byte(str)))
|
||||
|
||||
var update int64 = 0
|
||||
for _, u := range o.UpdateTimes {
|
||||
if u > update {
|
||||
update = u
|
||||
}
|
||||
}
|
||||
|
||||
return Etag(md5Counts, update)
|
||||
}
|
||||
|
||||
func (o *ChannelCounts) ToJson() string {
|
||||
b, _ := json.Marshal(o)
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func ChannelCountsFromJson(data io.Reader) *ChannelCounts {
|
||||
var o *ChannelCounts
|
||||
json.NewDecoder(data).Decode(&o)
|
||||
return o
|
||||
}
|
34
vendor/github.com/mattermost/mattermost-server/v5/model/channel_data.go
generated
vendored
34
vendor/github.com/mattermost/mattermost-server/v5/model/channel_data.go
generated
vendored
@ -1,34 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
)
|
||||
|
||||
type ChannelData struct {
|
||||
Channel *Channel `json:"channel"`
|
||||
Member *ChannelMember `json:"member"`
|
||||
}
|
||||
|
||||
func (o *ChannelData) Etag() string {
|
||||
var mt int64 = 0
|
||||
if o.Member != nil {
|
||||
mt = o.Member.LastUpdateAt
|
||||
}
|
||||
|
||||
return Etag(o.Channel.Id, o.Channel.UpdateAt, o.Channel.LastPostAt, mt)
|
||||
}
|
||||
|
||||
func (o *ChannelData) ToJson() string {
|
||||
b, _ := json.Marshal(o)
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func ChannelDataFromJson(data io.Reader) *ChannelData {
|
||||
var o *ChannelData
|
||||
json.NewDecoder(data).Decode(&o)
|
||||
return o
|
||||
}
|
95
vendor/github.com/mattermost/mattermost-server/v5/model/channel_list.go
generated
vendored
95
vendor/github.com/mattermost/mattermost-server/v5/model/channel_list.go
generated
vendored
@ -1,95 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
)
|
||||
|
||||
type ChannelList []*Channel
|
||||
|
||||
func (o *ChannelList) ToJson() string {
|
||||
b, err := json.Marshal(o)
|
||||
if err != nil {
|
||||
return "[]"
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func (o *ChannelList) Etag() string {
|
||||
|
||||
id := "0"
|
||||
var t int64 = 0
|
||||
var delta int64 = 0
|
||||
|
||||
for _, v := range *o {
|
||||
if v.LastPostAt > t {
|
||||
t = v.LastPostAt
|
||||
id = v.Id
|
||||
}
|
||||
|
||||
if v.UpdateAt > t {
|
||||
t = v.UpdateAt
|
||||
id = v.Id
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return Etag(id, t, delta, len(*o))
|
||||
}
|
||||
|
||||
func ChannelListFromJson(data io.Reader) *ChannelList {
|
||||
var o *ChannelList
|
||||
json.NewDecoder(data).Decode(&o)
|
||||
return o
|
||||
}
|
||||
|
||||
func ChannelSliceFromJson(data io.Reader) []*Channel {
|
||||
var o []*Channel
|
||||
json.NewDecoder(data).Decode(&o)
|
||||
return o
|
||||
}
|
||||
|
||||
type ChannelListWithTeamData []*ChannelWithTeamData
|
||||
|
||||
func (o *ChannelListWithTeamData) ToJson() string {
|
||||
b, err := json.Marshal(o)
|
||||
if err != nil {
|
||||
return "[]"
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func (o *ChannelListWithTeamData) Etag() string {
|
||||
|
||||
id := "0"
|
||||
var t int64 = 0
|
||||
var delta int64 = 0
|
||||
|
||||
for _, v := range *o {
|
||||
if v.LastPostAt > t {
|
||||
t = v.LastPostAt
|
||||
id = v.Id
|
||||
}
|
||||
|
||||
if v.UpdateAt > t {
|
||||
t = v.UpdateAt
|
||||
id = v.Id
|
||||
}
|
||||
|
||||
if v.TeamUpdateAt > t {
|
||||
t = v.TeamUpdateAt
|
||||
id = v.Id
|
||||
}
|
||||
}
|
||||
|
||||
return Etag(id, t, delta, len(*o))
|
||||
}
|
||||
|
||||
func ChannelListWithTeamDataFromJson(data io.Reader) *ChannelListWithTeamData {
|
||||
var o *ChannelListWithTeamData
|
||||
json.NewDecoder(data).Decode(&o)
|
||||
return o
|
||||
}
|
212
vendor/github.com/mattermost/mattermost-server/v5/model/channel_member.go
generated
vendored
212
vendor/github.com/mattermost/mattermost-server/v5/model/channel_member.go
generated
vendored
@ -1,212 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
CHANNEL_NOTIFY_DEFAULT = "default"
|
||||
CHANNEL_NOTIFY_ALL = "all"
|
||||
CHANNEL_NOTIFY_MENTION = "mention"
|
||||
CHANNEL_NOTIFY_NONE = "none"
|
||||
CHANNEL_MARK_UNREAD_ALL = "all"
|
||||
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 {
|
||||
TeamId string `json:"team_id"`
|
||||
ChannelId string `json:"channel_id"`
|
||||
MsgCount int64 `json:"msg_count"`
|
||||
MentionCount int64 `json:"mention_count"`
|
||||
MentionCountRoot int64 `json:"mention_count_root"`
|
||||
MsgCountRoot int64 `json:"msg_count_root"`
|
||||
NotifyProps StringMap `json:"-"`
|
||||
}
|
||||
|
||||
type ChannelUnreadAt struct {
|
||||
TeamId string `json:"team_id"`
|
||||
UserId string `json:"user_id"`
|
||||
ChannelId string `json:"channel_id"`
|
||||
MsgCount int64 `json:"msg_count"`
|
||||
MentionCount int64 `json:"mention_count"`
|
||||
MentionCountRoot int64 `json:"mention_count_root"`
|
||||
MsgCountRoot int64 `json:"msg_count_root"`
|
||||
LastViewedAt int64 `json:"last_viewed_at"`
|
||||
NotifyProps StringMap `json:"-"`
|
||||
}
|
||||
|
||||
type ChannelMember struct {
|
||||
ChannelId string `json:"channel_id"`
|
||||
UserId string `json:"user_id"`
|
||||
Roles string `json:"roles"`
|
||||
LastViewedAt int64 `json:"last_viewed_at"`
|
||||
MsgCount int64 `json:"msg_count"`
|
||||
MentionCount int64 `json:"mention_count"`
|
||||
MentionCountRoot int64 `json:"mention_count_root"`
|
||||
MsgCountRoot int64 `json:"msg_count_root"`
|
||||
NotifyProps StringMap `json:"notify_props"`
|
||||
LastUpdateAt int64 `json:"last_update_at"`
|
||||
SchemeGuest bool `json:"scheme_guest"`
|
||||
SchemeUser bool `json:"scheme_user"`
|
||||
SchemeAdmin bool `json:"scheme_admin"`
|
||||
ExplicitRoles string `json:"explicit_roles"`
|
||||
}
|
||||
|
||||
type ChannelMembers []ChannelMember
|
||||
|
||||
type ChannelMemberForExport struct {
|
||||
ChannelMember
|
||||
ChannelName string
|
||||
Username string
|
||||
}
|
||||
|
||||
func (o *ChannelMembers) ToJson() string {
|
||||
b, err := json.Marshal(o)
|
||||
if err != nil {
|
||||
return "[]"
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func (o *ChannelUnread) ToJson() string {
|
||||
b, _ := json.Marshal(o)
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func (o *ChannelUnreadAt) ToJson() string {
|
||||
b, _ := json.Marshal(o)
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func ChannelMembersFromJson(data io.Reader) *ChannelMembers {
|
||||
var o *ChannelMembers
|
||||
json.NewDecoder(data).Decode(&o)
|
||||
return o
|
||||
}
|
||||
|
||||
func ChannelUnreadFromJson(data io.Reader) *ChannelUnread {
|
||||
var o *ChannelUnread
|
||||
json.NewDecoder(data).Decode(&o)
|
||||
return o
|
||||
}
|
||||
|
||||
func ChannelUnreadAtFromJson(data io.Reader) *ChannelUnreadAt {
|
||||
var o *ChannelUnreadAt
|
||||
json.NewDecoder(data).Decode(&o)
|
||||
return o
|
||||
}
|
||||
|
||||
func (o *ChannelMember) ToJson() string {
|
||||
b, _ := json.Marshal(o)
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func ChannelMemberFromJson(data io.Reader) *ChannelMember {
|
||||
var o *ChannelMember
|
||||
json.NewDecoder(data).Decode(&o)
|
||||
return o
|
||||
}
|
||||
|
||||
func (o *ChannelMember) IsValid() *AppError {
|
||||
|
||||
if !IsValidId(o.ChannelId) {
|
||||
return NewAppError("ChannelMember.IsValid", "model.channel_member.is_valid.channel_id.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if !IsValidId(o.UserId) {
|
||||
return NewAppError("ChannelMember.IsValid", "model.channel_member.is_valid.user_id.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
notifyLevel := o.NotifyProps[DESKTOP_NOTIFY_PROP]
|
||||
if len(notifyLevel) > 20 || !IsChannelNotifyLevelValid(notifyLevel) {
|
||||
return NewAppError("ChannelMember.IsValid", "model.channel_member.is_valid.notify_level.app_error", nil, "notify_level="+notifyLevel, http.StatusBadRequest)
|
||||
}
|
||||
|
||||
markUnreadLevel := o.NotifyProps[MARK_UNREAD_NOTIFY_PROP]
|
||||
if len(markUnreadLevel) > 20 || !IsChannelMarkUnreadLevelValid(markUnreadLevel) {
|
||||
return NewAppError("ChannelMember.IsValid", "model.channel_member.is_valid.unread_level.app_error", nil, "mark_unread_level="+markUnreadLevel, http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if pushLevel, ok := o.NotifyProps[PUSH_NOTIFY_PROP]; ok {
|
||||
if len(pushLevel) > 20 || !IsChannelNotifyLevelValid(pushLevel) {
|
||||
return NewAppError("ChannelMember.IsValid", "model.channel_member.is_valid.push_level.app_error", nil, "push_notification_level="+pushLevel, http.StatusBadRequest)
|
||||
}
|
||||
}
|
||||
|
||||
if sendEmail, ok := o.NotifyProps[EMAIL_NOTIFY_PROP]; ok {
|
||||
if len(sendEmail) > 20 || !IsSendEmailValid(sendEmail) {
|
||||
return NewAppError("ChannelMember.IsValid", "model.channel_member.is_valid.email_value.app_error", nil, "push_notification_level="+sendEmail, http.StatusBadRequest)
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
func (o *ChannelMember) PreSave() {
|
||||
o.LastUpdateAt = GetMillis()
|
||||
}
|
||||
|
||||
func (o *ChannelMember) PreUpdate() {
|
||||
o.LastUpdateAt = GetMillis()
|
||||
}
|
||||
|
||||
func (o *ChannelMember) GetRoles() []string {
|
||||
return strings.Fields(o.Roles)
|
||||
}
|
||||
|
||||
func (o *ChannelMember) SetChannelMuted(muted bool) {
|
||||
if o.IsChannelMuted() {
|
||||
o.NotifyProps[MARK_UNREAD_NOTIFY_PROP] = CHANNEL_MARK_UNREAD_ALL
|
||||
} else {
|
||||
o.NotifyProps[MARK_UNREAD_NOTIFY_PROP] = CHANNEL_MARK_UNREAD_MENTION
|
||||
}
|
||||
}
|
||||
|
||||
func (o *ChannelMember) IsChannelMuted() bool {
|
||||
return o.NotifyProps[MARK_UNREAD_NOTIFY_PROP] == CHANNEL_MARK_UNREAD_MENTION
|
||||
}
|
||||
|
||||
func IsChannelNotifyLevelValid(notifyLevel string) bool {
|
||||
return notifyLevel == CHANNEL_NOTIFY_DEFAULT ||
|
||||
notifyLevel == CHANNEL_NOTIFY_ALL ||
|
||||
notifyLevel == CHANNEL_NOTIFY_MENTION ||
|
||||
notifyLevel == CHANNEL_NOTIFY_NONE
|
||||
}
|
||||
|
||||
func IsChannelMarkUnreadLevelValid(markUnreadLevel string) bool {
|
||||
return markUnreadLevel == CHANNEL_MARK_UNREAD_ALL || markUnreadLevel == CHANNEL_MARK_UNREAD_MENTION
|
||||
}
|
||||
|
||||
func IsSendEmailValid(sendEmail string) bool {
|
||||
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 {
|
||||
return StringMap{
|
||||
DESKTOP_NOTIFY_PROP: CHANNEL_NOTIFY_DEFAULT,
|
||||
MARK_UNREAD_NOTIFY_PROP: CHANNEL_MARK_UNREAD_ALL,
|
||||
PUSH_NOTIFY_PROP: CHANNEL_NOTIFY_DEFAULT,
|
||||
EMAIL_NOTIFY_PROP: CHANNEL_NOTIFY_DEFAULT,
|
||||
IGNORE_CHANNEL_MENTIONS_NOTIFY_PROP: IGNORE_CHANNEL_MENTIONS_DEFAULT,
|
||||
}
|
||||
}
|
11
vendor/github.com/mattermost/mattermost-server/v5/model/channel_member_history.go
generated
vendored
11
vendor/github.com/mattermost/mattermost-server/v5/model/channel_member_history.go
generated
vendored
@ -1,11 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
type ChannelMemberHistory struct {
|
||||
ChannelId string
|
||||
UserId string
|
||||
JoinTime int64
|
||||
LeaveTime *int64
|
||||
}
|
17
vendor/github.com/mattermost/mattermost-server/v5/model/channel_member_history_result.go
generated
vendored
17
vendor/github.com/mattermost/mattermost-server/v5/model/channel_member_history_result.go
generated
vendored
@ -1,17 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
type ChannelMemberHistoryResult struct {
|
||||
ChannelId string
|
||||
UserId string
|
||||
JoinTime int64
|
||||
LeaveTime *int64
|
||||
|
||||
// these two fields are never set in the database - when we SELECT, we join on Users to get them
|
||||
UserEmail string `db:"Email"`
|
||||
Username string
|
||||
IsBot bool
|
||||
UserDeleteAt int64
|
||||
}
|
28
vendor/github.com/mattermost/mattermost-server/v5/model/channel_mentions.go
generated
vendored
28
vendor/github.com/mattermost/mattermost-server/v5/model/channel_mentions.go
generated
vendored
@ -1,28 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var channelMentionRegexp = regexp.MustCompile(`\B~[a-zA-Z0-9\-_]+`)
|
||||
|
||||
func ChannelMentions(message string) []string {
|
||||
var names []string
|
||||
|
||||
if strings.Contains(message, "~") {
|
||||
alreadyMentioned := make(map[string]bool)
|
||||
for _, match := range channelMentionRegexp.FindAllString(message, -1) {
|
||||
name := match[1:]
|
||||
if !alreadyMentioned[name] {
|
||||
names = append(names, name)
|
||||
alreadyMentioned[name] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return names
|
||||
}
|
40
vendor/github.com/mattermost/mattermost-server/v5/model/channel_search.go
generated
vendored
40
vendor/github.com/mattermost/mattermost-server/v5/model/channel_search.go
generated
vendored
@ -1,40 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
)
|
||||
|
||||
const CHANNEL_SEARCH_DEFAULT_LIMIT = 50
|
||||
|
||||
type ChannelSearch struct {
|
||||
Term string `json:"term"`
|
||||
ExcludeDefaultChannels bool `json:"exclude_default_channels"`
|
||||
NotAssociatedToGroup string `json:"not_associated_to_group"`
|
||||
TeamIds []string `json:"team_ids"`
|
||||
GroupConstrained bool `json:"group_constrained"`
|
||||
ExcludeGroupConstrained bool `json:"exclude_group_constrained"`
|
||||
ExcludePolicyConstrained bool `json:"exclude_policy_constrained"`
|
||||
Public bool `json:"public"`
|
||||
Private bool `json:"private"`
|
||||
IncludeDeleted bool `json:"include_deleted"`
|
||||
Deleted bool `json:"deleted"`
|
||||
Page *int `json:"page,omitempty"`
|
||||
PerPage *int `json:"per_page,omitempty"`
|
||||
}
|
||||
|
||||
// ToJson convert a Channel to a json string
|
||||
func (c *ChannelSearch) ToJson() string {
|
||||
b, _ := json.Marshal(c)
|
||||
return string(b)
|
||||
}
|
||||
|
||||
// ChannelSearchFromJson will decode the input and return a Channel
|
||||
func ChannelSearchFromJson(data io.Reader) *ChannelSearch {
|
||||
var cs *ChannelSearch
|
||||
json.NewDecoder(data).Decode(&cs)
|
||||
return cs
|
||||
}
|
126
vendor/github.com/mattermost/mattermost-server/v5/model/channel_sidebar.go
generated
vendored
126
vendor/github.com/mattermost/mattermost-server/v5/model/channel_sidebar.go
generated
vendored
@ -1,126 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
type SidebarCategoryType string
|
||||
type SidebarCategorySorting string
|
||||
|
||||
const (
|
||||
// Each sidebar category has a 'type'. System categories are Channels, Favorites and DMs
|
||||
// All user-created categories will have type Custom
|
||||
SidebarCategoryChannels SidebarCategoryType = "channels"
|
||||
SidebarCategoryDirectMessages SidebarCategoryType = "direct_messages"
|
||||
SidebarCategoryFavorites SidebarCategoryType = "favorites"
|
||||
SidebarCategoryCustom SidebarCategoryType = "custom"
|
||||
// Increment to use when adding/reordering things in the sidebar
|
||||
MinimalSidebarSortDistance = 10
|
||||
// Default Sort Orders for categories
|
||||
DefaultSidebarSortOrderFavorites = 0
|
||||
DefaultSidebarSortOrderChannels = DefaultSidebarSortOrderFavorites + MinimalSidebarSortDistance
|
||||
DefaultSidebarSortOrderDMs = DefaultSidebarSortOrderChannels + MinimalSidebarSortDistance
|
||||
// Sorting modes
|
||||
// default for all categories except DMs (behaves like manual)
|
||||
SidebarCategorySortDefault SidebarCategorySorting = ""
|
||||
// sort manually
|
||||
SidebarCategorySortManual SidebarCategorySorting = "manual"
|
||||
// sort by recency (default for DMs)
|
||||
SidebarCategorySortRecent SidebarCategorySorting = "recent"
|
||||
// sort by display name alphabetically
|
||||
SidebarCategorySortAlphabetical SidebarCategorySorting = "alpha"
|
||||
)
|
||||
|
||||
// SidebarCategory represents the corresponding DB table
|
||||
// SortOrder is never returned to the user and only used for queries
|
||||
type SidebarCategory struct {
|
||||
Id string `json:"id"`
|
||||
UserId string `json:"user_id"`
|
||||
TeamId string `json:"team_id"`
|
||||
SortOrder int64 `json:"-"`
|
||||
Sorting SidebarCategorySorting `json:"sorting"`
|
||||
Type SidebarCategoryType `json:"type"`
|
||||
DisplayName string `json:"display_name"`
|
||||
Muted bool `json:"muted"`
|
||||
Collapsed bool `json:"collapsed"`
|
||||
}
|
||||
|
||||
// SidebarCategoryWithChannels combines data from SidebarCategory table with the Channel IDs that belong to that category
|
||||
type SidebarCategoryWithChannels struct {
|
||||
SidebarCategory
|
||||
Channels []string `json:"channel_ids"`
|
||||
}
|
||||
|
||||
type SidebarCategoryOrder []string
|
||||
|
||||
// OrderedSidebarCategories combines categories, their channel IDs and an array of Category IDs, sorted
|
||||
type OrderedSidebarCategories struct {
|
||||
Categories SidebarCategoriesWithChannels `json:"categories"`
|
||||
Order SidebarCategoryOrder `json:"order"`
|
||||
}
|
||||
|
||||
type SidebarChannel struct {
|
||||
ChannelId string `json:"channel_id"`
|
||||
UserId string `json:"user_id"`
|
||||
CategoryId string `json:"category_id"`
|
||||
SortOrder int64 `json:"-"`
|
||||
}
|
||||
|
||||
type SidebarChannels []*SidebarChannel
|
||||
type SidebarCategoriesWithChannels []*SidebarCategoryWithChannels
|
||||
|
||||
func SidebarCategoryFromJson(data io.Reader) (*SidebarCategoryWithChannels, error) {
|
||||
var o *SidebarCategoryWithChannels
|
||||
err := json.NewDecoder(data).Decode(&o)
|
||||
return o, err
|
||||
}
|
||||
|
||||
func SidebarCategoriesFromJson(data io.Reader) ([]*SidebarCategoryWithChannels, error) {
|
||||
var o []*SidebarCategoryWithChannels
|
||||
err := json.NewDecoder(data).Decode(&o)
|
||||
return o, err
|
||||
}
|
||||
|
||||
func OrderedSidebarCategoriesFromJson(data io.Reader) (*OrderedSidebarCategories, error) {
|
||||
var o *OrderedSidebarCategories
|
||||
err := json.NewDecoder(data).Decode(&o)
|
||||
return o, err
|
||||
}
|
||||
|
||||
func (o SidebarCategoryWithChannels) ToJson() []byte {
|
||||
b, _ := json.Marshal(o)
|
||||
return b
|
||||
}
|
||||
|
||||
func SidebarCategoriesWithChannelsToJson(o []*SidebarCategoryWithChannels) []byte {
|
||||
b, err := json.Marshal(o)
|
||||
if err != nil {
|
||||
return []byte("[]")
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func (o OrderedSidebarCategories) ToJson() []byte {
|
||||
b, err := json.Marshal(o)
|
||||
if err != nil {
|
||||
return []byte("[]")
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
var categoryIdPattern = regexp.MustCompile("(favorites|channels|direct_messages)_[a-z0-9]{26}_[a-z0-9]{26}")
|
||||
|
||||
func IsValidCategoryId(s string) bool {
|
||||
// Category IDs can either be regular IDs
|
||||
if IsValidId(s) {
|
||||
return true
|
||||
}
|
||||
|
||||
// Or default categories can follow the pattern {type}_{userID}_{teamID}
|
||||
return categoryIdPattern.MatchString(s)
|
||||
}
|
27
vendor/github.com/mattermost/mattermost-server/v5/model/channel_stats.go
generated
vendored
27
vendor/github.com/mattermost/mattermost-server/v5/model/channel_stats.go
generated
vendored
@ -1,27 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
)
|
||||
|
||||
type ChannelStats struct {
|
||||
ChannelId string `json:"channel_id"`
|
||||
MemberCount int64 `json:"member_count"`
|
||||
GuestCount int64 `json:"guest_count"`
|
||||
PinnedPostCount int64 `json:"pinnedpost_count"`
|
||||
}
|
||||
|
||||
func (o *ChannelStats) ToJson() string {
|
||||
b, _ := json.Marshal(o)
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func ChannelStatsFromJson(data io.Reader) *ChannelStats {
|
||||
var o *ChannelStats
|
||||
json.NewDecoder(data).Decode(&o)
|
||||
return o
|
||||
}
|
42
vendor/github.com/mattermost/mattermost-server/v5/model/channel_view.go
generated
vendored
42
vendor/github.com/mattermost/mattermost-server/v5/model/channel_view.go
generated
vendored
@ -1,42 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
)
|
||||
|
||||
type ChannelView struct {
|
||||
ChannelId string `json:"channel_id"`
|
||||
PrevChannelId string `json:"prev_channel_id"`
|
||||
CollapsedThreadsSupported bool `json:"collapsed_threads_supported"`
|
||||
}
|
||||
|
||||
func (o *ChannelView) ToJson() string {
|
||||
b, _ := json.Marshal(o)
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func ChannelViewFromJson(data io.Reader) *ChannelView {
|
||||
var o *ChannelView
|
||||
json.NewDecoder(data).Decode(&o)
|
||||
return o
|
||||
}
|
||||
|
||||
type ChannelViewResponse struct {
|
||||
Status string `json:"status"`
|
||||
LastViewedAtTimes map[string]int64 `json:"last_viewed_at_times"`
|
||||
}
|
||||
|
||||
func (o *ChannelViewResponse) ToJson() string {
|
||||
b, _ := json.Marshal(o)
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func ChannelViewResponseFromJson(data io.Reader) *ChannelViewResponse {
|
||||
var o *ChannelViewResponse
|
||||
json.NewDecoder(data).Decode(&o)
|
||||
return o
|
||||
}
|
6343
vendor/github.com/mattermost/mattermost-server/v5/model/client4.go
generated
vendored
6343
vendor/github.com/mattermost/mattermost-server/v5/model/client4.go
generated
vendored
File diff suppressed because it is too large
Load Diff
188
vendor/github.com/mattermost/mattermost-server/v5/model/cloud.go
generated
vendored
188
vendor/github.com/mattermost/mattermost-server/v5/model/cloud.go
generated
vendored
@ -1,188 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import "strings"
|
||||
|
||||
const (
|
||||
EventTypeFailedPayment = "failed-payment"
|
||||
EventTypeFailedPaymentNoCard = "failed-payment-no-card"
|
||||
EventTypeSendAdminWelcomeEmail = "send-admin-welcome-email"
|
||||
EventTypeTrialWillEnd = "trial-will-end"
|
||||
EventTypeTrialEnded = "trial-ended"
|
||||
JoinLimitation = "join"
|
||||
InviteLimitation = "invite"
|
||||
)
|
||||
|
||||
var MockCWS string
|
||||
|
||||
type BillingScheme string
|
||||
|
||||
const (
|
||||
BillingSchemePerSeat = BillingScheme("per_seat")
|
||||
BillingSchemeFlatFee = BillingScheme("flat_fee")
|
||||
)
|
||||
|
||||
type RecurringInterval string
|
||||
|
||||
const (
|
||||
RecurringIntervalYearly = RecurringInterval("year")
|
||||
RecurringIntervalMonthly = RecurringInterval("month")
|
||||
)
|
||||
|
||||
type SubscriptionFamily string
|
||||
|
||||
const (
|
||||
SubscriptionFamilyCloud = SubscriptionFamily("cloud")
|
||||
SubscriptionFamilyOnPrem = SubscriptionFamily("on-prem")
|
||||
)
|
||||
|
||||
// Product model represents a product on the cloud system.
|
||||
type Product struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
PricePerSeat float64 `json:"price_per_seat"`
|
||||
AddOns []*AddOn `json:"add_ons"`
|
||||
SKU string `json:"sku"`
|
||||
PriceID string `json:"price_id"`
|
||||
Family SubscriptionFamily `json:"product_family"`
|
||||
RecurringInterval RecurringInterval `json:"recurring_interval"`
|
||||
BillingScheme BillingScheme `json:"billing_scheme"`
|
||||
}
|
||||
|
||||
// AddOn represents an addon to a product.
|
||||
type AddOn struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
DisplayName string `json:"display_name"`
|
||||
PricePerSeat float64 `json:"price_per_seat"`
|
||||
}
|
||||
|
||||
// StripeSetupIntent represents the SetupIntent model from Stripe for updating payment methods.
|
||||
type StripeSetupIntent struct {
|
||||
ID string `json:"id"`
|
||||
ClientSecret string `json:"client_secret"`
|
||||
}
|
||||
|
||||
// ConfirmPaymentMethodRequest contains the fields for the customer payment update API.
|
||||
type ConfirmPaymentMethodRequest struct {
|
||||
StripeSetupIntentID string `json:"stripe_setup_intent_id"`
|
||||
}
|
||||
|
||||
// Customer model represents a customer on the system.
|
||||
type CloudCustomer struct {
|
||||
CloudCustomerInfo
|
||||
ID string `json:"id"`
|
||||
CreatorID string `json:"creator_id"`
|
||||
CreateAt int64 `json:"create_at"`
|
||||
BillingAddress *Address `json:"billing_address"`
|
||||
CompanyAddress *Address `json:"company_address"`
|
||||
PaymentMethod *PaymentMethod `json:"payment_method"`
|
||||
}
|
||||
|
||||
// CloudCustomerInfo represents editable info of a customer.
|
||||
type CloudCustomerInfo struct {
|
||||
Name string `json:"name"`
|
||||
Email string `json:"email,omitempty"`
|
||||
ContactFirstName string `json:"contact_first_name,omitempty"`
|
||||
ContactLastName string `json:"contact_last_name,omitempty"`
|
||||
NumEmployees int `json:"num_employees"`
|
||||
}
|
||||
|
||||
// Address model represents a customer's address.
|
||||
type Address struct {
|
||||
City string `json:"city"`
|
||||
Country string `json:"country"`
|
||||
Line1 string `json:"line1"`
|
||||
Line2 string `json:"line2"`
|
||||
PostalCode string `json:"postal_code"`
|
||||
State string `json:"state"`
|
||||
}
|
||||
|
||||
// PaymentMethod represents methods of payment for a customer.
|
||||
type PaymentMethod struct {
|
||||
Type string `json:"type"`
|
||||
LastFour int `json:"last_four"`
|
||||
ExpMonth int `json:"exp_month"`
|
||||
ExpYear int `json:"exp_year"`
|
||||
CardBrand string `json:"card_brand"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
// Subscription model represents a subscription on the system.
|
||||
type Subscription struct {
|
||||
ID string `json:"id"`
|
||||
CustomerID string `json:"customer_id"`
|
||||
ProductID string `json:"product_id"`
|
||||
AddOns []string `json:"add_ons"`
|
||||
StartAt int64 `json:"start_at"`
|
||||
EndAt int64 `json:"end_at"`
|
||||
CreateAt int64 `json:"create_at"`
|
||||
Seats int `json:"seats"`
|
||||
Status string `json:"status"`
|
||||
DNS string `json:"dns"`
|
||||
IsPaidTier string `json:"is_paid_tier"`
|
||||
LastInvoice *Invoice `json:"last_invoice"`
|
||||
IsFreeTrial string `json:"is_free_trial"`
|
||||
TrialEndAt int64 `json:"trial_end_at"`
|
||||
}
|
||||
|
||||
// GetWorkSpaceNameFromDNS returns the work space name. For example from test.mattermost.cloud.com, it returns test
|
||||
func (s *Subscription) GetWorkSpaceNameFromDNS() string {
|
||||
return strings.Split(s.DNS, ".")[0]
|
||||
}
|
||||
|
||||
// Invoice model represents a cloud invoice
|
||||
type Invoice struct {
|
||||
ID string `json:"id"`
|
||||
Number string `json:"number"`
|
||||
CreateAt int64 `json:"create_at"`
|
||||
Total int64 `json:"total"`
|
||||
Tax int64 `json:"tax"`
|
||||
Status string `json:"status"`
|
||||
Description string `json:"description"`
|
||||
PeriodStart int64 `json:"period_start"`
|
||||
PeriodEnd int64 `json:"period_end"`
|
||||
SubscriptionID string `json:"subscription_id"`
|
||||
Items []*InvoiceLineItem `json:"line_items"`
|
||||
}
|
||||
|
||||
// InvoiceLineItem model represents a cloud invoice lineitem tied to an invoice.
|
||||
type InvoiceLineItem struct {
|
||||
PriceID string `json:"price_id"`
|
||||
Total int64 `json:"total"`
|
||||
Quantity int64 `json:"quantity"`
|
||||
PricePerUnit int64 `json:"price_per_unit"`
|
||||
Description string `json:"description"`
|
||||
Type string `json:"type"`
|
||||
Metadata map[string]interface{} `json:"metadata"`
|
||||
}
|
||||
|
||||
type CWSWebhookPayload struct {
|
||||
Event string `json:"event"`
|
||||
FailedPayment *FailedPayment `json:"failed_payment"`
|
||||
CloudWorkspaceOwner *CloudWorkspaceOwner `json:"cloud_workspace_owner"`
|
||||
SubscriptionTrialEndUnixTimeStamp int64 `json:"trial_end_time_stamp"`
|
||||
}
|
||||
|
||||
type FailedPayment struct {
|
||||
CardBrand string `json:"card_brand"`
|
||||
LastFour int `json:"last_four"`
|
||||
FailureMessage string `json:"failure_message"`
|
||||
}
|
||||
|
||||
// CloudWorkspaceOwner is part of the CWS Webhook payload that contains information about the user that created the workspace from the CWS
|
||||
type CloudWorkspaceOwner struct {
|
||||
UserName string `json:"username"`
|
||||
}
|
||||
type SubscriptionStats struct {
|
||||
RemainingSeats int `json:"remaining_seats"`
|
||||
IsPaidTier string `json:"is_paid_tier"`
|
||||
IsFreeTrial string `json:"is_free_trial"`
|
||||
}
|
||||
|
||||
type SubscriptionChange struct {
|
||||
ProductID string `json:"product_id"`
|
||||
}
|
137
vendor/github.com/mattermost/mattermost-server/v5/model/cluster_discovery.go
generated
vendored
137
vendor/github.com/mattermost/mattermost-server/v5/model/cluster_discovery.go
generated
vendored
@ -1,137 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
)
|
||||
|
||||
const (
|
||||
CDS_OFFLINE_AFTER_MILLIS = 1000 * 60 * 30 // 30 minutes
|
||||
CDS_TYPE_APP = "mattermost_app"
|
||||
)
|
||||
|
||||
type ClusterDiscovery struct {
|
||||
Id string `json:"id"`
|
||||
Type string `json:"type"`
|
||||
ClusterName string `json:"cluster_name"`
|
||||
Hostname string `json:"hostname"`
|
||||
GossipPort int32 `json:"gossip_port"`
|
||||
Port int32 `json:"port"`
|
||||
CreateAt int64 `json:"create_at"`
|
||||
LastPingAt int64 `json:"last_ping_at"`
|
||||
}
|
||||
|
||||
func (o *ClusterDiscovery) PreSave() {
|
||||
if o.Id == "" {
|
||||
o.Id = NewId()
|
||||
}
|
||||
|
||||
if o.CreateAt == 0 {
|
||||
o.CreateAt = GetMillis()
|
||||
o.LastPingAt = o.CreateAt
|
||||
}
|
||||
}
|
||||
|
||||
func (o *ClusterDiscovery) AutoFillHostname() {
|
||||
// attempt to set the hostname from the OS
|
||||
if o.Hostname == "" {
|
||||
if hn, err := os.Hostname(); err == nil {
|
||||
o.Hostname = hn
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (o *ClusterDiscovery) AutoFillIpAddress(iface string, ipAddress string) {
|
||||
// attempt to set the hostname to the first non-local IP address
|
||||
if o.Hostname == "" {
|
||||
if ipAddress != "" {
|
||||
o.Hostname = ipAddress
|
||||
} else {
|
||||
o.Hostname = GetServerIpAddress(iface)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (o *ClusterDiscovery) IsEqual(in *ClusterDiscovery) bool {
|
||||
if in == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if o.Type != in.Type {
|
||||
return false
|
||||
}
|
||||
|
||||
if o.ClusterName != in.ClusterName {
|
||||
return false
|
||||
}
|
||||
|
||||
if o.Hostname != in.Hostname {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func FilterClusterDiscovery(vs []*ClusterDiscovery, f func(*ClusterDiscovery) bool) []*ClusterDiscovery {
|
||||
copy := make([]*ClusterDiscovery, 0)
|
||||
for _, v := range vs {
|
||||
if f(v) {
|
||||
copy = append(copy, v)
|
||||
}
|
||||
}
|
||||
|
||||
return copy
|
||||
}
|
||||
|
||||
func (o *ClusterDiscovery) IsValid() *AppError {
|
||||
if !IsValidId(o.Id) {
|
||||
return NewAppError("ClusterDiscovery.IsValid", "model.cluster.is_valid.id.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if o.ClusterName == "" {
|
||||
return NewAppError("ClusterDiscovery.IsValid", "model.cluster.is_valid.name.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if o.Type == "" {
|
||||
return NewAppError("ClusterDiscovery.IsValid", "model.cluster.is_valid.type.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if o.Hostname == "" {
|
||||
return NewAppError("ClusterDiscovery.IsValid", "model.cluster.is_valid.hostname.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if o.CreateAt == 0 {
|
||||
return NewAppError("ClusterDiscovery.IsValid", "model.cluster.is_valid.create_at.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if o.LastPingAt == 0 {
|
||||
return NewAppError("ClusterDiscovery.IsValid", "model.cluster.is_valid.last_ping_at.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *ClusterDiscovery) ToJson() string {
|
||||
b, err := json.Marshal(o)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func ClusterDiscoveryFromJson(data io.Reader) *ClusterDiscovery {
|
||||
decoder := json.NewDecoder(data)
|
||||
var me ClusterDiscovery
|
||||
err := decoder.Decode(&me)
|
||||
if err == nil {
|
||||
return &me
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
43
vendor/github.com/mattermost/mattermost-server/v5/model/cluster_info.go
generated
vendored
43
vendor/github.com/mattermost/mattermost-server/v5/model/cluster_info.go
generated
vendored
@ -1,43 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
)
|
||||
|
||||
type ClusterInfo struct {
|
||||
Id string `json:"id"`
|
||||
Version string `json:"version"`
|
||||
ConfigHash string `json:"config_hash"`
|
||||
IpAddress string `json:"ipaddress"`
|
||||
Hostname string `json:"hostname"`
|
||||
}
|
||||
|
||||
func (ci *ClusterInfo) ToJson() string {
|
||||
b, _ := json.Marshal(ci)
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func ClusterInfoFromJson(data io.Reader) *ClusterInfo {
|
||||
var ci *ClusterInfo
|
||||
json.NewDecoder(data).Decode(&ci)
|
||||
return ci
|
||||
}
|
||||
|
||||
func ClusterInfosToJson(objmap []*ClusterInfo) string {
|
||||
b, _ := json.Marshal(objmap)
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func ClusterInfosFromJson(data io.Reader) []*ClusterInfo {
|
||||
decoder := json.NewDecoder(data)
|
||||
|
||||
var objmap []*ClusterInfo
|
||||
if err := decoder.Decode(&objmap); err != nil {
|
||||
return make([]*ClusterInfo, 0)
|
||||
}
|
||||
return objmap
|
||||
}
|
79
vendor/github.com/mattermost/mattermost-server/v5/model/cluster_message.go
generated
vendored
79
vendor/github.com/mattermost/mattermost-server/v5/model/cluster_message.go
generated
vendored
@ -1,79 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
)
|
||||
|
||||
const (
|
||||
CLUSTER_EVENT_PUBLISH = "publish"
|
||||
CLUSTER_EVENT_UPDATE_STATUS = "update_status"
|
||||
CLUSTER_EVENT_INVALIDATE_ALL_CACHES = "inv_all_caches"
|
||||
CLUSTER_EVENT_INVALIDATE_CACHE_FOR_REACTIONS = "inv_reactions"
|
||||
CLUSTER_EVENT_INVALIDATE_CACHE_FOR_WEBHOOK = "inv_webhook"
|
||||
CLUSTER_EVENT_INVALIDATE_CACHE_FOR_CHANNEL_POSTS = "inv_channel_posts"
|
||||
CLUSTER_EVENT_INVALIDATE_CACHE_FOR_CHANNEL_MEMBERS_NOTIFY_PROPS = "inv_channel_members_notify_props"
|
||||
CLUSTER_EVENT_INVALIDATE_CACHE_FOR_CHANNEL_MEMBERS = "inv_channel_members"
|
||||
CLUSTER_EVENT_INVALIDATE_CACHE_FOR_CHANNEL_BY_NAME = "inv_channel_name"
|
||||
CLUSTER_EVENT_INVALIDATE_CACHE_FOR_CHANNEL = "inv_channel"
|
||||
CLUSTER_EVENT_INVALIDATE_CACHE_FOR_CHANNEL_GUEST_COUNT = "inv_channel_guest_count"
|
||||
CLUSTER_EVENT_INVALIDATE_CACHE_FOR_USER = "inv_user"
|
||||
CLUSTER_EVENT_INVALIDATE_CACHE_FOR_USER_TEAMS = "inv_user_teams"
|
||||
CLUSTER_EVENT_CLEAR_SESSION_CACHE_FOR_USER = "clear_session_user"
|
||||
CLUSTER_EVENT_INVALIDATE_CACHE_FOR_ROLES = "inv_roles"
|
||||
CLUSTER_EVENT_INVALIDATE_CACHE_FOR_ROLE_PERMISSIONS = "inv_role_permissions"
|
||||
CLUSTER_EVENT_INVALIDATE_CACHE_FOR_PROFILE_BY_IDS = "inv_profile_ids"
|
||||
CLUSTER_EVENT_INVALIDATE_CACHE_FOR_PROFILE_IN_CHANNEL = "inv_profile_in_channel"
|
||||
CLUSTER_EVENT_INVALIDATE_CACHE_FOR_SCHEMES = "inv_schemes"
|
||||
CLUSTER_EVENT_INVALIDATE_CACHE_FOR_FILE_INFOS = "inv_file_infos"
|
||||
CLUSTER_EVENT_INVALIDATE_CACHE_FOR_WEBHOOKS = "inv_webhooks"
|
||||
CLUSTER_EVENT_INVALIDATE_CACHE_FOR_EMOJIS_BY_ID = "inv_emojis_by_id"
|
||||
CLUSTER_EVENT_INVALIDATE_CACHE_FOR_EMOJIS_ID_BY_NAME = "inv_emojis_id_by_name"
|
||||
CLUSTER_EVENT_INVALIDATE_CACHE_FOR_CHANNEL_PINNEDPOSTS_COUNTS = "inv_channel_pinnedposts_counts"
|
||||
CLUSTER_EVENT_INVALIDATE_CACHE_FOR_CHANNEL_MEMBER_COUNTS = "inv_channel_member_counts"
|
||||
CLUSTER_EVENT_INVALIDATE_CACHE_FOR_LAST_POSTS = "inv_last_posts"
|
||||
CLUSTER_EVENT_INVALIDATE_CACHE_FOR_LAST_POST_TIME = "inv_last_post_time"
|
||||
CLUSTER_EVENT_INVALIDATE_CACHE_FOR_TEAMS = "inv_teams"
|
||||
CLUSTER_EVENT_CLEAR_SESSION_CACHE_FOR_ALL_USERS = "inv_all_user_sessions"
|
||||
CLUSTER_EVENT_INSTALL_PLUGIN = "install_plugin"
|
||||
CLUSTER_EVENT_REMOVE_PLUGIN = "remove_plugin"
|
||||
CLUSTER_EVENT_PLUGIN_EVENT = "plugin_event"
|
||||
CLUSTER_EVENT_INVALIDATE_CACHE_FOR_TERMS_OF_SERVICE = "inv_terms_of_service"
|
||||
CLUSTER_EVENT_BUSY_STATE_CHANGED = "busy_state_change"
|
||||
|
||||
// Gossip communication
|
||||
CLUSTER_GOSSIP_EVENT_REQUEST_GET_LOGS = "gossip_request_get_logs"
|
||||
CLUSTER_GOSSIP_EVENT_RESPONSE_GET_LOGS = "gossip_response_get_logs"
|
||||
CLUSTER_GOSSIP_EVENT_REQUEST_GET_CLUSTER_STATS = "gossip_request_cluster_stats"
|
||||
CLUSTER_GOSSIP_EVENT_RESPONSE_GET_CLUSTER_STATS = "gossip_response_cluster_stats"
|
||||
CLUSTER_GOSSIP_EVENT_REQUEST_GET_PLUGIN_STATUSES = "gossip_request_plugin_statuses"
|
||||
CLUSTER_GOSSIP_EVENT_RESPONSE_GET_PLUGIN_STATUSES = "gossip_response_plugin_statuses"
|
||||
CLUSTER_GOSSIP_EVENT_REQUEST_SAVE_CONFIG = "gossip_request_save_config"
|
||||
CLUSTER_GOSSIP_EVENT_RESPONSE_SAVE_CONFIG = "gossip_response_save_config"
|
||||
|
||||
// SendTypes for ClusterMessage.
|
||||
CLUSTER_SEND_BEST_EFFORT = "best_effort"
|
||||
CLUSTER_SEND_RELIABLE = "reliable"
|
||||
)
|
||||
|
||||
type ClusterMessage struct {
|
||||
Event string `json:"event"`
|
||||
SendType string `json:"-"`
|
||||
WaitForAllToSend bool `json:"-"`
|
||||
Data string `json:"data,omitempty"`
|
||||
Props map[string]string `json:"props,omitempty"`
|
||||
}
|
||||
|
||||
func (o *ClusterMessage) ToJson() string {
|
||||
b, _ := json.Marshal(o)
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func ClusterMessageFromJson(data io.Reader) *ClusterMessage {
|
||||
var o *ClusterMessage
|
||||
json.NewDecoder(data).Decode(&o)
|
||||
return o
|
||||
}
|
27
vendor/github.com/mattermost/mattermost-server/v5/model/cluster_stats.go
generated
vendored
27
vendor/github.com/mattermost/mattermost-server/v5/model/cluster_stats.go
generated
vendored
@ -1,27 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
)
|
||||
|
||||
type ClusterStats struct {
|
||||
Id string `json:"id"`
|
||||
TotalWebsocketConnections int `json:"total_websocket_connections"`
|
||||
TotalReadDbConnections int `json:"total_read_db_connections"`
|
||||
TotalMasterDbConnections int `json:"total_master_db_connections"`
|
||||
}
|
||||
|
||||
func (cs *ClusterStats) ToJson() string {
|
||||
b, _ := json.Marshal(cs)
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func ClusterStatsFromJson(data io.Reader) *ClusterStats {
|
||||
var cs *ClusterStats
|
||||
json.NewDecoder(data).Decode(&cs)
|
||||
return cs
|
||||
}
|
161
vendor/github.com/mattermost/mattermost-server/v5/model/command.go
generated
vendored
161
vendor/github.com/mattermost/mattermost-server/v5/model/command.go
generated
vendored
@ -1,161 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
COMMAND_METHOD_POST = "P"
|
||||
COMMAND_METHOD_GET = "G"
|
||||
MIN_TRIGGER_LENGTH = 1
|
||||
MAX_TRIGGER_LENGTH = 128
|
||||
)
|
||||
|
||||
type Command struct {
|
||||
Id string `json:"id"`
|
||||
Token string `json:"token"`
|
||||
CreateAt int64 `json:"create_at"`
|
||||
UpdateAt int64 `json:"update_at"`
|
||||
DeleteAt int64 `json:"delete_at"`
|
||||
CreatorId string `json:"creator_id"`
|
||||
TeamId string `json:"team_id"`
|
||||
Trigger string `json:"trigger"`
|
||||
Method string `json:"method"`
|
||||
Username string `json:"username"`
|
||||
IconURL string `json:"icon_url"`
|
||||
AutoComplete bool `json:"auto_complete"`
|
||||
AutoCompleteDesc string `json:"auto_complete_desc"`
|
||||
AutoCompleteHint string `json:"auto_complete_hint"`
|
||||
DisplayName string `json:"display_name"`
|
||||
Description string `json:"description"`
|
||||
URL string `json:"url"`
|
||||
// PluginId records the id of the plugin that created this Command. If it is blank, the Command
|
||||
// was not created by a plugin.
|
||||
PluginId string `json:"plugin_id"`
|
||||
AutocompleteData *AutocompleteData `db:"-" json:"autocomplete_data,omitempty"`
|
||||
// AutocompleteIconData is a base64 encoded svg
|
||||
AutocompleteIconData string `db:"-" json:"autocomplete_icon_data,omitempty"`
|
||||
}
|
||||
|
||||
func (o *Command) ToJson() string {
|
||||
b, _ := json.Marshal(o)
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func CommandFromJson(data io.Reader) *Command {
|
||||
var o *Command
|
||||
json.NewDecoder(data).Decode(&o)
|
||||
return o
|
||||
}
|
||||
|
||||
func CommandListToJson(l []*Command) string {
|
||||
b, _ := json.Marshal(l)
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func CommandListFromJson(data io.Reader) []*Command {
|
||||
var o []*Command
|
||||
json.NewDecoder(data).Decode(&o)
|
||||
return o
|
||||
}
|
||||
|
||||
func (o *Command) IsValid() *AppError {
|
||||
|
||||
if !IsValidId(o.Id) {
|
||||
return NewAppError("Command.IsValid", "model.command.is_valid.id.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if len(o.Token) != 26 {
|
||||
return NewAppError("Command.IsValid", "model.command.is_valid.token.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if o.CreateAt == 0 {
|
||||
return NewAppError("Command.IsValid", "model.command.is_valid.create_at.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if o.UpdateAt == 0 {
|
||||
return NewAppError("Command.IsValid", "model.command.is_valid.update_at.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
// If the CreatorId is blank, this should be a command created by a plugin.
|
||||
if o.CreatorId == "" && !IsValidPluginId(o.PluginId) {
|
||||
return NewAppError("Command.IsValid", "model.command.is_valid.plugin_id.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
// If the PluginId is blank, this should be a command associated with a userId.
|
||||
if o.PluginId == "" && !IsValidId(o.CreatorId) {
|
||||
return NewAppError("Command.IsValid", "model.command.is_valid.user_id.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if o.CreatorId != "" && o.PluginId != "" {
|
||||
return NewAppError("Command.IsValid", "model.command.is_valid.plugin_id.app_error", nil, "command cannot have both a CreatorId and a PluginId", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if !IsValidId(o.TeamId) {
|
||||
return NewAppError("Command.IsValid", "model.command.is_valid.team_id.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if len(o.Trigger) < MIN_TRIGGER_LENGTH || len(o.Trigger) > MAX_TRIGGER_LENGTH || strings.Index(o.Trigger, "/") == 0 || strings.Contains(o.Trigger, " ") {
|
||||
return NewAppError("Command.IsValid", "model.command.is_valid.trigger.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if o.URL == "" || len(o.URL) > 1024 {
|
||||
return NewAppError("Command.IsValid", "model.command.is_valid.url.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if !IsValidHttpUrl(o.URL) {
|
||||
return NewAppError("Command.IsValid", "model.command.is_valid.url_http.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if !(o.Method == COMMAND_METHOD_GET || o.Method == COMMAND_METHOD_POST) {
|
||||
return NewAppError("Command.IsValid", "model.command.is_valid.method.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if len(o.DisplayName) > 64 {
|
||||
return NewAppError("Command.IsValid", "model.command.is_valid.display_name.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if len(o.Description) > 128 {
|
||||
return NewAppError("Command.IsValid", "model.command.is_valid.description.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if o.AutocompleteData != nil {
|
||||
if err := o.AutocompleteData.IsValid(); err != nil {
|
||||
return NewAppError("Command.IsValid", "model.command.is_valid.autocomplete_data.app_error", nil, err.Error(), http.StatusBadRequest)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *Command) PreSave() {
|
||||
if o.Id == "" {
|
||||
o.Id = NewId()
|
||||
}
|
||||
|
||||
if o.Token == "" {
|
||||
o.Token = NewId()
|
||||
}
|
||||
|
||||
o.CreateAt = GetMillis()
|
||||
o.UpdateAt = o.CreateAt
|
||||
}
|
||||
|
||||
func (o *Command) PreUpdate() {
|
||||
o.UpdateAt = GetMillis()
|
||||
}
|
||||
|
||||
func (o *Command) Sanitize() {
|
||||
o.Token = ""
|
||||
o.CreatorId = ""
|
||||
o.Method = ""
|
||||
o.URL = ""
|
||||
o.Username = ""
|
||||
o.IconURL = ""
|
||||
}
|
59
vendor/github.com/mattermost/mattermost-server/v5/model/command_args.go
generated
vendored
59
vendor/github.com/mattermost/mattermost-server/v5/model/command_args.go
generated
vendored
@ -1,59 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
|
||||
"github.com/mattermost/mattermost-server/v5/shared/i18n"
|
||||
)
|
||||
|
||||
type CommandArgs struct {
|
||||
UserId string `json:"user_id"`
|
||||
ChannelId string `json:"channel_id"`
|
||||
TeamId string `json:"team_id"`
|
||||
RootId string `json:"root_id"`
|
||||
ParentId string `json:"parent_id"`
|
||||
TriggerId string `json:"trigger_id,omitempty"`
|
||||
Command string `json:"command"`
|
||||
SiteURL string `json:"-"`
|
||||
T i18n.TranslateFunc `json:"-"`
|
||||
UserMentions UserMentionMap `json:"-"`
|
||||
ChannelMentions ChannelMentionMap `json:"-"`
|
||||
|
||||
// DO NOT USE Session field is deprecated. MM-26398
|
||||
Session Session `json:"-"`
|
||||
}
|
||||
|
||||
func (o *CommandArgs) ToJson() string {
|
||||
b, _ := json.Marshal(o)
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func CommandArgsFromJson(data io.Reader) *CommandArgs {
|
||||
var o *CommandArgs
|
||||
json.NewDecoder(data).Decode(&o)
|
||||
return o
|
||||
}
|
||||
|
||||
// AddUserMention adds or overrides an entry in UserMentions with name username
|
||||
// and identifier userId
|
||||
func (o *CommandArgs) AddUserMention(username, userId string) {
|
||||
if o.UserMentions == nil {
|
||||
o.UserMentions = make(UserMentionMap)
|
||||
}
|
||||
|
||||
o.UserMentions[username] = userId
|
||||
}
|
||||
|
||||
// AddChannelMention adds or overrides an entry in ChannelMentions with name
|
||||
// channelName and identifier channelId
|
||||
func (o *CommandArgs) AddChannelMention(channelName, channelId string) {
|
||||
if o.ChannelMentions == nil {
|
||||
o.ChannelMentions = make(ChannelMentionMap)
|
||||
}
|
||||
|
||||
o.ChannelMentions[channelName] = channelId
|
||||
}
|
455
vendor/github.com/mattermost/mattermost-server/v5/model/command_autocomplete.go
generated
vendored
455
vendor/github.com/mattermost/mattermost-server/v5/model/command_autocomplete.go
generated
vendored
@ -1,455 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/url"
|
||||
"path"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// AutocompleteArgType describes autocomplete argument type
|
||||
type AutocompleteArgType string
|
||||
|
||||
// Argument types
|
||||
const (
|
||||
AutocompleteArgTypeText AutocompleteArgType = "TextInput"
|
||||
AutocompleteArgTypeStaticList AutocompleteArgType = "StaticList"
|
||||
AutocompleteArgTypeDynamicList AutocompleteArgType = "DynamicList"
|
||||
)
|
||||
|
||||
// AutocompleteData describes slash command autocomplete information.
|
||||
type AutocompleteData struct {
|
||||
// Trigger of the command
|
||||
Trigger string
|
||||
// Hint of a command
|
||||
Hint string
|
||||
// Text displayed to the user to help with the autocomplete description
|
||||
HelpText string
|
||||
// Role of the user who should be able to see the autocomplete info of this command
|
||||
RoleID string
|
||||
// Arguments of the command. Arguments can be named or positional.
|
||||
// If they are positional order in the list matters, if they are named order does not matter.
|
||||
// All arguments should be either named or positional, no mixing allowed.
|
||||
Arguments []*AutocompleteArg
|
||||
// Subcommands of the command
|
||||
SubCommands []*AutocompleteData
|
||||
}
|
||||
|
||||
// AutocompleteArg describes an argument of the command. Arguments can be named or positional.
|
||||
// If Name is empty string Argument is positional otherwise it is named argument.
|
||||
// Named arguments are passed as --Name Argument_Value.
|
||||
type AutocompleteArg struct {
|
||||
// Name of the argument
|
||||
Name string
|
||||
// Text displayed to the user to help with the autocomplete
|
||||
HelpText string
|
||||
// Type of the argument
|
||||
Type AutocompleteArgType
|
||||
// Required determines if argument is optional or not.
|
||||
Required bool
|
||||
// Actual data of the argument (depends on the Type)
|
||||
Data interface{}
|
||||
}
|
||||
|
||||
// AutocompleteTextArg describes text user can input as an argument.
|
||||
type AutocompleteTextArg struct {
|
||||
// Hint of the input text
|
||||
Hint string
|
||||
// Regex pattern to match
|
||||
Pattern string
|
||||
}
|
||||
|
||||
// AutocompleteListItem describes an item in the AutocompleteStaticListArg.
|
||||
type AutocompleteListItem struct {
|
||||
Item string
|
||||
Hint string
|
||||
HelpText string
|
||||
}
|
||||
|
||||
// AutocompleteStaticListArg is used to input one of the arguments from the list,
|
||||
// for example [yes, no], [on, off], and so on.
|
||||
type AutocompleteStaticListArg struct {
|
||||
PossibleArguments []AutocompleteListItem
|
||||
}
|
||||
|
||||
// AutocompleteDynamicListArg is used when user wants to download possible argument list from the URL.
|
||||
type AutocompleteDynamicListArg struct {
|
||||
FetchURL string
|
||||
}
|
||||
|
||||
// AutocompleteSuggestion describes a single suggestion item sent to the front-end
|
||||
// Example: for user input `/jira cre` -
|
||||
// Complete might be `/jira create`
|
||||
// Suggestion might be `create`,
|
||||
// Hint might be `[issue text]`,
|
||||
// Description might be `Create a new Issue`
|
||||
type AutocompleteSuggestion struct {
|
||||
// Complete describes completed suggestion
|
||||
Complete string
|
||||
// Suggestion describes what user might want to input next
|
||||
Suggestion string
|
||||
// Hint describes a hint about the suggested input
|
||||
Hint string
|
||||
// Description of the command or a suggestion
|
||||
Description string
|
||||
// IconData is base64 encoded svg image
|
||||
IconData string
|
||||
}
|
||||
|
||||
// NewAutocompleteData returns new Autocomplete data.
|
||||
func NewAutocompleteData(trigger, hint, helpText string) *AutocompleteData {
|
||||
return &AutocompleteData{
|
||||
Trigger: trigger,
|
||||
Hint: hint,
|
||||
HelpText: helpText,
|
||||
RoleID: SYSTEM_USER_ROLE_ID,
|
||||
Arguments: []*AutocompleteArg{},
|
||||
SubCommands: []*AutocompleteData{},
|
||||
}
|
||||
}
|
||||
|
||||
// AddCommand adds a subcommand to the autocomplete data.
|
||||
func (ad *AutocompleteData) AddCommand(command *AutocompleteData) {
|
||||
ad.SubCommands = append(ad.SubCommands, command)
|
||||
}
|
||||
|
||||
// AddTextArgument adds positional AutocompleteArgTypeText argument to the command.
|
||||
func (ad *AutocompleteData) AddTextArgument(helpText, hint, pattern string) {
|
||||
ad.AddNamedTextArgument("", helpText, hint, pattern, true)
|
||||
}
|
||||
|
||||
// AddNamedTextArgument adds named AutocompleteArgTypeText argument to the command.
|
||||
func (ad *AutocompleteData) AddNamedTextArgument(name, helpText, hint, pattern string, required bool) {
|
||||
argument := AutocompleteArg{
|
||||
Name: name,
|
||||
HelpText: helpText,
|
||||
Type: AutocompleteArgTypeText,
|
||||
Required: required,
|
||||
Data: &AutocompleteTextArg{Hint: hint, Pattern: pattern},
|
||||
}
|
||||
ad.Arguments = append(ad.Arguments, &argument)
|
||||
}
|
||||
|
||||
// AddStaticListArgument adds positional AutocompleteArgTypeStaticList argument to the command.
|
||||
func (ad *AutocompleteData) AddStaticListArgument(helpText string, required bool, items []AutocompleteListItem) {
|
||||
ad.AddNamedStaticListArgument("", helpText, required, items)
|
||||
}
|
||||
|
||||
// AddNamedStaticListArgument adds named AutocompleteArgTypeStaticList argument to the command.
|
||||
func (ad *AutocompleteData) AddNamedStaticListArgument(name, helpText string, required bool, items []AutocompleteListItem) {
|
||||
argument := AutocompleteArg{
|
||||
Name: name,
|
||||
HelpText: helpText,
|
||||
Type: AutocompleteArgTypeStaticList,
|
||||
Required: required,
|
||||
Data: &AutocompleteStaticListArg{PossibleArguments: items},
|
||||
}
|
||||
ad.Arguments = append(ad.Arguments, &argument)
|
||||
}
|
||||
|
||||
// AddDynamicListArgument adds positional AutocompleteArgTypeDynamicList argument to the command.
|
||||
func (ad *AutocompleteData) AddDynamicListArgument(helpText, url string, required bool) {
|
||||
ad.AddNamedDynamicListArgument("", helpText, url, required)
|
||||
}
|
||||
|
||||
// AddNamedDynamicListArgument adds named AutocompleteArgTypeDynamicList argument to the command.
|
||||
func (ad *AutocompleteData) AddNamedDynamicListArgument(name, helpText, url string, required bool) {
|
||||
argument := AutocompleteArg{
|
||||
Name: name,
|
||||
HelpText: helpText,
|
||||
Type: AutocompleteArgTypeDynamicList,
|
||||
Required: required,
|
||||
Data: &AutocompleteDynamicListArg{FetchURL: url},
|
||||
}
|
||||
ad.Arguments = append(ad.Arguments, &argument)
|
||||
}
|
||||
|
||||
// Equals method checks if command is the same.
|
||||
func (ad *AutocompleteData) Equals(command *AutocompleteData) bool {
|
||||
if !(ad.Trigger == command.Trigger && ad.HelpText == command.HelpText && ad.RoleID == command.RoleID && ad.Hint == command.Hint) {
|
||||
return false
|
||||
}
|
||||
if len(ad.Arguments) != len(command.Arguments) || len(ad.SubCommands) != len(command.SubCommands) {
|
||||
return false
|
||||
}
|
||||
for i := range ad.Arguments {
|
||||
if !ad.Arguments[i].Equals(command.Arguments[i]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
for i := range ad.SubCommands {
|
||||
if !ad.SubCommands[i].Equals(command.SubCommands[i]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// UpdateRelativeURLsForPluginCommands method updates relative urls for plugin commands
|
||||
func (ad *AutocompleteData) UpdateRelativeURLsForPluginCommands(baseURL *url.URL) error {
|
||||
for _, arg := range ad.Arguments {
|
||||
if arg.Type != AutocompleteArgTypeDynamicList {
|
||||
continue
|
||||
}
|
||||
dynamicList, ok := arg.Data.(*AutocompleteDynamicListArg)
|
||||
if !ok {
|
||||
return errors.New("Not a proper DynamicList type argument")
|
||||
}
|
||||
dynamicListURL, err := url.Parse(dynamicList.FetchURL)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "FetchURL is not a proper url")
|
||||
}
|
||||
if !dynamicListURL.IsAbs() {
|
||||
absURL := &url.URL{}
|
||||
*absURL = *baseURL
|
||||
absURL.Path = path.Join(absURL.Path, dynamicList.FetchURL)
|
||||
dynamicList.FetchURL = absURL.String()
|
||||
}
|
||||
|
||||
}
|
||||
for _, command := range ad.SubCommands {
|
||||
err := command.UpdateRelativeURLsForPluginCommands(baseURL)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsValid method checks if autocomplete data is valid.
|
||||
func (ad *AutocompleteData) IsValid() error {
|
||||
if ad == nil {
|
||||
return errors.New("No nil commands are allowed in AutocompleteData")
|
||||
}
|
||||
if ad.Trigger == "" {
|
||||
return errors.New("An empty command name in the autocomplete data")
|
||||
}
|
||||
if strings.ToLower(ad.Trigger) != ad.Trigger {
|
||||
return errors.New("Command should be lowercase")
|
||||
}
|
||||
roles := []string{SYSTEM_ADMIN_ROLE_ID, SYSTEM_USER_ROLE_ID, ""}
|
||||
if stringNotInSlice(ad.RoleID, roles) {
|
||||
return errors.New("Wrong role in the autocomplete data")
|
||||
}
|
||||
if len(ad.Arguments) > 0 && len(ad.SubCommands) > 0 {
|
||||
return errors.New("Command can't have arguments and subcommands")
|
||||
}
|
||||
if len(ad.Arguments) > 0 {
|
||||
namedArgumentIndex := -1
|
||||
for i, arg := range ad.Arguments {
|
||||
if arg.Name != "" { // it's a named argument
|
||||
if namedArgumentIndex == -1 { // first named argument
|
||||
namedArgumentIndex = i
|
||||
}
|
||||
} else { // it's a positional argument
|
||||
if namedArgumentIndex != -1 {
|
||||
return errors.New("Named argument should not be before positional argument")
|
||||
}
|
||||
}
|
||||
if arg.Type == AutocompleteArgTypeDynamicList {
|
||||
dynamicList, ok := arg.Data.(*AutocompleteDynamicListArg)
|
||||
if !ok {
|
||||
return errors.New("Not a proper DynamicList type argument")
|
||||
}
|
||||
_, err := url.Parse(dynamicList.FetchURL)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "FetchURL is not a proper url")
|
||||
}
|
||||
} else if arg.Type == AutocompleteArgTypeStaticList {
|
||||
staticList, ok := arg.Data.(*AutocompleteStaticListArg)
|
||||
if !ok {
|
||||
return errors.New("Not a proper StaticList type argument")
|
||||
}
|
||||
for _, arg := range staticList.PossibleArguments {
|
||||
if arg.Item == "" {
|
||||
return errors.New("Possible argument name not set in StaticList argument")
|
||||
}
|
||||
}
|
||||
} else if arg.Type == AutocompleteArgTypeText {
|
||||
if _, ok := arg.Data.(*AutocompleteTextArg); !ok {
|
||||
return errors.New("Not a proper TextInput type argument")
|
||||
}
|
||||
if arg.Name == "" && !arg.Required {
|
||||
return errors.New("Positional argument can not be optional")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, command := range ad.SubCommands {
|
||||
err := command.IsValid()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ToJSON encodes AutocompleteData struct to the json
|
||||
func (ad *AutocompleteData) ToJSON() ([]byte, error) {
|
||||
b, err := json.Marshal(ad)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "can't marshal slash command %s", ad.Trigger)
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// AutocompleteDataFromJSON decodes AutocompleteData struct from the json
|
||||
func AutocompleteDataFromJSON(data []byte) (*AutocompleteData, error) {
|
||||
var ad AutocompleteData
|
||||
if err := json.Unmarshal(data, &ad); err != nil {
|
||||
return nil, errors.Wrap(err, "can't unmarshal AutocompleteData")
|
||||
}
|
||||
return &ad, nil
|
||||
}
|
||||
|
||||
// Equals method checks if argument is the same.
|
||||
func (a *AutocompleteArg) Equals(arg *AutocompleteArg) bool {
|
||||
if a.Name != arg.Name ||
|
||||
a.HelpText != arg.HelpText ||
|
||||
a.Type != arg.Type ||
|
||||
a.Required != arg.Required ||
|
||||
!reflect.DeepEqual(a.Data, arg.Data) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// UnmarshalJSON will unmarshal argument
|
||||
func (a *AutocompleteArg) UnmarshalJSON(b []byte) error {
|
||||
var arg map[string]interface{}
|
||||
if err := json.Unmarshal(b, &arg); err != nil {
|
||||
return errors.Wrapf(err, "Can't unmarshal argument %s", string(b))
|
||||
}
|
||||
var ok bool
|
||||
a.Name, ok = arg["Name"].(string)
|
||||
if !ok {
|
||||
return errors.Errorf("No field Name in the argument %s", string(b))
|
||||
}
|
||||
|
||||
a.HelpText, ok = arg["HelpText"].(string)
|
||||
if !ok {
|
||||
return errors.Errorf("No field HelpText in the argument %s", string(b))
|
||||
}
|
||||
|
||||
t, ok := arg["Type"].(string)
|
||||
if !ok {
|
||||
return errors.Errorf("No field Type in the argument %s", string(b))
|
||||
}
|
||||
a.Type = AutocompleteArgType(t)
|
||||
|
||||
a.Required, ok = arg["Required"].(bool)
|
||||
if !ok {
|
||||
return errors.Errorf("No field Required in the argument %s", string(b))
|
||||
}
|
||||
|
||||
data, ok := arg["Data"]
|
||||
if !ok {
|
||||
return errors.Errorf("No field Data in the argument %s", string(b))
|
||||
}
|
||||
|
||||
if a.Type == AutocompleteArgTypeText {
|
||||
m, ok := data.(map[string]interface{})
|
||||
if !ok {
|
||||
return errors.Errorf("Wrong Data type in the TextInput argument %s", string(b))
|
||||
}
|
||||
pattern, ok := m["Pattern"].(string)
|
||||
if !ok {
|
||||
return errors.Errorf("No field Pattern in the TextInput argument %s", string(b))
|
||||
}
|
||||
hint, ok := m["Hint"].(string)
|
||||
if !ok {
|
||||
return errors.Errorf("No field Hint in the TextInput argument %s", string(b))
|
||||
}
|
||||
a.Data = &AutocompleteTextArg{Hint: hint, Pattern: pattern}
|
||||
} else if a.Type == AutocompleteArgTypeStaticList {
|
||||
m, ok := data.(map[string]interface{})
|
||||
if !ok {
|
||||
return errors.Errorf("Wrong Data type in the StaticList argument %s", string(b))
|
||||
}
|
||||
list, ok := m["PossibleArguments"].([]interface{})
|
||||
if !ok {
|
||||
return errors.Errorf("No field PossibleArguments in the StaticList argument %s", string(b))
|
||||
}
|
||||
|
||||
possibleArguments := []AutocompleteListItem{}
|
||||
for i := range list {
|
||||
args, ok := list[i].(map[string]interface{})
|
||||
if !ok {
|
||||
return errors.Errorf("Wrong AutocompleteStaticListItem type in the StaticList argument %s", string(b))
|
||||
}
|
||||
item, ok := args["Item"].(string)
|
||||
if !ok {
|
||||
return errors.Errorf("No field Item in the StaticList's possible arguments %s", string(b))
|
||||
}
|
||||
|
||||
hint, ok := args["Hint"].(string)
|
||||
if !ok {
|
||||
return errors.Errorf("No field Hint in the StaticList's possible arguments %s", string(b))
|
||||
}
|
||||
helpText, ok := args["HelpText"].(string)
|
||||
if !ok {
|
||||
return errors.Errorf("No field Hint in the StaticList's possible arguments %s", string(b))
|
||||
}
|
||||
|
||||
possibleArguments = append(possibleArguments, AutocompleteListItem{
|
||||
Item: item,
|
||||
Hint: hint,
|
||||
HelpText: helpText,
|
||||
})
|
||||
}
|
||||
a.Data = &AutocompleteStaticListArg{PossibleArguments: possibleArguments}
|
||||
} else if a.Type == AutocompleteArgTypeDynamicList {
|
||||
m, ok := data.(map[string]interface{})
|
||||
if !ok {
|
||||
return errors.Errorf("Wrong type in the DynamicList argument %s", string(b))
|
||||
}
|
||||
url, ok := m["FetchURL"].(string)
|
||||
if !ok {
|
||||
return errors.Errorf("No field FetchURL in the DynamicList's argument %s", string(b))
|
||||
}
|
||||
a.Data = &AutocompleteDynamicListArg{FetchURL: url}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// AutocompleteSuggestionsToJSON returns json for a list of AutocompleteSuggestion objects
|
||||
func AutocompleteSuggestionsToJSON(suggestions []AutocompleteSuggestion) []byte {
|
||||
b, _ := json.Marshal(suggestions)
|
||||
return b
|
||||
}
|
||||
|
||||
// AutocompleteSuggestionsFromJSON returns list of AutocompleteSuggestions from json.
|
||||
func AutocompleteSuggestionsFromJSON(data io.Reader) []AutocompleteSuggestion {
|
||||
var o []AutocompleteSuggestion
|
||||
json.NewDecoder(data).Decode(&o)
|
||||
return o
|
||||
}
|
||||
|
||||
// AutocompleteStaticListItemsToJSON returns json for a list of AutocompleteStaticListItem objects
|
||||
func AutocompleteStaticListItemsToJSON(items []AutocompleteListItem) []byte {
|
||||
b, _ := json.Marshal(items)
|
||||
return b
|
||||
}
|
||||
|
||||
// AutocompleteStaticListItemsFromJSON returns list of AutocompleteStaticListItem from json.
|
||||
func AutocompleteStaticListItemsFromJSON(data io.Reader) []AutocompleteListItem {
|
||||
var o []AutocompleteListItem
|
||||
json.NewDecoder(data).Decode(&o)
|
||||
return o
|
||||
}
|
||||
|
||||
func stringNotInSlice(a string, slice []string) bool {
|
||||
for _, b := range slice {
|
||||
if b == a {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
31
vendor/github.com/mattermost/mattermost-server/v5/model/command_request.go
generated
vendored
31
vendor/github.com/mattermost/mattermost-server/v5/model/command_request.go
generated
vendored
@ -1,31 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
)
|
||||
|
||||
type CommandMoveRequest struct {
|
||||
TeamId string `json:"team_id"`
|
||||
}
|
||||
|
||||
func CommandMoveRequestFromJson(data io.Reader) (*CommandMoveRequest, error) {
|
||||
decoder := json.NewDecoder(data)
|
||||
var cmr CommandMoveRequest
|
||||
err := decoder.Decode(&cmr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &cmr, nil
|
||||
}
|
||||
|
||||
func (cmr *CommandMoveRequest) ToJson() string {
|
||||
b, err := json.Marshal(cmr)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return string(b)
|
||||
}
|
77
vendor/github.com/mattermost/mattermost-server/v5/model/command_response.go
generated
vendored
77
vendor/github.com/mattermost/mattermost-server/v5/model/command_response.go
generated
vendored
@ -1,77 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
|
||||
"github.com/mattermost/mattermost-server/v5/utils/jsonutils"
|
||||
)
|
||||
|
||||
const (
|
||||
COMMAND_RESPONSE_TYPE_IN_CHANNEL = "in_channel"
|
||||
COMMAND_RESPONSE_TYPE_EPHEMERAL = "ephemeral"
|
||||
)
|
||||
|
||||
type CommandResponse struct {
|
||||
ResponseType string `json:"response_type"`
|
||||
Text string `json:"text"`
|
||||
Username string `json:"username"`
|
||||
ChannelId string `json:"channel_id"`
|
||||
IconURL string `json:"icon_url"`
|
||||
Type string `json:"type"`
|
||||
Props StringInterface `json:"props"`
|
||||
GotoLocation string `json:"goto_location"`
|
||||
TriggerId string `json:"trigger_id"`
|
||||
SkipSlackParsing bool `json:"skip_slack_parsing"` // Set to `true` to skip the Slack-compatibility handling of Text.
|
||||
Attachments []*SlackAttachment `json:"attachments"`
|
||||
ExtraResponses []*CommandResponse `json:"extra_responses"`
|
||||
}
|
||||
|
||||
func (o *CommandResponse) ToJson() string {
|
||||
b, _ := json.Marshal(o)
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func CommandResponseFromHTTPBody(contentType string, body io.Reader) (*CommandResponse, error) {
|
||||
if strings.TrimSpace(strings.Split(contentType, ";")[0]) == "application/json" {
|
||||
return CommandResponseFromJson(body)
|
||||
}
|
||||
if b, err := ioutil.ReadAll(body); err == nil {
|
||||
return CommandResponseFromPlainText(string(b)), nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func CommandResponseFromPlainText(text string) *CommandResponse {
|
||||
return &CommandResponse{
|
||||
Text: text,
|
||||
}
|
||||
}
|
||||
|
||||
func CommandResponseFromJson(data io.Reader) (*CommandResponse, error) {
|
||||
b, err := ioutil.ReadAll(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var o CommandResponse
|
||||
err = json.Unmarshal(b, &o)
|
||||
if err != nil {
|
||||
return nil, jsonutils.HumanizeJSONError(err, b)
|
||||
}
|
||||
|
||||
o.Attachments = StringifySlackFieldValue(o.Attachments)
|
||||
|
||||
if o.ExtraResponses != nil {
|
||||
for _, resp := range o.ExtraResponses {
|
||||
resp.Attachments = StringifySlackFieldValue(resp.Attachments)
|
||||
}
|
||||
}
|
||||
|
||||
return &o, nil
|
||||
}
|
65
vendor/github.com/mattermost/mattermost-server/v5/model/command_webhook.go
generated
vendored
65
vendor/github.com/mattermost/mattermost-server/v5/model/command_webhook.go
generated
vendored
@ -1,65 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type CommandWebhook struct {
|
||||
Id string
|
||||
CreateAt int64
|
||||
CommandId string
|
||||
UserId string
|
||||
ChannelId string
|
||||
RootId string
|
||||
ParentId string
|
||||
UseCount int
|
||||
}
|
||||
|
||||
const (
|
||||
COMMAND_WEBHOOK_LIFETIME = 1000 * 60 * 30
|
||||
)
|
||||
|
||||
func (o *CommandWebhook) PreSave() {
|
||||
if o.Id == "" {
|
||||
o.Id = NewId()
|
||||
}
|
||||
|
||||
if o.CreateAt == 0 {
|
||||
o.CreateAt = GetMillis()
|
||||
}
|
||||
}
|
||||
|
||||
func (o *CommandWebhook) IsValid() *AppError {
|
||||
if !IsValidId(o.Id) {
|
||||
return NewAppError("CommandWebhook.IsValid", "model.command_hook.id.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if o.CreateAt == 0 {
|
||||
return NewAppError("CommandWebhook.IsValid", "model.command_hook.create_at.app_error", nil, "id="+o.Id, http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if !IsValidId(o.CommandId) {
|
||||
return NewAppError("CommandWebhook.IsValid", "model.command_hook.command_id.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if !IsValidId(o.UserId) {
|
||||
return NewAppError("CommandWebhook.IsValid", "model.command_hook.user_id.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if !IsValidId(o.ChannelId) {
|
||||
return NewAppError("CommandWebhook.IsValid", "model.command_hook.channel_id.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if o.RootId != "" && !IsValidId(o.RootId) {
|
||||
return NewAppError("CommandWebhook.IsValid", "model.command_hook.root_id.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if o.ParentId != "" && !IsValidId(o.ParentId) {
|
||||
return NewAppError("CommandWebhook.IsValid", "model.command_hook.parent_id.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
137
vendor/github.com/mattermost/mattermost-server/v5/model/compliance.go
generated
vendored
137
vendor/github.com/mattermost/mattermost-server/v5/model/compliance.go
generated
vendored
@ -1,137 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
COMPLIANCE_STATUS_CREATED = "created"
|
||||
COMPLIANCE_STATUS_RUNNING = "running"
|
||||
COMPLIANCE_STATUS_FINISHED = "finished"
|
||||
COMPLIANCE_STATUS_FAILED = "failed"
|
||||
COMPLIANCE_STATUS_REMOVED = "removed"
|
||||
|
||||
COMPLIANCE_TYPE_DAILY = "daily"
|
||||
COMPLIANCE_TYPE_ADHOC = "adhoc"
|
||||
)
|
||||
|
||||
type Compliance struct {
|
||||
Id string `json:"id"`
|
||||
CreateAt int64 `json:"create_at"`
|
||||
UserId string `json:"user_id"`
|
||||
Status string `json:"status"`
|
||||
Count int `json:"count"`
|
||||
Desc string `json:"desc"`
|
||||
Type string `json:"type"`
|
||||
StartAt int64 `json:"start_at"`
|
||||
EndAt int64 `json:"end_at"`
|
||||
Keywords string `json:"keywords"`
|
||||
Emails string `json:"emails"`
|
||||
}
|
||||
|
||||
type Compliances []Compliance
|
||||
|
||||
// ComplianceExportCursor is used for paginated iteration of posts
|
||||
// for compliance export.
|
||||
// We need to keep track of the last post ID in addition to the last post
|
||||
// CreateAt to break ties when two posts have the same CreateAt.
|
||||
type ComplianceExportCursor struct {
|
||||
LastChannelsQueryPostCreateAt int64
|
||||
LastChannelsQueryPostID string
|
||||
ChannelsQueryCompleted bool
|
||||
LastDirectMessagesQueryPostCreateAt int64
|
||||
LastDirectMessagesQueryPostID string
|
||||
DirectMessagesQueryCompleted bool
|
||||
}
|
||||
|
||||
func (c *Compliance) ToJson() string {
|
||||
b, _ := json.Marshal(c)
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func (c *Compliance) PreSave() {
|
||||
if c.Id == "" {
|
||||
c.Id = NewId()
|
||||
}
|
||||
|
||||
if c.Status == "" {
|
||||
c.Status = COMPLIANCE_STATUS_CREATED
|
||||
}
|
||||
|
||||
c.Count = 0
|
||||
c.Emails = NormalizeEmail(c.Emails)
|
||||
c.Keywords = strings.ToLower(c.Keywords)
|
||||
|
||||
c.CreateAt = GetMillis()
|
||||
}
|
||||
|
||||
func (c *Compliance) DeepCopy() *Compliance {
|
||||
copy := *c
|
||||
return ©
|
||||
}
|
||||
|
||||
func (c *Compliance) JobName() string {
|
||||
jobName := c.Type
|
||||
if c.Type == COMPLIANCE_TYPE_DAILY {
|
||||
jobName += "-" + c.Desc
|
||||
}
|
||||
|
||||
jobName += "-" + c.Id
|
||||
|
||||
return jobName
|
||||
}
|
||||
|
||||
func (c *Compliance) IsValid() *AppError {
|
||||
|
||||
if !IsValidId(c.Id) {
|
||||
return NewAppError("Compliance.IsValid", "model.compliance.is_valid.id.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if c.CreateAt == 0 {
|
||||
return NewAppError("Compliance.IsValid", "model.compliance.is_valid.create_at.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if len(c.Desc) > 512 || c.Desc == "" {
|
||||
return NewAppError("Compliance.IsValid", "model.compliance.is_valid.desc.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if c.StartAt == 0 {
|
||||
return NewAppError("Compliance.IsValid", "model.compliance.is_valid.start_at.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if c.EndAt == 0 {
|
||||
return NewAppError("Compliance.IsValid", "model.compliance.is_valid.end_at.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if c.EndAt <= c.StartAt {
|
||||
return NewAppError("Compliance.IsValid", "model.compliance.is_valid.start_end_at.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func ComplianceFromJson(data io.Reader) *Compliance {
|
||||
var c *Compliance
|
||||
json.NewDecoder(data).Decode(&c)
|
||||
return c
|
||||
}
|
||||
|
||||
func (c Compliances) ToJson() string {
|
||||
b, err := json.Marshal(c)
|
||||
if err != nil {
|
||||
return "[]"
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func CompliancesFromJson(data io.Reader) Compliances {
|
||||
var o Compliances
|
||||
json.NewDecoder(data).Decode(&o)
|
||||
return o
|
||||
}
|
124
vendor/github.com/mattermost/mattermost-server/v5/model/compliance_post.go
generated
vendored
124
vendor/github.com/mattermost/mattermost-server/v5/model/compliance_post.go
generated
vendored
@ -1,124 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"time"
|
||||
)
|
||||
|
||||
type CompliancePost struct {
|
||||
|
||||
// From Team
|
||||
TeamName string
|
||||
TeamDisplayName string
|
||||
|
||||
// From Channel
|
||||
ChannelName string
|
||||
ChannelDisplayName string
|
||||
ChannelType string
|
||||
|
||||
// From User
|
||||
UserUsername string
|
||||
UserEmail string
|
||||
UserNickname string
|
||||
|
||||
// From Post
|
||||
PostId string
|
||||
PostCreateAt int64
|
||||
PostUpdateAt int64
|
||||
PostDeleteAt int64
|
||||
PostRootId string
|
||||
PostParentId string
|
||||
PostOriginalId string
|
||||
PostMessage string
|
||||
PostType string
|
||||
PostProps string
|
||||
PostHashtags string
|
||||
PostFileIds string
|
||||
|
||||
IsBot bool
|
||||
}
|
||||
|
||||
func CompliancePostHeader() []string {
|
||||
return []string{
|
||||
"TeamName",
|
||||
"TeamDisplayName",
|
||||
|
||||
"ChannelName",
|
||||
"ChannelDisplayName",
|
||||
"ChannelType",
|
||||
|
||||
"UserUsername",
|
||||
"UserEmail",
|
||||
"UserNickname",
|
||||
"UserType",
|
||||
|
||||
"PostId",
|
||||
"PostCreateAt",
|
||||
"PostUpdateAt",
|
||||
"PostDeleteAt",
|
||||
"PostRootId",
|
||||
"PostParentId",
|
||||
"PostOriginalId",
|
||||
"PostMessage",
|
||||
"PostType",
|
||||
"PostProps",
|
||||
"PostHashtags",
|
||||
"PostFileIds",
|
||||
}
|
||||
}
|
||||
|
||||
func cleanComplianceStrings(in string) string {
|
||||
if matched, _ := regexp.MatchString("^\\s*(=|\\+|\\-)", in); matched {
|
||||
return "'" + in
|
||||
}
|
||||
return in
|
||||
}
|
||||
|
||||
func (cp *CompliancePost) Row() []string {
|
||||
|
||||
postDeleteAt := ""
|
||||
if cp.PostDeleteAt > 0 {
|
||||
postDeleteAt = time.Unix(0, cp.PostDeleteAt*int64(1000*1000)).Format(time.RFC3339)
|
||||
}
|
||||
|
||||
postUpdateAt := ""
|
||||
if cp.PostUpdateAt != cp.PostCreateAt {
|
||||
postUpdateAt = time.Unix(0, cp.PostUpdateAt*int64(1000*1000)).Format(time.RFC3339)
|
||||
}
|
||||
|
||||
userType := "user"
|
||||
if cp.IsBot {
|
||||
userType = "bot"
|
||||
}
|
||||
|
||||
return []string{
|
||||
cleanComplianceStrings(cp.TeamName),
|
||||
cleanComplianceStrings(cp.TeamDisplayName),
|
||||
|
||||
cleanComplianceStrings(cp.ChannelName),
|
||||
cleanComplianceStrings(cp.ChannelDisplayName),
|
||||
cleanComplianceStrings(cp.ChannelType),
|
||||
|
||||
cleanComplianceStrings(cp.UserUsername),
|
||||
cleanComplianceStrings(cp.UserEmail),
|
||||
cleanComplianceStrings(cp.UserNickname),
|
||||
userType,
|
||||
|
||||
cp.PostId,
|
||||
time.Unix(0, cp.PostCreateAt*int64(1000*1000)).Format(time.RFC3339),
|
||||
postUpdateAt,
|
||||
postDeleteAt,
|
||||
|
||||
cp.PostRootId,
|
||||
cp.PostParentId,
|
||||
cp.PostOriginalId,
|
||||
cleanComplianceStrings(cp.PostMessage),
|
||||
cp.PostType,
|
||||
cp.PostProps,
|
||||
cp.PostHashtags,
|
||||
cp.PostFileIds,
|
||||
}
|
||||
}
|
3994
vendor/github.com/mattermost/mattermost-server/v5/model/config.go
generated
vendored
3994
vendor/github.com/mattermost/mattermost-server/v5/model/config.go
generated
vendored
File diff suppressed because it is too large
Load Diff
141
vendor/github.com/mattermost/mattermost-server/v5/model/custom_status.go
generated
vendored
141
vendor/github.com/mattermost/mattermost-server/v5/model/custom_status.go
generated
vendored
@ -1,141 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
UserPropsKeyCustomStatus = "customStatus"
|
||||
|
||||
CustomStatusTextMaxRunes = 100
|
||||
MaxRecentCustomStatuses = 5
|
||||
DefaultCustomStatusEmoji = "speech_balloon"
|
||||
)
|
||||
|
||||
var validCustomStatusDuration = map[string]bool{
|
||||
"thirty_minutes": true,
|
||||
"one_hour": true,
|
||||
"four_hours": true,
|
||||
"today": true,
|
||||
"this_week": true,
|
||||
"date_and_time": true,
|
||||
}
|
||||
|
||||
type CustomStatus struct {
|
||||
Emoji string `json:"emoji"`
|
||||
Text string `json:"text"`
|
||||
Duration string `json:"duration"`
|
||||
ExpiresAt time.Time `json:"expires_at"`
|
||||
}
|
||||
|
||||
func (cs *CustomStatus) PreSave() {
|
||||
if cs.Emoji == "" {
|
||||
cs.Emoji = DefaultCustomStatusEmoji
|
||||
}
|
||||
|
||||
if cs.Duration == "" && !cs.ExpiresAt.Before(time.Now()) {
|
||||
cs.Duration = "date_and_time"
|
||||
}
|
||||
|
||||
runes := []rune(cs.Text)
|
||||
if len(runes) > CustomStatusTextMaxRunes {
|
||||
cs.Text = string(runes[:CustomStatusTextMaxRunes])
|
||||
}
|
||||
}
|
||||
|
||||
func (cs *CustomStatus) ToJson() string {
|
||||
csCopy := *cs
|
||||
b, _ := json.Marshal(csCopy)
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func (cs *CustomStatus) AreDurationAndExpirationTimeValid() bool {
|
||||
if cs.Duration == "" && (cs.ExpiresAt.IsZero() || !cs.ExpiresAt.Before(time.Now())) {
|
||||
return true
|
||||
}
|
||||
|
||||
if validCustomStatusDuration[cs.Duration] && !cs.ExpiresAt.Before(time.Now()) {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func CustomStatusFromJson(data io.Reader) *CustomStatus {
|
||||
var cs *CustomStatus
|
||||
_ = json.NewDecoder(data).Decode(&cs)
|
||||
return cs
|
||||
}
|
||||
|
||||
func RuneToHexadecimalString(r rune) string {
|
||||
return fmt.Sprintf("%04x", r)
|
||||
}
|
||||
|
||||
type RecentCustomStatuses []CustomStatus
|
||||
|
||||
func (rcs *RecentCustomStatuses) Contains(cs *CustomStatus) bool {
|
||||
var csJSON = cs.ToJson()
|
||||
|
||||
// status is empty
|
||||
if cs == nil || csJSON == "" || (cs.Emoji == "" && cs.Text == "") {
|
||||
return false
|
||||
}
|
||||
|
||||
for _, status := range *rcs {
|
||||
if status.ToJson() == csJSON {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (rcs *RecentCustomStatuses) Add(cs *CustomStatus) *RecentCustomStatuses {
|
||||
newRCS := (*rcs)[:0]
|
||||
|
||||
// if same `text` exists in existing recent custom statuses, modify existing status
|
||||
for _, status := range *rcs {
|
||||
if status.Text != cs.Text {
|
||||
newRCS = append(newRCS, status)
|
||||
}
|
||||
}
|
||||
newRCS = append(RecentCustomStatuses{*cs}, newRCS...)
|
||||
if len(newRCS) > MaxRecentCustomStatuses {
|
||||
newRCS = newRCS[:MaxRecentCustomStatuses]
|
||||
}
|
||||
return &newRCS
|
||||
}
|
||||
|
||||
func (rcs *RecentCustomStatuses) Remove(cs *CustomStatus) *RecentCustomStatuses {
|
||||
var csJSON = cs.ToJson()
|
||||
if csJSON == "" || (cs.Emoji == "" && cs.Text == "") {
|
||||
return rcs
|
||||
}
|
||||
|
||||
newRCS := (*rcs)[:0]
|
||||
for _, status := range *rcs {
|
||||
if status.ToJson() != csJSON {
|
||||
newRCS = append(newRCS, status)
|
||||
}
|
||||
}
|
||||
|
||||
return &newRCS
|
||||
}
|
||||
|
||||
func (rcs *RecentCustomStatuses) ToJson() string {
|
||||
rcsCopy := *rcs
|
||||
b, _ := json.Marshal(rcsCopy)
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func RecentCustomStatusesFromJson(data io.Reader) *RecentCustomStatuses {
|
||||
var rcs *RecentCustomStatuses
|
||||
_ = json.NewDecoder(data).Decode(&rcs)
|
||||
return rcs
|
||||
}
|
132
vendor/github.com/mattermost/mattermost-server/v5/model/data_retention_policy.go
generated
vendored
132
vendor/github.com/mattermost/mattermost-server/v5/model/data_retention_policy.go
generated
vendored
@ -1,132 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
)
|
||||
|
||||
type GlobalRetentionPolicy struct {
|
||||
MessageDeletionEnabled bool `json:"message_deletion_enabled"`
|
||||
FileDeletionEnabled bool `json:"file_deletion_enabled"`
|
||||
MessageRetentionCutoff int64 `json:"message_retention_cutoff"`
|
||||
FileRetentionCutoff int64 `json:"file_retention_cutoff"`
|
||||
}
|
||||
|
||||
type RetentionPolicy struct {
|
||||
ID string `db:"Id" json:"id"`
|
||||
DisplayName string `json:"display_name"`
|
||||
PostDuration *int64 `json:"post_duration"`
|
||||
}
|
||||
|
||||
type RetentionPolicyWithTeamAndChannelIDs struct {
|
||||
RetentionPolicy
|
||||
TeamIDs []string `json:"team_ids"`
|
||||
ChannelIDs []string `json:"channel_ids"`
|
||||
}
|
||||
|
||||
type RetentionPolicyWithTeamAndChannelCounts struct {
|
||||
RetentionPolicy
|
||||
ChannelCount int64 `json:"channel_count"`
|
||||
TeamCount int64 `json:"team_count"`
|
||||
}
|
||||
|
||||
type RetentionPolicyChannel struct {
|
||||
PolicyID string `db:"PolicyId"`
|
||||
ChannelID string `db:"ChannelId"`
|
||||
}
|
||||
|
||||
type RetentionPolicyTeam struct {
|
||||
PolicyID string `db:"PolicyId"`
|
||||
TeamID string `db:"TeamId"`
|
||||
}
|
||||
|
||||
type RetentionPolicyWithTeamAndChannelCountsList struct {
|
||||
Policies []*RetentionPolicyWithTeamAndChannelCounts `json:"policies"`
|
||||
TotalCount int64 `json:"total_count"`
|
||||
}
|
||||
|
||||
type RetentionPolicyForTeam struct {
|
||||
TeamID string `db:"Id" json:"team_id"`
|
||||
PostDuration int64 `json:"post_duration"`
|
||||
}
|
||||
|
||||
type RetentionPolicyForTeamList struct {
|
||||
Policies []*RetentionPolicyForTeam `json:"policies"`
|
||||
TotalCount int64 `json:"total_count"`
|
||||
}
|
||||
|
||||
type RetentionPolicyForChannel struct {
|
||||
ChannelID string `db:"Id" json:"channel_id"`
|
||||
PostDuration int64 `json:"post_duration"`
|
||||
}
|
||||
|
||||
type RetentionPolicyForChannelList struct {
|
||||
Policies []*RetentionPolicyForChannel `json:"policies"`
|
||||
TotalCount int64 `json:"total_count"`
|
||||
}
|
||||
|
||||
type RetentionPolicyCursor struct {
|
||||
ChannelPoliciesDone bool
|
||||
TeamPoliciesDone bool
|
||||
GlobalPoliciesDone bool
|
||||
}
|
||||
|
||||
func (rp *GlobalRetentionPolicy) ToJson() []byte {
|
||||
b, _ := json.Marshal(rp)
|
||||
return b
|
||||
}
|
||||
|
||||
func GlobalRetentionPolicyFromJson(data io.Reader) *GlobalRetentionPolicy {
|
||||
var grp *GlobalRetentionPolicy
|
||||
json.NewDecoder(data).Decode(&grp)
|
||||
return grp
|
||||
}
|
||||
|
||||
func RetentionPolicyWithTeamAndChannelCountsFromJson(data io.Reader) (*RetentionPolicyWithTeamAndChannelCounts, error) {
|
||||
var rp RetentionPolicyWithTeamAndChannelCounts
|
||||
err := json.NewDecoder(data).Decode(&rp)
|
||||
return &rp, err
|
||||
}
|
||||
|
||||
func (rp *RetentionPolicyWithTeamAndChannelCounts) ToJson() []byte {
|
||||
b, _ := json.Marshal(rp)
|
||||
return b
|
||||
}
|
||||
|
||||
func RetentionPolicyWithTeamAndChannelCountsListFromJson(data io.Reader) (*RetentionPolicyWithTeamAndChannelCountsList, error) {
|
||||
var rpList *RetentionPolicyWithTeamAndChannelCountsList
|
||||
err := json.NewDecoder(data).Decode(&rpList)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return rpList, nil
|
||||
}
|
||||
|
||||
func (rpList *RetentionPolicyWithTeamAndChannelCountsList) ToJson() []byte {
|
||||
b, _ := json.Marshal(rpList)
|
||||
return b
|
||||
}
|
||||
|
||||
func RetentionPolicyWithTeamAndChannelIdsFromJson(data io.Reader) (*RetentionPolicyWithTeamAndChannelIDs, error) {
|
||||
var rp *RetentionPolicyWithTeamAndChannelIDs
|
||||
err := json.NewDecoder(data).Decode(&rp)
|
||||
return rp, err
|
||||
}
|
||||
|
||||
func (rp *RetentionPolicyWithTeamAndChannelIDs) ToJson() []byte {
|
||||
b, _ := json.Marshal(rp)
|
||||
return b
|
||||
}
|
||||
|
||||
func (lst *RetentionPolicyForTeamList) ToJson() []byte {
|
||||
b, _ := json.Marshal(lst)
|
||||
return b
|
||||
}
|
||||
|
||||
func (lst *RetentionPolicyForChannelList) ToJson() []byte {
|
||||
b, _ := json.Marshal(lst)
|
||||
return b
|
||||
}
|
119
vendor/github.com/mattermost/mattermost-server/v5/model/emoji.go
generated
vendored
119
vendor/github.com/mattermost/mattermost-server/v5/model/emoji.go
generated
vendored
@ -1,119 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"sort"
|
||||
)
|
||||
|
||||
const (
|
||||
EMOJI_NAME_MAX_LENGTH = 64
|
||||
EMOJI_SORT_BY_NAME = "name"
|
||||
)
|
||||
|
||||
var EMOJI_PATTERN = regexp.MustCompile(`:[a-zA-Z0-9_+-]+:`)
|
||||
|
||||
var ReverseSystemEmojisMap = makeReverseEmojiMap()
|
||||
|
||||
type Emoji struct {
|
||||
Id string `json:"id"`
|
||||
CreateAt int64 `json:"create_at"`
|
||||
UpdateAt int64 `json:"update_at"`
|
||||
DeleteAt int64 `json:"delete_at"`
|
||||
CreatorId string `json:"creator_id"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
func inSystemEmoji(emojiName string) bool {
|
||||
_, ok := SystemEmojis[emojiName]
|
||||
return ok
|
||||
}
|
||||
|
||||
func GetSystemEmojiId(emojiName string) (string, bool) {
|
||||
id, found := SystemEmojis[emojiName]
|
||||
return id, found
|
||||
}
|
||||
|
||||
func makeReverseEmojiMap() map[string][]string {
|
||||
reverseEmojiMap := make(map[string][]string)
|
||||
for key, value := range SystemEmojis {
|
||||
emojiNames := reverseEmojiMap[value]
|
||||
emojiNames = append(emojiNames, key)
|
||||
sort.Strings(emojiNames)
|
||||
reverseEmojiMap[value] = emojiNames
|
||||
}
|
||||
|
||||
return reverseEmojiMap
|
||||
}
|
||||
|
||||
func GetEmojiNameFromUnicode(unicode string) (emojiName string, count int) {
|
||||
if emojiNames, found := ReverseSystemEmojisMap[unicode]; found {
|
||||
return emojiNames[0], len(emojiNames)
|
||||
}
|
||||
|
||||
return "", 0
|
||||
}
|
||||
|
||||
func (emoji *Emoji) IsValid() *AppError {
|
||||
if !IsValidId(emoji.Id) {
|
||||
return NewAppError("Emoji.IsValid", "model.emoji.id.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if emoji.CreateAt == 0 {
|
||||
return NewAppError("Emoji.IsValid", "model.emoji.create_at.app_error", nil, "id="+emoji.Id, http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if emoji.UpdateAt == 0 {
|
||||
return NewAppError("Emoji.IsValid", "model.emoji.update_at.app_error", nil, "id="+emoji.Id, http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if len(emoji.CreatorId) > 26 {
|
||||
return NewAppError("Emoji.IsValid", "model.emoji.user_id.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
return IsValidEmojiName(emoji.Name)
|
||||
}
|
||||
|
||||
func IsValidEmojiName(name string) *AppError {
|
||||
if name == "" || len(name) > EMOJI_NAME_MAX_LENGTH || !IsValidAlphaNumHyphenUnderscorePlus(name) || inSystemEmoji(name) {
|
||||
return NewAppError("Emoji.IsValid", "model.emoji.name.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (emoji *Emoji) PreSave() {
|
||||
if emoji.Id == "" {
|
||||
emoji.Id = NewId()
|
||||
}
|
||||
|
||||
emoji.CreateAt = GetMillis()
|
||||
emoji.UpdateAt = emoji.CreateAt
|
||||
}
|
||||
|
||||
func (emoji *Emoji) ToJson() string {
|
||||
b, _ := json.Marshal(emoji)
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func EmojiFromJson(data io.Reader) *Emoji {
|
||||
var emoji *Emoji
|
||||
json.NewDecoder(data).Decode(&emoji)
|
||||
return emoji
|
||||
}
|
||||
|
||||
func EmojiListToJson(emojiList []*Emoji) string {
|
||||
b, _ := json.Marshal(emojiList)
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func EmojiListFromJson(data io.Reader) []*Emoji {
|
||||
var emojiList []*Emoji
|
||||
json.NewDecoder(data).Decode(&emojiList)
|
||||
return emojiList
|
||||
}
|
7
vendor/github.com/mattermost/mattermost-server/v5/model/emoji_data.go
generated
vendored
7
vendor/github.com/mattermost/mattermost-server/v5/model/emoji_data.go
generated
vendored
File diff suppressed because one or more lines are too long
25
vendor/github.com/mattermost/mattermost-server/v5/model/emoji_search.go
generated
vendored
25
vendor/github.com/mattermost/mattermost-server/v5/model/emoji_search.go
generated
vendored
@ -1,25 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
)
|
||||
|
||||
type EmojiSearch struct {
|
||||
Term string `json:"term"`
|
||||
PrefixOnly bool `json:"prefix_only"`
|
||||
}
|
||||
|
||||
func (es *EmojiSearch) ToJson() string {
|
||||
b, _ := json.Marshal(es)
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func EmojiSearchFromJson(data io.Reader) *EmojiSearch {
|
||||
var es *EmojiSearch
|
||||
json.NewDecoder(data).Decode(&es)
|
||||
return es
|
||||
}
|
94
vendor/github.com/mattermost/mattermost-server/v5/model/feature_flags.go
generated
vendored
94
vendor/github.com/mattermost/mattermost-server/v5/model/feature_flags.go
generated
vendored
@ -1,94 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type FeatureFlags struct {
|
||||
// Exists only for unit and manual testing.
|
||||
// When set to a value, will be returned by the ping endpoint.
|
||||
TestFeature string
|
||||
// Exists only for testing bool functionality. Boolean feature flags interpret "on" or "true" as true and
|
||||
// all other values as false.
|
||||
TestBoolFeature bool
|
||||
|
||||
// Toggle on and off scheduled jobs for cloud user limit emails see MM-29999
|
||||
CloudDelinquentEmailJobsEnabled bool
|
||||
|
||||
// Toggle on and off support for Collapsed Threads
|
||||
CollapsedThreads bool
|
||||
|
||||
// Enable the remote cluster service for shared channels.
|
||||
EnableRemoteClusterService bool
|
||||
|
||||
// AppsEnabled toggle the Apps framework functionalities both in server and client side
|
||||
AppsEnabled bool
|
||||
|
||||
// Feature flags to control plugin versions
|
||||
PluginIncidentManagement string `plugin_id:"com.mattermost.plugin-incident-management"`
|
||||
PluginApps string `plugin_id:"com.mattermost.apps"`
|
||||
PluginFocalboard string `plugin_id:"focalboard"`
|
||||
|
||||
// Enable timed dnd support for user status
|
||||
TimedDND bool
|
||||
}
|
||||
|
||||
func (f *FeatureFlags) SetDefaults() {
|
||||
f.TestFeature = "off"
|
||||
f.TestBoolFeature = false
|
||||
f.CloudDelinquentEmailJobsEnabled = false
|
||||
f.CollapsedThreads = true
|
||||
f.EnableRemoteClusterService = false
|
||||
f.AppsEnabled = false
|
||||
f.PluginIncidentManagement = "1.16.1"
|
||||
f.PluginApps = ""
|
||||
f.PluginFocalboard = ""
|
||||
f.TimedDND = false
|
||||
}
|
||||
|
||||
func (f *FeatureFlags) Plugins() map[string]string {
|
||||
rFFVal := reflect.ValueOf(f).Elem()
|
||||
rFFType := reflect.TypeOf(f).Elem()
|
||||
|
||||
pluginVersions := make(map[string]string)
|
||||
for i := 0; i < rFFVal.NumField(); i++ {
|
||||
rFieldVal := rFFVal.Field(i)
|
||||
rFieldType := rFFType.Field(i)
|
||||
|
||||
pluginId, hasPluginId := rFieldType.Tag.Lookup("plugin_id")
|
||||
if !hasPluginId {
|
||||
continue
|
||||
}
|
||||
|
||||
pluginVersions[pluginId] = rFieldVal.String()
|
||||
}
|
||||
|
||||
return pluginVersions
|
||||
}
|
||||
|
||||
// ToMap returns the feature flags as a map[string]string
|
||||
// Supports boolean and string feature flags.
|
||||
func (f *FeatureFlags) ToMap() map[string]string {
|
||||
refStructVal := reflect.ValueOf(*f)
|
||||
refStructType := reflect.TypeOf(*f)
|
||||
ret := make(map[string]string)
|
||||
for i := 0; i < refStructVal.NumField(); i++ {
|
||||
refFieldVal := refStructVal.Field(i)
|
||||
if !refFieldVal.IsValid() {
|
||||
continue
|
||||
}
|
||||
refFieldType := refStructType.Field(i)
|
||||
switch refFieldType.Type.Kind() {
|
||||
case reflect.Bool:
|
||||
ret[refFieldType.Name] = strconv.FormatBool(refFieldVal.Bool())
|
||||
default:
|
||||
ret[refFieldType.Name] = refFieldVal.String()
|
||||
}
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
29
vendor/github.com/mattermost/mattermost-server/v5/model/file.go
generated
vendored
29
vendor/github.com/mattermost/mattermost-server/v5/model/file.go
generated
vendored
@ -1,29 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
)
|
||||
|
||||
const (
|
||||
MaxImageSize = int64(6048 * 4032) // 24 megapixels, roughly 36MB as a raw image
|
||||
)
|
||||
|
||||
type FileUploadResponse struct {
|
||||
FileInfos []*FileInfo `json:"file_infos"`
|
||||
ClientIds []string `json:"client_ids"`
|
||||
}
|
||||
|
||||
func FileUploadResponseFromJson(data io.Reader) *FileUploadResponse {
|
||||
var o *FileUploadResponse
|
||||
json.NewDecoder(data).Decode(&o)
|
||||
return o
|
||||
}
|
||||
|
||||
func (o *FileUploadResponse) ToJson() string {
|
||||
b, _ := json.Marshal(o)
|
||||
return string(b)
|
||||
}
|
215
vendor/github.com/mattermost/mattermost-server/v5/model/file_info.go
generated
vendored
215
vendor/github.com/mattermost/mattermost-server/v5/model/file_info.go
generated
vendored
@ -1,215 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"image"
|
||||
"image/gif"
|
||||
"io"
|
||||
"mime"
|
||||
"net/http"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
FILEINFO_SORT_BY_CREATED = "CreateAt"
|
||||
FILEINFO_SORT_BY_SIZE = "Size"
|
||||
)
|
||||
|
||||
// GetFileInfosOptions contains options for getting FileInfos
|
||||
type GetFileInfosOptions struct {
|
||||
// UserIds optionally limits the FileInfos to those created by the given users.
|
||||
UserIds []string `json:"user_ids"`
|
||||
// ChannelIds optionally limits the FileInfos to those created in the given channels.
|
||||
ChannelIds []string `json:"channel_ids"`
|
||||
// Since optionally limits FileInfos to those created at or after the given time, specified as Unix time in milliseconds.
|
||||
Since int64 `json:"since"`
|
||||
// IncludeDeleted if set includes deleted FileInfos.
|
||||
IncludeDeleted bool `json:"include_deleted"`
|
||||
// SortBy sorts the FileInfos by this field. The default is to sort by date created.
|
||||
SortBy string `json:"sort_by"`
|
||||
// SortDescending changes the sort direction to descending order when true.
|
||||
SortDescending bool `json:"sort_descending"`
|
||||
}
|
||||
|
||||
type FileInfo struct {
|
||||
Id string `json:"id"`
|
||||
CreatorId string `json:"user_id"`
|
||||
PostId string `json:"post_id,omitempty"`
|
||||
ChannelId string `db:"-" json:"channel_id"`
|
||||
CreateAt int64 `json:"create_at"`
|
||||
UpdateAt int64 `json:"update_at"`
|
||||
DeleteAt int64 `json:"delete_at"`
|
||||
Path string `json:"-"` // not sent back to the client
|
||||
ThumbnailPath string `json:"-"` // not sent back to the client
|
||||
PreviewPath string `json:"-"` // not sent back to the client
|
||||
Name string `json:"name"`
|
||||
Extension string `json:"extension"`
|
||||
Size int64 `json:"size"`
|
||||
MimeType string `json:"mime_type"`
|
||||
Width int `json:"width,omitempty"`
|
||||
Height int `json:"height,omitempty"`
|
||||
HasPreviewImage bool `json:"has_preview_image,omitempty"`
|
||||
MiniPreview *[]byte `json:"mini_preview"` // declared as *[]byte to avoid postgres/mysql differences in deserialization
|
||||
Content string `json:"-"`
|
||||
RemoteId *string `json:"remote_id"`
|
||||
}
|
||||
|
||||
func (fi *FileInfo) ToJson() string {
|
||||
b, _ := json.Marshal(fi)
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func FileInfoFromJson(data io.Reader) *FileInfo {
|
||||
decoder := json.NewDecoder(data)
|
||||
|
||||
var fi FileInfo
|
||||
if err := decoder.Decode(&fi); err != nil {
|
||||
return nil
|
||||
}
|
||||
return &fi
|
||||
}
|
||||
|
||||
func FileInfosToJson(infos []*FileInfo) string {
|
||||
b, _ := json.Marshal(infos)
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func FileInfosFromJson(data io.Reader) []*FileInfo {
|
||||
decoder := json.NewDecoder(data)
|
||||
|
||||
var infos []*FileInfo
|
||||
if err := decoder.Decode(&infos); err != nil {
|
||||
return nil
|
||||
}
|
||||
return infos
|
||||
}
|
||||
|
||||
func (fi *FileInfo) PreSave() {
|
||||
if fi.Id == "" {
|
||||
fi.Id = NewId()
|
||||
}
|
||||
|
||||
if fi.CreateAt == 0 {
|
||||
fi.CreateAt = GetMillis()
|
||||
}
|
||||
|
||||
if fi.UpdateAt < fi.CreateAt {
|
||||
fi.UpdateAt = fi.CreateAt
|
||||
}
|
||||
|
||||
if fi.RemoteId == nil {
|
||||
fi.RemoteId = NewString("")
|
||||
}
|
||||
}
|
||||
|
||||
func (fi *FileInfo) IsValid() *AppError {
|
||||
if !IsValidId(fi.Id) {
|
||||
return NewAppError("FileInfo.IsValid", "model.file_info.is_valid.id.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if !IsValidId(fi.CreatorId) && fi.CreatorId != "nouser" {
|
||||
return NewAppError("FileInfo.IsValid", "model.file_info.is_valid.user_id.app_error", nil, "id="+fi.Id, http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if fi.PostId != "" && !IsValidId(fi.PostId) {
|
||||
return NewAppError("FileInfo.IsValid", "model.file_info.is_valid.post_id.app_error", nil, "id="+fi.Id, http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if fi.CreateAt == 0 {
|
||||
return NewAppError("FileInfo.IsValid", "model.file_info.is_valid.create_at.app_error", nil, "id="+fi.Id, http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if fi.UpdateAt == 0 {
|
||||
return NewAppError("FileInfo.IsValid", "model.file_info.is_valid.update_at.app_error", nil, "id="+fi.Id, http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if fi.Path == "" {
|
||||
return NewAppError("FileInfo.IsValid", "model.file_info.is_valid.path.app_error", nil, "id="+fi.Id, http.StatusBadRequest)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (fi *FileInfo) IsImage() bool {
|
||||
return strings.HasPrefix(fi.MimeType, "image")
|
||||
}
|
||||
|
||||
func NewInfo(name string) *FileInfo {
|
||||
info := &FileInfo{
|
||||
Name: name,
|
||||
}
|
||||
|
||||
extension := strings.ToLower(filepath.Ext(name))
|
||||
info.MimeType = mime.TypeByExtension(extension)
|
||||
|
||||
if extension != "" && extension[0] == '.' {
|
||||
// The client expects a file extension without the leading period
|
||||
info.Extension = extension[1:]
|
||||
} else {
|
||||
info.Extension = extension
|
||||
}
|
||||
|
||||
return info
|
||||
}
|
||||
|
||||
func GetInfoForBytes(name string, data io.ReadSeeker, size int) (*FileInfo, *AppError) {
|
||||
info := &FileInfo{
|
||||
Name: name,
|
||||
Size: int64(size),
|
||||
}
|
||||
var err *AppError
|
||||
|
||||
extension := strings.ToLower(filepath.Ext(name))
|
||||
info.MimeType = mime.TypeByExtension(extension)
|
||||
|
||||
if extension != "" && extension[0] == '.' {
|
||||
// The client expects a file extension without the leading period
|
||||
info.Extension = extension[1:]
|
||||
} else {
|
||||
info.Extension = extension
|
||||
}
|
||||
|
||||
if info.IsImage() {
|
||||
// Only set the width and height if it's actually an image that we can understand
|
||||
if config, _, err := image.DecodeConfig(data); err == nil {
|
||||
info.Width = config.Width
|
||||
info.Height = config.Height
|
||||
|
||||
if info.MimeType == "image/gif" {
|
||||
// Just show the gif itself instead of a preview image for animated gifs
|
||||
data.Seek(0, io.SeekStart)
|
||||
gifConfig, err := gif.DecodeAll(data)
|
||||
if err != nil {
|
||||
// Still return the rest of the info even though it doesn't appear to be an actual gif
|
||||
info.HasPreviewImage = true
|
||||
return info, NewAppError("GetInfoForBytes", "model.file_info.get.gif.app_error", nil, err.Error(), http.StatusBadRequest)
|
||||
}
|
||||
info.HasPreviewImage = len(gifConfig.Image) == 1
|
||||
} else {
|
||||
info.HasPreviewImage = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return info, err
|
||||
}
|
||||
|
||||
func GetEtagForFileInfos(infos []*FileInfo) string {
|
||||
if len(infos) == 0 {
|
||||
return Etag()
|
||||
}
|
||||
|
||||
var maxUpdateAt int64
|
||||
|
||||
for _, info := range infos {
|
||||
if info.UpdateAt > maxUpdateAt {
|
||||
maxUpdateAt = info.UpdateAt
|
||||
}
|
||||
}
|
||||
|
||||
return Etag(infos[0].PostId, maxUpdateAt)
|
||||
}
|
128
vendor/github.com/mattermost/mattermost-server/v5/model/file_info_list.go
generated
vendored
128
vendor/github.com/mattermost/mattermost-server/v5/model/file_info_list.go
generated
vendored
@ -1,128 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"sort"
|
||||
)
|
||||
|
||||
type FileInfoList struct {
|
||||
Order []string `json:"order"`
|
||||
FileInfos map[string]*FileInfo `json:"file_infos"`
|
||||
NextFileInfoId string `json:"next_file_info_id"`
|
||||
PrevFileInfoId string `json:"prev_file_info_id"`
|
||||
}
|
||||
|
||||
func NewFileInfoList() *FileInfoList {
|
||||
return &FileInfoList{
|
||||
Order: make([]string, 0),
|
||||
FileInfos: make(map[string]*FileInfo),
|
||||
NextFileInfoId: "",
|
||||
PrevFileInfoId: "",
|
||||
}
|
||||
}
|
||||
|
||||
func (o *FileInfoList) ToSlice() []*FileInfo {
|
||||
var fileInfos []*FileInfo
|
||||
for _, id := range o.Order {
|
||||
fileInfos = append(fileInfos, o.FileInfos[id])
|
||||
}
|
||||
return fileInfos
|
||||
}
|
||||
|
||||
func (o *FileInfoList) ToJson() string {
|
||||
b, err := json.Marshal(o)
|
||||
if err != nil {
|
||||
return ""
|
||||
} else {
|
||||
return string(b)
|
||||
}
|
||||
}
|
||||
|
||||
func (o *FileInfoList) MakeNonNil() {
|
||||
if o.Order == nil {
|
||||
o.Order = make([]string, 0)
|
||||
}
|
||||
|
||||
if o.FileInfos == nil {
|
||||
o.FileInfos = make(map[string]*FileInfo)
|
||||
}
|
||||
}
|
||||
|
||||
func (o *FileInfoList) AddOrder(id string) {
|
||||
if o.Order == nil {
|
||||
o.Order = make([]string, 0, 128)
|
||||
}
|
||||
|
||||
o.Order = append(o.Order, id)
|
||||
}
|
||||
|
||||
func (o *FileInfoList) AddFileInfo(fileInfo *FileInfo) {
|
||||
if o.FileInfos == nil {
|
||||
o.FileInfos = make(map[string]*FileInfo)
|
||||
}
|
||||
|
||||
o.FileInfos[fileInfo.Id] = fileInfo
|
||||
}
|
||||
|
||||
func (o *FileInfoList) UniqueOrder() {
|
||||
keys := make(map[string]bool)
|
||||
order := []string{}
|
||||
for _, fileInfoId := range o.Order {
|
||||
if _, value := keys[fileInfoId]; !value {
|
||||
keys[fileInfoId] = true
|
||||
order = append(order, fileInfoId)
|
||||
}
|
||||
}
|
||||
|
||||
o.Order = order
|
||||
}
|
||||
|
||||
func (o *FileInfoList) Extend(other *FileInfoList) {
|
||||
for fileInfoId := range other.FileInfos {
|
||||
o.AddFileInfo(other.FileInfos[fileInfoId])
|
||||
}
|
||||
|
||||
for _, fileInfoId := range other.Order {
|
||||
o.AddOrder(fileInfoId)
|
||||
}
|
||||
|
||||
o.UniqueOrder()
|
||||
}
|
||||
|
||||
func (o *FileInfoList) SortByCreateAt() {
|
||||
sort.Slice(o.Order, func(i, j int) bool {
|
||||
return o.FileInfos[o.Order[i]].CreateAt > o.FileInfos[o.Order[j]].CreateAt
|
||||
})
|
||||
}
|
||||
|
||||
func (o *FileInfoList) Etag() string {
|
||||
id := "0"
|
||||
var t int64 = 0
|
||||
|
||||
for _, v := range o.FileInfos {
|
||||
if v.UpdateAt > t {
|
||||
t = v.UpdateAt
|
||||
id = v.Id
|
||||
} else if v.UpdateAt == t && v.Id > id {
|
||||
t = v.UpdateAt
|
||||
id = v.Id
|
||||
}
|
||||
}
|
||||
|
||||
orderId := ""
|
||||
if len(o.Order) > 0 {
|
||||
orderId = o.Order[0]
|
||||
}
|
||||
|
||||
return Etag(orderId, id, t)
|
||||
}
|
||||
|
||||
func FileInfoListFromJson(data io.Reader) *FileInfoList {
|
||||
var o *FileInfoList
|
||||
json.NewDecoder(data).Decode(&o)
|
||||
return o
|
||||
}
|
37
vendor/github.com/mattermost/mattermost-server/v5/model/file_info_search_results.go
generated
vendored
37
vendor/github.com/mattermost/mattermost-server/v5/model/file_info_search_results.go
generated
vendored
@ -1,37 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
)
|
||||
|
||||
type FileInfoSearchMatches map[string][]string
|
||||
|
||||
type FileInfoSearchResults struct {
|
||||
*FileInfoList
|
||||
Matches FileInfoSearchMatches `json:"matches"`
|
||||
}
|
||||
|
||||
func MakeFileInfoSearchResults(fileInfos *FileInfoList, matches FileInfoSearchMatches) *FileInfoSearchResults {
|
||||
return &FileInfoSearchResults{
|
||||
fileInfos,
|
||||
matches,
|
||||
}
|
||||
}
|
||||
|
||||
func (o *FileInfoSearchResults) ToJson() string {
|
||||
b, err := json.Marshal(o)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func FileInfoSearchResultsFromJson(data io.Reader) *FileInfoSearchResults {
|
||||
var o *FileInfoSearchResults
|
||||
json.NewDecoder(data).Decode(&o)
|
||||
return o
|
||||
}
|
8
vendor/github.com/mattermost/mattermost-server/v5/model/gitlab.go
generated
vendored
8
vendor/github.com/mattermost/mattermost-server/v5/model/gitlab.go
generated
vendored
@ -1,8 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
const (
|
||||
USER_AUTH_SERVICE_GITLAB = "gitlab"
|
||||
)
|
221
vendor/github.com/mattermost/mattermost-server/v5/model/group.go
generated
vendored
221
vendor/github.com/mattermost/mattermost-server/v5/model/group.go
generated
vendored
@ -1,221 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
const (
|
||||
GroupSourceLdap GroupSource = "ldap"
|
||||
|
||||
GroupNameMaxLength = 64
|
||||
GroupSourceMaxLength = 64
|
||||
GroupDisplayNameMaxLength = 128
|
||||
GroupDescriptionMaxLength = 1024
|
||||
GroupRemoteIDMaxLength = 48
|
||||
)
|
||||
|
||||
type GroupSource string
|
||||
|
||||
var allGroupSources = []GroupSource{
|
||||
GroupSourceLdap,
|
||||
}
|
||||
|
||||
var groupSourcesRequiringRemoteID = []GroupSource{
|
||||
GroupSourceLdap,
|
||||
}
|
||||
|
||||
type Group struct {
|
||||
Id string `json:"id"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
DisplayName string `json:"display_name"`
|
||||
Description string `json:"description"`
|
||||
Source GroupSource `json:"source"`
|
||||
RemoteId string `json:"remote_id"`
|
||||
CreateAt int64 `json:"create_at"`
|
||||
UpdateAt int64 `json:"update_at"`
|
||||
DeleteAt int64 `json:"delete_at"`
|
||||
HasSyncables bool `db:"-" json:"has_syncables"`
|
||||
MemberCount *int `db:"-" json:"member_count,omitempty"`
|
||||
AllowReference bool `json:"allow_reference"`
|
||||
}
|
||||
|
||||
type GroupWithSchemeAdmin struct {
|
||||
Group
|
||||
SchemeAdmin *bool `db:"SyncableSchemeAdmin" json:"scheme_admin,omitempty"`
|
||||
}
|
||||
|
||||
type GroupsAssociatedToChannelWithSchemeAdmin struct {
|
||||
ChannelId string `json:"channel_id"`
|
||||
Group
|
||||
SchemeAdmin *bool `db:"SyncableSchemeAdmin" json:"scheme_admin,omitempty"`
|
||||
}
|
||||
type GroupsAssociatedToChannel struct {
|
||||
ChannelId string `json:"channel_id"`
|
||||
Groups []*GroupWithSchemeAdmin `json:"groups"`
|
||||
}
|
||||
|
||||
type GroupPatch struct {
|
||||
Name *string `json:"name"`
|
||||
DisplayName *string `json:"display_name"`
|
||||
Description *string `json:"description"`
|
||||
AllowReference *bool `json:"allow_reference"`
|
||||
}
|
||||
|
||||
type LdapGroupSearchOpts struct {
|
||||
Q string
|
||||
IsLinked *bool
|
||||
IsConfigured *bool
|
||||
}
|
||||
|
||||
type GroupSearchOpts struct {
|
||||
Q string
|
||||
NotAssociatedToTeam string
|
||||
NotAssociatedToChannel string
|
||||
IncludeMemberCount bool
|
||||
FilterAllowReference bool
|
||||
PageOpts *PageOpts
|
||||
Since int64
|
||||
|
||||
// FilterParentTeamPermitted filters the groups to the intersect of the
|
||||
// set associated to the parent team and those returned by the query.
|
||||
// If the parent team is not group-constrained or if NotAssociatedToChannel
|
||||
// is not set then this option is ignored.
|
||||
FilterParentTeamPermitted bool
|
||||
}
|
||||
|
||||
type PageOpts struct {
|
||||
Page int
|
||||
PerPage int
|
||||
}
|
||||
|
||||
type GroupStats struct {
|
||||
GroupID string `json:"group_id"`
|
||||
TotalMemberCount int64 `json:"total_member_count"`
|
||||
}
|
||||
|
||||
func (group *Group) Patch(patch *GroupPatch) {
|
||||
if patch.Name != nil {
|
||||
group.Name = patch.Name
|
||||
}
|
||||
if patch.DisplayName != nil {
|
||||
group.DisplayName = *patch.DisplayName
|
||||
}
|
||||
if patch.Description != nil {
|
||||
group.Description = *patch.Description
|
||||
}
|
||||
if patch.AllowReference != nil {
|
||||
group.AllowReference = *patch.AllowReference
|
||||
}
|
||||
}
|
||||
|
||||
func (group *Group) IsValidForCreate() *AppError {
|
||||
err := group.IsValidName()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if l := len(group.DisplayName); l == 0 || l > GroupDisplayNameMaxLength {
|
||||
return NewAppError("Group.IsValidForCreate", "model.group.display_name.app_error", map[string]interface{}{"GroupDisplayNameMaxLength": GroupDisplayNameMaxLength}, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if len(group.Description) > GroupDescriptionMaxLength {
|
||||
return NewAppError("Group.IsValidForCreate", "model.group.description.app_error", map[string]interface{}{"GroupDescriptionMaxLength": GroupDescriptionMaxLength}, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
isValidSource := false
|
||||
for _, groupSource := range allGroupSources {
|
||||
if group.Source == groupSource {
|
||||
isValidSource = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !isValidSource {
|
||||
return NewAppError("Group.IsValidForCreate", "model.group.source.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if len(group.RemoteId) > GroupRemoteIDMaxLength || (group.RemoteId == "" && group.requiresRemoteId()) {
|
||||
return NewAppError("Group.IsValidForCreate", "model.group.remote_id.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (group *Group) requiresRemoteId() bool {
|
||||
for _, groupSource := range groupSourcesRequiringRemoteID {
|
||||
if groupSource == group.Source {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (group *Group) IsValidForUpdate() *AppError {
|
||||
if !IsValidId(group.Id) {
|
||||
return NewAppError("Group.IsValidForUpdate", "app.group.id.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
if group.CreateAt == 0 {
|
||||
return NewAppError("Group.IsValidForUpdate", "model.group.create_at.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
if group.UpdateAt == 0 {
|
||||
return NewAppError("Group.IsValidForUpdate", "model.group.update_at.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
if err := group.IsValidForCreate(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (group *Group) ToJson() string {
|
||||
b, _ := json.Marshal(group)
|
||||
return string(b)
|
||||
}
|
||||
|
||||
var validGroupnameChars = regexp.MustCompile(`^[a-z0-9\.\-_]+$`)
|
||||
|
||||
func (group *Group) IsValidName() *AppError {
|
||||
|
||||
if group.Name == nil {
|
||||
if group.AllowReference {
|
||||
return NewAppError("Group.IsValidName", "model.group.name.app_error", map[string]interface{}{"GroupNameMaxLength": GroupNameMaxLength}, "", http.StatusBadRequest)
|
||||
}
|
||||
} else {
|
||||
if l := len(*group.Name); l == 0 || l > GroupNameMaxLength {
|
||||
return NewAppError("Group.IsValidName", "model.group.name.invalid_length.app_error", map[string]interface{}{"GroupNameMaxLength": GroupNameMaxLength}, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if !validGroupnameChars.MatchString(*group.Name) {
|
||||
return NewAppError("Group.IsValidName", "model.group.name.invalid_chars.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func GroupFromJson(data io.Reader) *Group {
|
||||
var group *Group
|
||||
json.NewDecoder(data).Decode(&group)
|
||||
return group
|
||||
}
|
||||
|
||||
func GroupsFromJson(data io.Reader) []*Group {
|
||||
var groups []*Group
|
||||
json.NewDecoder(data).Decode(&groups)
|
||||
return groups
|
||||
}
|
||||
|
||||
func GroupPatchFromJson(data io.Reader) *GroupPatch {
|
||||
var groupPatch *GroupPatch
|
||||
json.NewDecoder(data).Decode(&groupPatch)
|
||||
return groupPatch
|
||||
}
|
||||
|
||||
func GroupStatsFromJson(data io.Reader) *GroupStats {
|
||||
var groupStats *GroupStats
|
||||
json.NewDecoder(data).Decode(&groupStats)
|
||||
return groupStats
|
||||
}
|
23
vendor/github.com/mattermost/mattermost-server/v5/model/group_member.go
generated
vendored
23
vendor/github.com/mattermost/mattermost-server/v5/model/group_member.go
generated
vendored
@ -1,23 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import "net/http"
|
||||
|
||||
type GroupMember struct {
|
||||
GroupId string `json:"group_id"`
|
||||
UserId string `json:"user_id"`
|
||||
CreateAt int64 `json:"create_at"`
|
||||
DeleteAt int64 `json:"delete_at"`
|
||||
}
|
||||
|
||||
func (gm *GroupMember) IsValid() *AppError {
|
||||
if !IsValidId(gm.GroupId) {
|
||||
return NewAppError("GroupMember.IsValid", "model.group_member.group_id.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
if !IsValidId(gm.UserId) {
|
||||
return NewAppError("GroupMember.IsValid", "model.group_member.user_id.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
return nil
|
||||
}
|
191
vendor/github.com/mattermost/mattermost-server/v5/model/group_syncable.go
generated
vendored
191
vendor/github.com/mattermost/mattermost-server/v5/model/group_syncable.go
generated
vendored
@ -1,191 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type GroupSyncableType string
|
||||
|
||||
const (
|
||||
GroupSyncableTypeTeam GroupSyncableType = "Team"
|
||||
GroupSyncableTypeChannel GroupSyncableType = "Channel"
|
||||
)
|
||||
|
||||
func (gst GroupSyncableType) String() string {
|
||||
return string(gst)
|
||||
}
|
||||
|
||||
type GroupSyncable struct {
|
||||
GroupId string `json:"group_id"`
|
||||
|
||||
// SyncableId represents the Id of the model that is being synced with the group, for example a ChannelId or
|
||||
// TeamId.
|
||||
SyncableId string `db:"-" json:"-"`
|
||||
|
||||
AutoAdd bool `json:"auto_add"`
|
||||
SchemeAdmin bool `json:"scheme_admin"`
|
||||
CreateAt int64 `json:"create_at"`
|
||||
DeleteAt int64 `json:"delete_at"`
|
||||
UpdateAt int64 `json:"update_at"`
|
||||
Type GroupSyncableType `db:"-" json:"-"`
|
||||
|
||||
// Values joined in from the associated team and/or channel
|
||||
ChannelDisplayName string `db:"-" json:"-"`
|
||||
TeamDisplayName string `db:"-" json:"-"`
|
||||
TeamType string `db:"-" json:"-"`
|
||||
ChannelType string `db:"-" json:"-"`
|
||||
TeamID string `db:"-" json:"-"`
|
||||
}
|
||||
|
||||
func (syncable *GroupSyncable) IsValid() *AppError {
|
||||
if !IsValidId(syncable.GroupId) {
|
||||
return NewAppError("GroupSyncable.SyncableIsValid", "model.group_syncable.group_id.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
if !IsValidId(syncable.SyncableId) {
|
||||
return NewAppError("GroupSyncable.SyncableIsValid", "model.group_syncable.syncable_id.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (syncable *GroupSyncable) UnmarshalJSON(b []byte) error {
|
||||
var kvp map[string]interface{}
|
||||
err := json.Unmarshal(b, &kvp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var channelId string
|
||||
var teamId string
|
||||
for key, value := range kvp {
|
||||
switch key {
|
||||
case "team_id":
|
||||
teamId = value.(string)
|
||||
case "channel_id":
|
||||
channelId = value.(string)
|
||||
case "group_id":
|
||||
syncable.GroupId = value.(string)
|
||||
case "auto_add":
|
||||
syncable.AutoAdd = value.(bool)
|
||||
default:
|
||||
}
|
||||
}
|
||||
if channelId != "" {
|
||||
syncable.TeamID = teamId
|
||||
syncable.SyncableId = channelId
|
||||
syncable.Type = GroupSyncableTypeChannel
|
||||
} else {
|
||||
syncable.SyncableId = teamId
|
||||
syncable.Type = GroupSyncableTypeTeam
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (syncable *GroupSyncable) MarshalJSON() ([]byte, error) {
|
||||
type Alias GroupSyncable
|
||||
switch syncable.Type {
|
||||
case GroupSyncableTypeTeam:
|
||||
return json.Marshal(&struct {
|
||||
TeamID string `json:"team_id"`
|
||||
TeamDisplayName string `json:"team_display_name,omitempty"`
|
||||
TeamType string `json:"team_type,omitempty"`
|
||||
Type GroupSyncableType `json:"type,omitempty"`
|
||||
*Alias
|
||||
}{
|
||||
TeamDisplayName: syncable.TeamDisplayName,
|
||||
TeamType: syncable.TeamType,
|
||||
TeamID: syncable.SyncableId,
|
||||
Type: syncable.Type,
|
||||
Alias: (*Alias)(syncable),
|
||||
})
|
||||
case GroupSyncableTypeChannel:
|
||||
return json.Marshal(&struct {
|
||||
ChannelID string `json:"channel_id"`
|
||||
ChannelDisplayName string `json:"channel_display_name,omitempty"`
|
||||
ChannelType string `json:"channel_type,omitempty"`
|
||||
Type GroupSyncableType `json:"type,omitempty"`
|
||||
|
||||
TeamID string `json:"team_id,omitempty"`
|
||||
TeamDisplayName string `json:"team_display_name,omitempty"`
|
||||
TeamType string `json:"team_type,omitempty"`
|
||||
|
||||
*Alias
|
||||
}{
|
||||
ChannelID: syncable.SyncableId,
|
||||
ChannelDisplayName: syncable.ChannelDisplayName,
|
||||
ChannelType: syncable.ChannelType,
|
||||
Type: syncable.Type,
|
||||
|
||||
TeamID: syncable.TeamID,
|
||||
TeamDisplayName: syncable.TeamDisplayName,
|
||||
TeamType: syncable.TeamType,
|
||||
|
||||
Alias: (*Alias)(syncable),
|
||||
})
|
||||
default:
|
||||
return nil, &json.MarshalerError{
|
||||
Err: fmt.Errorf("unknown syncable type: %s", syncable.Type),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type GroupSyncablePatch struct {
|
||||
AutoAdd *bool `json:"auto_add"`
|
||||
SchemeAdmin *bool `json:"scheme_admin"`
|
||||
}
|
||||
|
||||
func (syncable *GroupSyncable) Patch(patch *GroupSyncablePatch) {
|
||||
if patch.AutoAdd != nil {
|
||||
syncable.AutoAdd = *patch.AutoAdd
|
||||
}
|
||||
if patch.SchemeAdmin != nil {
|
||||
syncable.SchemeAdmin = *patch.SchemeAdmin
|
||||
}
|
||||
}
|
||||
|
||||
type UserTeamIDPair struct {
|
||||
UserID string
|
||||
TeamID string
|
||||
}
|
||||
|
||||
type UserChannelIDPair struct {
|
||||
UserID string
|
||||
ChannelID string
|
||||
}
|
||||
|
||||
func GroupSyncableFromJson(data io.Reader) *GroupSyncable {
|
||||
groupSyncable := &GroupSyncable{}
|
||||
bodyBytes, _ := ioutil.ReadAll(data)
|
||||
json.Unmarshal(bodyBytes, groupSyncable)
|
||||
return groupSyncable
|
||||
}
|
||||
|
||||
func GroupSyncablesFromJson(data io.Reader) []*GroupSyncable {
|
||||
groupSyncables := []*GroupSyncable{}
|
||||
bodyBytes, _ := ioutil.ReadAll(data)
|
||||
json.Unmarshal(bodyBytes, &groupSyncables)
|
||||
return groupSyncables
|
||||
}
|
||||
|
||||
func NewGroupTeam(groupID, teamID string, autoAdd bool) *GroupSyncable {
|
||||
return &GroupSyncable{
|
||||
GroupId: groupID,
|
||||
SyncableId: teamID,
|
||||
Type: GroupSyncableTypeTeam,
|
||||
AutoAdd: autoAdd,
|
||||
}
|
||||
}
|
||||
|
||||
func NewGroupChannel(groupID, channelID string, autoAdd bool) *GroupSyncable {
|
||||
return &GroupSyncable{
|
||||
GroupId: groupID,
|
||||
SyncableId: channelID,
|
||||
Type: GroupSyncableTypeChannel,
|
||||
AutoAdd: autoAdd,
|
||||
}
|
||||
}
|
53
vendor/github.com/mattermost/mattermost-server/v5/model/guest_invite.go
generated
vendored
53
vendor/github.com/mattermost/mattermost-server/v5/model/guest_invite.go
generated
vendored
@ -1,53 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type GuestsInvite struct {
|
||||
Emails []string `json:"emails"`
|
||||
Channels []string `json:"channels"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
// IsValid validates the user and returns an error if it isn't configured
|
||||
// correctly.
|
||||
func (i *GuestsInvite) IsValid() *AppError {
|
||||
if len(i.Emails) == 0 {
|
||||
return NewAppError("GuestsInvite.IsValid", "model.guest.is_valid.emails.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
for _, email := range i.Emails {
|
||||
if len(email) > USER_EMAIL_MAX_LENGTH || email == "" || !IsValidEmail(email) {
|
||||
return NewAppError("GuestsInvite.IsValid", "model.guest.is_valid.email.app_error", nil, "email="+email, http.StatusBadRequest)
|
||||
}
|
||||
}
|
||||
|
||||
if len(i.Channels) == 0 {
|
||||
return NewAppError("GuestsInvite.IsValid", "model.guest.is_valid.channels.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
for _, channel := range i.Channels {
|
||||
if len(channel) != 26 {
|
||||
return NewAppError("GuestsInvite.IsValid", "model.guest.is_valid.channel.app_error", nil, "channel="+channel, http.StatusBadRequest)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GuestsInviteFromJson will decode the input and return a GuestsInvite
|
||||
func GuestsInviteFromJson(data io.Reader) *GuestsInvite {
|
||||
var i *GuestsInvite
|
||||
json.NewDecoder(data).Decode(&i)
|
||||
return i
|
||||
}
|
||||
|
||||
func (i *GuestsInvite) ToJson() string {
|
||||
b, _ := json.Marshal(i)
|
||||
return string(b)
|
||||
}
|
215
vendor/github.com/mattermost/mattermost-server/v5/model/incoming_webhook.go
generated
vendored
215
vendor/github.com/mattermost/mattermost-server/v5/model/incoming_webhook.go
generated
vendored
@ -1,215 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
const (
|
||||
DEFAULT_WEBHOOK_USERNAME = "webhook"
|
||||
)
|
||||
|
||||
type IncomingWebhook struct {
|
||||
Id string `json:"id"`
|
||||
CreateAt int64 `json:"create_at"`
|
||||
UpdateAt int64 `json:"update_at"`
|
||||
DeleteAt int64 `json:"delete_at"`
|
||||
UserId string `json:"user_id"`
|
||||
ChannelId string `json:"channel_id"`
|
||||
TeamId string `json:"team_id"`
|
||||
DisplayName string `json:"display_name"`
|
||||
Description string `json:"description"`
|
||||
Username string `json:"username"`
|
||||
IconURL string `json:"icon_url"`
|
||||
ChannelLocked bool `json:"channel_locked"`
|
||||
}
|
||||
|
||||
type IncomingWebhookRequest struct {
|
||||
Text string `json:"text"`
|
||||
Username string `json:"username"`
|
||||
IconURL string `json:"icon_url"`
|
||||
ChannelName string `json:"channel"`
|
||||
Props StringInterface `json:"props"`
|
||||
Attachments []*SlackAttachment `json:"attachments"`
|
||||
Type string `json:"type"`
|
||||
IconEmoji string `json:"icon_emoji"`
|
||||
}
|
||||
|
||||
func (o *IncomingWebhook) ToJson() string {
|
||||
b, _ := json.Marshal(o)
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func IncomingWebhookFromJson(data io.Reader) *IncomingWebhook {
|
||||
var o *IncomingWebhook
|
||||
json.NewDecoder(data).Decode(&o)
|
||||
return o
|
||||
}
|
||||
|
||||
func IncomingWebhookListToJson(l []*IncomingWebhook) string {
|
||||
b, _ := json.Marshal(l)
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func IncomingWebhookListFromJson(data io.Reader) []*IncomingWebhook {
|
||||
var o []*IncomingWebhook
|
||||
json.NewDecoder(data).Decode(&o)
|
||||
return o
|
||||
}
|
||||
|
||||
func (o *IncomingWebhook) IsValid() *AppError {
|
||||
|
||||
if !IsValidId(o.Id) {
|
||||
return NewAppError("IncomingWebhook.IsValid", "model.incoming_hook.id.app_error", nil, "", http.StatusBadRequest)
|
||||
|
||||
}
|
||||
|
||||
if o.CreateAt == 0 {
|
||||
return NewAppError("IncomingWebhook.IsValid", "model.incoming_hook.create_at.app_error", nil, "id="+o.Id, http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if o.UpdateAt == 0 {
|
||||
return NewAppError("IncomingWebhook.IsValid", "model.incoming_hook.update_at.app_error", nil, "id="+o.Id, http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if !IsValidId(o.UserId) {
|
||||
return NewAppError("IncomingWebhook.IsValid", "model.incoming_hook.user_id.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if !IsValidId(o.ChannelId) {
|
||||
return NewAppError("IncomingWebhook.IsValid", "model.incoming_hook.channel_id.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if !IsValidId(o.TeamId) {
|
||||
return NewAppError("IncomingWebhook.IsValid", "model.incoming_hook.team_id.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if len(o.DisplayName) > 64 {
|
||||
return NewAppError("IncomingWebhook.IsValid", "model.incoming_hook.display_name.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if len(o.Description) > 500 {
|
||||
return NewAppError("IncomingWebhook.IsValid", "model.incoming_hook.description.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if len(o.Username) > 64 {
|
||||
return NewAppError("IncomingWebhook.IsValid", "model.incoming_hook.username.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if len(o.IconURL) > 1024 {
|
||||
return NewAppError("IncomingWebhook.IsValid", "model.incoming_hook.icon_url.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *IncomingWebhook) PreSave() {
|
||||
if o.Id == "" {
|
||||
o.Id = NewId()
|
||||
}
|
||||
|
||||
o.CreateAt = GetMillis()
|
||||
o.UpdateAt = o.CreateAt
|
||||
}
|
||||
|
||||
func (o *IncomingWebhook) PreUpdate() {
|
||||
o.UpdateAt = GetMillis()
|
||||
}
|
||||
|
||||
// escapeControlCharsFromPayload escapes control chars (\n, \t) from a byte slice.
|
||||
// Context:
|
||||
// JSON strings are not supposed to contain control characters such as \n, \t,
|
||||
// ... but some incoming webhooks might still send invalid JSON and we want to
|
||||
// try to handle that. An example invalid JSON string from an incoming webhook
|
||||
// might look like this (strings for both "text" and "fallback" attributes are
|
||||
// invalid JSON strings because they contain unescaped newlines and tabs):
|
||||
// `{
|
||||
// "text": "this is a test
|
||||
// that contains a newline and tabs",
|
||||
// "attachments": [
|
||||
// {
|
||||
// "fallback": "Required plain-text summary of the attachment
|
||||
// that contains a newline and tabs",
|
||||
// "color": "#36a64f",
|
||||
// ...
|
||||
// "text": "Optional text that appears within the attachment
|
||||
// that contains a newline and tabs",
|
||||
// ...
|
||||
// "thumb_url": "http://example.com/path/to/thumb.png"
|
||||
// }
|
||||
// ]
|
||||
// }`
|
||||
// This function will search for `"key": "value"` pairs, and escape \n, \t
|
||||
// from the value.
|
||||
func escapeControlCharsFromPayload(by []byte) []byte {
|
||||
// we'll search for `"text": "..."` or `"fallback": "..."`, ...
|
||||
keys := "text|fallback|pretext|author_name|title|value"
|
||||
|
||||
// the regexp reads like this:
|
||||
// (?s): this flag let . match \n (default is false)
|
||||
// "(keys)": we search for the keys defined above
|
||||
// \s*:\s*: followed by 0..n spaces/tabs, a colon then 0..n spaces/tabs
|
||||
// ": a double-quote
|
||||
// (\\"|[^"])*: any number of times the `\"` string or any char but a double-quote
|
||||
// ": a double-quote
|
||||
r := `(?s)"(` + keys + `)"\s*:\s*"(\\"|[^"])*"`
|
||||
re := regexp.MustCompile(r)
|
||||
|
||||
// the function that will escape \n and \t on the regexp matches
|
||||
repl := func(b []byte) []byte {
|
||||
if bytes.Contains(b, []byte("\n")) {
|
||||
b = bytes.Replace(b, []byte("\n"), []byte("\\n"), -1)
|
||||
}
|
||||
if bytes.Contains(b, []byte("\t")) {
|
||||
b = bytes.Replace(b, []byte("\t"), []byte("\\t"), -1)
|
||||
}
|
||||
|
||||
return b
|
||||
}
|
||||
|
||||
return re.ReplaceAllFunc(by, repl)
|
||||
}
|
||||
|
||||
func decodeIncomingWebhookRequest(by []byte) (*IncomingWebhookRequest, error) {
|
||||
decoder := json.NewDecoder(bytes.NewReader(by))
|
||||
var o IncomingWebhookRequest
|
||||
err := decoder.Decode(&o)
|
||||
if err == nil {
|
||||
return &o, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func IncomingWebhookRequestFromJson(data io.Reader) (*IncomingWebhookRequest, *AppError) {
|
||||
buf := new(bytes.Buffer)
|
||||
buf.ReadFrom(data)
|
||||
by := buf.Bytes()
|
||||
|
||||
// Try to decode the JSON data. Only if it fails, try to escape control
|
||||
// characters from the strings contained in the JSON data.
|
||||
o, err := decodeIncomingWebhookRequest(by)
|
||||
if err != nil {
|
||||
o, err = decodeIncomingWebhookRequest(escapeControlCharsFromPayload(by))
|
||||
if err != nil {
|
||||
return nil, NewAppError("IncomingWebhookRequestFromJson", "model.incoming_hook.parse_data.app_error", nil, err.Error(), http.StatusBadRequest)
|
||||
}
|
||||
}
|
||||
|
||||
o.Attachments = StringifySlackFieldValue(o.Attachments)
|
||||
|
||||
return o, nil
|
||||
}
|
||||
|
||||
func (o *IncomingWebhookRequest) ToJson() string {
|
||||
b, err := json.Marshal(o)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return string(b)
|
||||
}
|
30
vendor/github.com/mattermost/mattermost-server/v5/model/initial_load.go
generated
vendored
30
vendor/github.com/mattermost/mattermost-server/v5/model/initial_load.go
generated
vendored
@ -1,30 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
)
|
||||
|
||||
type InitialLoad struct {
|
||||
User *User `json:"user"`
|
||||
TeamMembers []*TeamMember `json:"team_members"`
|
||||
Teams []*Team `json:"teams"`
|
||||
Preferences Preferences `json:"preferences"`
|
||||
ClientCfg map[string]string `json:"client_cfg"`
|
||||
LicenseCfg map[string]string `json:"license_cfg"`
|
||||
NoAccounts bool `json:"no_accounts"`
|
||||
}
|
||||
|
||||
func (il *InitialLoad) ToJson() string {
|
||||
b, _ := json.Marshal(il)
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func InitialLoadFromJson(data io.Reader) *InitialLoad {
|
||||
var il *InitialLoad
|
||||
json.NewDecoder(data).Decode(&il)
|
||||
return il
|
||||
}
|
532
vendor/github.com/mattermost/mattermost-server/v5/model/integration_action.go
generated
vendored
532
vendor/github.com/mattermost/mattermost-server/v5/model/integration_action.go
generated
vendored
@ -1,532 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/ecdsa"
|
||||
"crypto/rand"
|
||||
"encoding/asn1"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"math/big"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
POST_ACTION_TYPE_BUTTON = "button"
|
||||
POST_ACTION_TYPE_SELECT = "select"
|
||||
INTERACTIVE_DIALOG_TRIGGER_TIMEOUT_MILLISECONDS = 3000
|
||||
)
|
||||
|
||||
var PostActionRetainPropKeys = []string{"from_webhook", "override_username", "override_icon_url"}
|
||||
|
||||
type DoPostActionRequest struct {
|
||||
SelectedOption string `json:"selected_option,omitempty"`
|
||||
Cookie string `json:"cookie,omitempty"`
|
||||
}
|
||||
|
||||
type PostAction struct {
|
||||
// A unique Action ID. If not set, generated automatically.
|
||||
Id string `json:"id,omitempty"`
|
||||
|
||||
// The type of the interactive element. Currently supported are
|
||||
// "select" and "button".
|
||||
Type string `json:"type,omitempty"`
|
||||
|
||||
// The text on the button, or in the select placeholder.
|
||||
Name string `json:"name,omitempty"`
|
||||
|
||||
// If the action is disabled.
|
||||
Disabled bool `json:"disabled,omitempty"`
|
||||
|
||||
// Style defines a text and border style.
|
||||
// Supported values are "default", "primary", "success", "good", "warning", "danger"
|
||||
// and any hex color.
|
||||
Style string `json:"style,omitempty"`
|
||||
|
||||
// DataSource indicates the data source for the select action. If left
|
||||
// empty, the select is populated from Options. Other supported values
|
||||
// are "users" and "channels".
|
||||
DataSource string `json:"data_source,omitempty"`
|
||||
|
||||
// Options contains the values listed in a select dropdown on the post.
|
||||
Options []*PostActionOptions `json:"options,omitempty"`
|
||||
|
||||
// DefaultOption contains the option, if any, that will appear as the
|
||||
// default selection in a select box. It has no effect when used with
|
||||
// other types of actions.
|
||||
DefaultOption string `json:"default_option,omitempty"`
|
||||
|
||||
// Defines the interaction with the backend upon a user action.
|
||||
// Integration contains Context, which is private plugin data;
|
||||
// Integrations are stripped from Posts when they are sent to the
|
||||
// client, or are encrypted in a Cookie.
|
||||
Integration *PostActionIntegration `json:"integration,omitempty"`
|
||||
Cookie string `json:"cookie,omitempty" db:"-"`
|
||||
}
|
||||
|
||||
func (p *PostAction) Equals(input *PostAction) bool {
|
||||
if p.Id != input.Id {
|
||||
return false
|
||||
}
|
||||
|
||||
if p.Type != input.Type {
|
||||
return false
|
||||
}
|
||||
|
||||
if p.Name != input.Name {
|
||||
return false
|
||||
}
|
||||
|
||||
if p.DataSource != input.DataSource {
|
||||
return false
|
||||
}
|
||||
|
||||
if p.DefaultOption != input.DefaultOption {
|
||||
return false
|
||||
}
|
||||
|
||||
if p.Cookie != input.Cookie {
|
||||
return false
|
||||
}
|
||||
|
||||
// Compare PostActionOptions
|
||||
if len(p.Options) != len(input.Options) {
|
||||
return false
|
||||
}
|
||||
|
||||
for k := range p.Options {
|
||||
if p.Options[k].Text != input.Options[k].Text {
|
||||
return false
|
||||
}
|
||||
|
||||
if p.Options[k].Value != input.Options[k].Value {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// Compare PostActionIntegration
|
||||
if p.Integration.URL != input.Integration.URL {
|
||||
return false
|
||||
}
|
||||
|
||||
if len(p.Integration.Context) != len(input.Integration.Context) {
|
||||
return false
|
||||
}
|
||||
|
||||
for key, value := range p.Integration.Context {
|
||||
inputValue, ok := input.Integration.Context[key]
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
switch inputValue.(type) {
|
||||
case string, bool, int, float64:
|
||||
if value != inputValue {
|
||||
return false
|
||||
}
|
||||
default:
|
||||
if !reflect.DeepEqual(value, inputValue) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// PostActionCookie is set by the server, serialized and encrypted into
|
||||
// PostAction.Cookie. The clients should hold on to it, and include it with
|
||||
// subsequent DoPostAction requests. This allows the server to access the
|
||||
// action metadata even when it's not available in the database, for ephemeral
|
||||
// posts.
|
||||
type PostActionCookie struct {
|
||||
Type string `json:"type,omitempty"`
|
||||
PostId string `json:"post_id,omitempty"`
|
||||
RootPostId string `json:"root_post_id,omitempty"`
|
||||
ChannelId string `json:"channel_id,omitempty"`
|
||||
DataSource string `json:"data_source,omitempty"`
|
||||
Integration *PostActionIntegration `json:"integration,omitempty"`
|
||||
RetainProps map[string]interface{} `json:"retain_props,omitempty"`
|
||||
RemoveProps []string `json:"remove_props,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"`
|
||||
UserName string `json:"user_name"`
|
||||
ChannelId string `json:"channel_id"`
|
||||
ChannelName string `json:"channel_name"`
|
||||
TeamId string `json:"team_id"`
|
||||
TeamName string `json:"team_domain"`
|
||||
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"`
|
||||
SkipSlackParsing bool `json:"skip_slack_parsing"` // Set to `true` to skip the Slack-compatibility handling of 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"`
|
||||
IntroductionText string `json:"introduction_text"`
|
||||
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 {
|
||||
Error string `json:"error,omitempty"`
|
||||
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(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.GetProp("attachments") != nil {
|
||||
o.AddProp("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 != nil && action.Id == id {
|
||||
return action
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *Post) GenerateActionIds() {
|
||||
if o.GetProp("attachments") != nil {
|
||||
o.AddProp("attachments", o.Attachments())
|
||||
}
|
||||
if attachments, ok := o.GetProp("attachments").([]*SlackAttachment); ok {
|
||||
for _, attachment := range attachments {
|
||||
for _, action := range attachment.Actions {
|
||||
if action != nil && action.Id == "" {
|
||||
action.Id = NewId()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func AddPostActionCookies(o *Post, secret []byte) *Post {
|
||||
p := o.Clone()
|
||||
|
||||
// retainedProps carry over their value from the old post, including no value
|
||||
retainProps := map[string]interface{}{}
|
||||
removeProps := []string{}
|
||||
for _, key := range PostActionRetainPropKeys {
|
||||
value, ok := p.GetProps()[key]
|
||||
if ok {
|
||||
retainProps[key] = value
|
||||
} else {
|
||||
removeProps = append(removeProps, key)
|
||||
}
|
||||
}
|
||||
|
||||
attachments := p.Attachments()
|
||||
for _, attachment := range attachments {
|
||||
for _, action := range attachment.Actions {
|
||||
c := &PostActionCookie{
|
||||
Type: action.Type,
|
||||
ChannelId: p.ChannelId,
|
||||
DataSource: action.DataSource,
|
||||
Integration: action.Integration,
|
||||
RetainProps: retainProps,
|
||||
RemoveProps: removeProps,
|
||||
}
|
||||
|
||||
c.PostId = p.Id
|
||||
if p.RootId == "" {
|
||||
c.RootPostId = p.Id
|
||||
} else {
|
||||
c.RootPostId = p.RootId
|
||||
}
|
||||
|
||||
b, _ := json.Marshal(c)
|
||||
action.Cookie, _ = encryptPostActionCookie(string(b), secret)
|
||||
}
|
||||
}
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
func encryptPostActionCookie(plain string, secret []byte) (string, error) {
|
||||
if len(secret) == 0 {
|
||||
return plain, nil
|
||||
}
|
||||
|
||||
block, err := aes.NewCipher(secret)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
aesgcm, err := cipher.NewGCM(block)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
nonce := make([]byte, aesgcm.NonceSize())
|
||||
_, err = io.ReadFull(rand.Reader, nonce)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
sealed := aesgcm.Seal(nil, nonce, []byte(plain), nil)
|
||||
|
||||
combined := append(nonce, sealed...)
|
||||
encoded := make([]byte, base64.StdEncoding.EncodedLen(len(combined)))
|
||||
base64.StdEncoding.Encode(encoded, combined)
|
||||
|
||||
return string(encoded), nil
|
||||
}
|
||||
|
||||
func DecryptPostActionCookie(encoded string, secret []byte) (string, error) {
|
||||
if len(secret) == 0 {
|
||||
return encoded, nil
|
||||
}
|
||||
|
||||
block, err := aes.NewCipher(secret)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
aesgcm, err := cipher.NewGCM(block)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
decoded := make([]byte, base64.StdEncoding.DecodedLen(len(encoded)))
|
||||
n, err := base64.StdEncoding.Decode(decoded, []byte(encoded))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
decoded = decoded[:n]
|
||||
|
||||
nonceSize := aesgcm.NonceSize()
|
||||
if len(decoded) < nonceSize {
|
||||
return "", fmt.Errorf("cookie too short")
|
||||
}
|
||||
|
||||
nonce, decoded := decoded[:nonceSize], decoded[nonceSize:]
|
||||
plain, err := aesgcm.Open(nil, nonce, decoded, nil)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return string(plain), nil
|
||||
}
|
||||
|
||||
func DoPostActionRequestFromJson(data io.Reader) *DoPostActionRequest {
|
||||
var o *DoPostActionRequest
|
||||
json.NewDecoder(data).Decode(&o)
|
||||
return o
|
||||
}
|
58
vendor/github.com/mattermost/mattermost-server/v5/model/integrity.go
generated
vendored
58
vendor/github.com/mattermost/mattermost-server/v5/model/integrity.go
generated
vendored
@ -1,58 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
)
|
||||
|
||||
type OrphanedRecord struct {
|
||||
ParentId *string `json:"parent_id"`
|
||||
ChildId *string `json:"child_id"`
|
||||
}
|
||||
|
||||
type RelationalIntegrityCheckData struct {
|
||||
ParentName string `json:"parent_name"`
|
||||
ChildName string `json:"child_name"`
|
||||
ParentIdAttr string `json:"parent_id_attr"`
|
||||
ChildIdAttr string `json:"child_id_attr"`
|
||||
Records []OrphanedRecord `json:"records"`
|
||||
}
|
||||
|
||||
type IntegrityCheckResult struct {
|
||||
Data interface{} `json:"data"`
|
||||
Err error `json:"err"`
|
||||
}
|
||||
|
||||
func (r *IntegrityCheckResult) UnmarshalJSON(b []byte) error {
|
||||
var data map[string]interface{}
|
||||
if err := json.Unmarshal(b, &data); err != nil {
|
||||
return err
|
||||
}
|
||||
if d, ok := data["data"]; ok && d != nil {
|
||||
var rdata RelationalIntegrityCheckData
|
||||
m := d.(map[string]interface{})
|
||||
rdata.ParentName = m["parent_name"].(string)
|
||||
rdata.ChildName = m["child_name"].(string)
|
||||
rdata.ParentIdAttr = m["parent_id_attr"].(string)
|
||||
rdata.ChildIdAttr = m["child_id_attr"].(string)
|
||||
for _, recData := range m["records"].([]interface{}) {
|
||||
var record OrphanedRecord
|
||||
m := recData.(map[string]interface{})
|
||||
if val := m["parent_id"]; val != nil {
|
||||
record.ParentId = NewString(val.(string))
|
||||
}
|
||||
if val := m["child_id"]; val != nil {
|
||||
record.ChildId = NewString(val.(string))
|
||||
}
|
||||
rdata.Records = append(rdata.Records, record)
|
||||
}
|
||||
r.Data = rdata
|
||||
}
|
||||
if err, ok := data["err"]; ok && err != nil {
|
||||
r.Err = errors.New(data["err"].(string))
|
||||
}
|
||||
return nil
|
||||
}
|
160
vendor/github.com/mattermost/mattermost-server/v5/model/job.go
generated
vendored
160
vendor/github.com/mattermost/mattermost-server/v5/model/job.go
generated
vendored
@ -1,160 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
JOB_TYPE_DATA_RETENTION = "data_retention"
|
||||
JOB_TYPE_MESSAGE_EXPORT = "message_export"
|
||||
JOB_TYPE_ELASTICSEARCH_POST_INDEXING = "elasticsearch_post_indexing"
|
||||
JOB_TYPE_ELASTICSEARCH_POST_AGGREGATION = "elasticsearch_post_aggregation"
|
||||
JOB_TYPE_BLEVE_POST_INDEXING = "bleve_post_indexing"
|
||||
JOB_TYPE_LDAP_SYNC = "ldap_sync"
|
||||
JOB_TYPE_MIGRATIONS = "migrations"
|
||||
JOB_TYPE_PLUGINS = "plugins"
|
||||
JOB_TYPE_EXPIRY_NOTIFY = "expiry_notify"
|
||||
JOB_TYPE_PRODUCT_NOTICES = "product_notices"
|
||||
JOB_TYPE_ACTIVE_USERS = "active_users"
|
||||
JOB_TYPE_IMPORT_PROCESS = "import_process"
|
||||
JOB_TYPE_IMPORT_DELETE = "import_delete"
|
||||
JOB_TYPE_EXPORT_PROCESS = "export_process"
|
||||
JOB_TYPE_EXPORT_DELETE = "export_delete"
|
||||
JOB_TYPE_CLOUD = "cloud"
|
||||
JOB_TYPE_RESEND_INVITATION_EMAIL = "resend_invitation_email"
|
||||
|
||||
JOB_STATUS_PENDING = "pending"
|
||||
JOB_STATUS_IN_PROGRESS = "in_progress"
|
||||
JOB_STATUS_SUCCESS = "success"
|
||||
JOB_STATUS_ERROR = "error"
|
||||
JOB_STATUS_CANCEL_REQUESTED = "cancel_requested"
|
||||
JOB_STATUS_CANCELED = "canceled"
|
||||
JOB_STATUS_WARNING = "warning"
|
||||
)
|
||||
|
||||
var ALL_JOB_TYPES = [...]string{
|
||||
JOB_TYPE_DATA_RETENTION,
|
||||
JOB_TYPE_MESSAGE_EXPORT,
|
||||
JOB_TYPE_ELASTICSEARCH_POST_INDEXING,
|
||||
JOB_TYPE_ELASTICSEARCH_POST_AGGREGATION,
|
||||
JOB_TYPE_BLEVE_POST_INDEXING,
|
||||
JOB_TYPE_LDAP_SYNC,
|
||||
JOB_TYPE_MIGRATIONS,
|
||||
JOB_TYPE_PLUGINS,
|
||||
JOB_TYPE_EXPIRY_NOTIFY,
|
||||
JOB_TYPE_PRODUCT_NOTICES,
|
||||
JOB_TYPE_ACTIVE_USERS,
|
||||
JOB_TYPE_IMPORT_PROCESS,
|
||||
JOB_TYPE_IMPORT_DELETE,
|
||||
JOB_TYPE_EXPORT_PROCESS,
|
||||
JOB_TYPE_EXPORT_DELETE,
|
||||
JOB_TYPE_CLOUD,
|
||||
}
|
||||
|
||||
type Job struct {
|
||||
Id string `json:"id"`
|
||||
Type string `json:"type"`
|
||||
Priority int64 `json:"priority"`
|
||||
CreateAt int64 `json:"create_at"`
|
||||
StartAt int64 `json:"start_at"`
|
||||
LastActivityAt int64 `json:"last_activity_at"`
|
||||
Status string `json:"status"`
|
||||
Progress int64 `json:"progress"`
|
||||
Data map[string]string `json:"data"`
|
||||
}
|
||||
|
||||
func (j *Job) IsValid() *AppError {
|
||||
if !IsValidId(j.Id) {
|
||||
return NewAppError("Job.IsValid", "model.job.is_valid.id.app_error", nil, "id="+j.Id, http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if j.CreateAt == 0 {
|
||||
return NewAppError("Job.IsValid", "model.job.is_valid.create_at.app_error", nil, "id="+j.Id, http.StatusBadRequest)
|
||||
}
|
||||
|
||||
switch j.Type {
|
||||
case JOB_TYPE_DATA_RETENTION:
|
||||
case JOB_TYPE_ELASTICSEARCH_POST_INDEXING:
|
||||
case JOB_TYPE_ELASTICSEARCH_POST_AGGREGATION:
|
||||
case JOB_TYPE_BLEVE_POST_INDEXING:
|
||||
case JOB_TYPE_LDAP_SYNC:
|
||||
case JOB_TYPE_MESSAGE_EXPORT:
|
||||
case JOB_TYPE_MIGRATIONS:
|
||||
case JOB_TYPE_PLUGINS:
|
||||
case JOB_TYPE_PRODUCT_NOTICES:
|
||||
case JOB_TYPE_EXPIRY_NOTIFY:
|
||||
case JOB_TYPE_ACTIVE_USERS:
|
||||
case JOB_TYPE_IMPORT_PROCESS:
|
||||
case JOB_TYPE_IMPORT_DELETE:
|
||||
case JOB_TYPE_EXPORT_PROCESS:
|
||||
case JOB_TYPE_EXPORT_DELETE:
|
||||
case JOB_TYPE_CLOUD:
|
||||
case JOB_TYPE_RESEND_INVITATION_EMAIL:
|
||||
default:
|
||||
return NewAppError("Job.IsValid", "model.job.is_valid.type.app_error", nil, "id="+j.Id, http.StatusBadRequest)
|
||||
}
|
||||
|
||||
switch j.Status {
|
||||
case JOB_STATUS_PENDING:
|
||||
case JOB_STATUS_IN_PROGRESS:
|
||||
case JOB_STATUS_SUCCESS:
|
||||
case JOB_STATUS_ERROR:
|
||||
case JOB_STATUS_CANCEL_REQUESTED:
|
||||
case JOB_STATUS_CANCELED:
|
||||
default:
|
||||
return NewAppError("Job.IsValid", "model.job.is_valid.status.app_error", nil, "id="+j.Id, http.StatusBadRequest)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (j *Job) ToJson() string {
|
||||
b, _ := json.Marshal(j)
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func JobFromJson(data io.Reader) *Job {
|
||||
var job Job
|
||||
if err := json.NewDecoder(data).Decode(&job); err == nil {
|
||||
return &job
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func JobsToJson(jobs []*Job) string {
|
||||
b, _ := json.Marshal(jobs)
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func JobsFromJson(data io.Reader) []*Job {
|
||||
var jobs []*Job
|
||||
if err := json.NewDecoder(data).Decode(&jobs); err == nil {
|
||||
return jobs
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (j *Job) DataToJson() string {
|
||||
b, _ := json.Marshal(j.Data)
|
||||
return string(b)
|
||||
}
|
||||
|
||||
type Worker interface {
|
||||
Run()
|
||||
Stop()
|
||||
JobChannel() chan<- Job
|
||||
}
|
||||
|
||||
type Scheduler interface {
|
||||
Name() string
|
||||
JobType() string
|
||||
Enabled(cfg *Config) bool
|
||||
NextScheduleTime(cfg *Config, now time.Time, pendingJobs bool, lastSuccessfulJob *Job) *time.Time
|
||||
ScheduleJob(cfg *Config, pendingJobs bool, lastSuccessfulJob *Job) (*Job, *AppError)
|
||||
}
|
10
vendor/github.com/mattermost/mattermost-server/v5/model/ldap.go
generated
vendored
10
vendor/github.com/mattermost/mattermost-server/v5/model/ldap.go
generated
vendored
@ -1,10 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
const (
|
||||
USER_AUTH_SERVICE_LDAP = "ldap"
|
||||
LDAP_PUBLIC_CERTIFICATE_NAME = "ldap-public.crt"
|
||||
LDAP_PRIVATE_KEY_NAME = "ldap-private.key"
|
||||
)
|
350
vendor/github.com/mattermost/mattermost-server/v5/model/license.go
generated
vendored
350
vendor/github.com/mattermost/mattermost-server/v5/model/license.go
generated
vendored
@ -1,350 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
EXPIRED_LICENSE_ERROR = "api.license.add_license.expired.app_error"
|
||||
INVALID_LICENSE_ERROR = "api.license.add_license.invalid.app_error"
|
||||
LICENSE_GRACE_PERIOD = 1000 * 60 * 60 * 24 * 10 //10 days
|
||||
LICENSE_RENEWAL_LINK = "https://mattermost.com/renew/"
|
||||
)
|
||||
|
||||
const (
|
||||
SIXTY_DAYS = 60
|
||||
FIFTY_EIGHT = 58
|
||||
LICENSE_UP_FOR_RENEWAL_EMAIL_SENT = "LicenseUpForRenewalEmailSent"
|
||||
)
|
||||
|
||||
var (
|
||||
trialDuration = 30*(time.Hour*24) + (time.Hour * 8) // 720 hours (30 days) + 8 hours is trial license duration
|
||||
adminTrialDuration = 30*(time.Hour*24) + (time.Hour * 23) + (time.Minute * 59) + (time.Second * 59) // 720 hours (30 days) + 23 hours, 59 mins and 59 seconds
|
||||
|
||||
// a sanctioned trial's duration is either more than the upper bound,
|
||||
// or less than the lower bound
|
||||
sanctionedTrialDurationLowerBound = 31*(time.Hour*24) + (time.Hour * 23) + (time.Minute * 59) + (time.Second * 59) // 744 hours (31 days) + 23 hours, 59 mins and 59 seconds
|
||||
sanctionedTrialDurationUpperBound = 29*(time.Hour*24) + (time.Hour * 23) + (time.Minute * 59) + (time.Second * 59) // 696 hours (29 days) + 23 hours, 59 mins and 59 seconds
|
||||
)
|
||||
|
||||
type LicenseRecord struct {
|
||||
Id string `json:"id"`
|
||||
CreateAt int64 `json:"create_at"`
|
||||
Bytes string `json:"-"`
|
||||
}
|
||||
|
||||
type License struct {
|
||||
Id string `json:"id"`
|
||||
IssuedAt int64 `json:"issued_at"`
|
||||
StartsAt int64 `json:"starts_at"`
|
||||
ExpiresAt int64 `json:"expires_at"`
|
||||
Customer *Customer `json:"customer"`
|
||||
Features *Features `json:"features"`
|
||||
SkuName string `json:"sku_name"`
|
||||
SkuShortName string `json:"sku_short_name"`
|
||||
IsTrial bool `json:"is_trial"`
|
||||
}
|
||||
|
||||
type Customer struct {
|
||||
Id string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Email string `json:"email"`
|
||||
Company string `json:"company"`
|
||||
}
|
||||
|
||||
type TrialLicenseRequest struct {
|
||||
ServerID string `json:"server_id"`
|
||||
Email string `json:"email"`
|
||||
Name string `json:"name"`
|
||||
SiteURL string `json:"site_url"`
|
||||
SiteName string `json:"site_name"`
|
||||
Users int `json:"users"`
|
||||
TermsAccepted bool `json:"terms_accepted"`
|
||||
ReceiveEmailsAccepted bool `json:"receive_emails_accepted"`
|
||||
}
|
||||
|
||||
func (tlr *TrialLicenseRequest) ToJson() string {
|
||||
b, _ := json.Marshal(tlr)
|
||||
return string(b)
|
||||
}
|
||||
|
||||
type Features struct {
|
||||
Users *int `json:"users"`
|
||||
LDAP *bool `json:"ldap"`
|
||||
LDAPGroups *bool `json:"ldap_groups"`
|
||||
MFA *bool `json:"mfa"`
|
||||
GoogleOAuth *bool `json:"google_oauth"`
|
||||
Office365OAuth *bool `json:"office365_oauth"`
|
||||
OpenId *bool `json:"openid"`
|
||||
Compliance *bool `json:"compliance"`
|
||||
Cluster *bool `json:"cluster"`
|
||||
Metrics *bool `json:"metrics"`
|
||||
MHPNS *bool `json:"mhpns"`
|
||||
SAML *bool `json:"saml"`
|
||||
Elasticsearch *bool `json:"elastic_search"`
|
||||
Announcement *bool `json:"announcement"`
|
||||
ThemeManagement *bool `json:"theme_management"`
|
||||
EmailNotificationContents *bool `json:"email_notification_contents"`
|
||||
DataRetention *bool `json:"data_retention"`
|
||||
MessageExport *bool `json:"message_export"`
|
||||
CustomPermissionsSchemes *bool `json:"custom_permissions_schemes"`
|
||||
CustomTermsOfService *bool `json:"custom_terms_of_service"`
|
||||
GuestAccounts *bool `json:"guest_accounts"`
|
||||
GuestAccountsPermissions *bool `json:"guest_accounts_permissions"`
|
||||
IDLoadedPushNotifications *bool `json:"id_loaded"`
|
||||
LockTeammateNameDisplay *bool `json:"lock_teammate_name_display"`
|
||||
EnterprisePlugins *bool `json:"enterprise_plugins"`
|
||||
AdvancedLogging *bool `json:"advanced_logging"`
|
||||
Cloud *bool `json:"cloud"`
|
||||
SharedChannels *bool `json:"shared_channels"`
|
||||
RemoteClusterService *bool `json:"remote_cluster_service"`
|
||||
|
||||
// after we enabled more features we'll need to control them with this
|
||||
FutureFeatures *bool `json:"future_features"`
|
||||
}
|
||||
|
||||
func (f *Features) ToMap() map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
"ldap": *f.LDAP,
|
||||
"ldap_groups": *f.LDAPGroups,
|
||||
"mfa": *f.MFA,
|
||||
"google": *f.GoogleOAuth,
|
||||
"office365": *f.Office365OAuth,
|
||||
"openid": *f.OpenId,
|
||||
"compliance": *f.Compliance,
|
||||
"cluster": *f.Cluster,
|
||||
"metrics": *f.Metrics,
|
||||
"mhpns": *f.MHPNS,
|
||||
"saml": *f.SAML,
|
||||
"elastic_search": *f.Elasticsearch,
|
||||
"email_notification_contents": *f.EmailNotificationContents,
|
||||
"data_retention": *f.DataRetention,
|
||||
"message_export": *f.MessageExport,
|
||||
"custom_permissions_schemes": *f.CustomPermissionsSchemes,
|
||||
"guest_accounts": *f.GuestAccounts,
|
||||
"guest_accounts_permissions": *f.GuestAccountsPermissions,
|
||||
"id_loaded": *f.IDLoadedPushNotifications,
|
||||
"lock_teammate_name_display": *f.LockTeammateNameDisplay,
|
||||
"enterprise_plugins": *f.EnterprisePlugins,
|
||||
"advanced_logging": *f.AdvancedLogging,
|
||||
"cloud": *f.Cloud,
|
||||
"shared_channels": *f.SharedChannels,
|
||||
"remote_cluster_service": *f.RemoteClusterService,
|
||||
"future": *f.FutureFeatures,
|
||||
}
|
||||
}
|
||||
|
||||
func (f *Features) SetDefaults() {
|
||||
if f.FutureFeatures == nil {
|
||||
f.FutureFeatures = NewBool(true)
|
||||
}
|
||||
|
||||
if f.Users == nil {
|
||||
f.Users = NewInt(0)
|
||||
}
|
||||
|
||||
if f.LDAP == nil {
|
||||
f.LDAP = NewBool(*f.FutureFeatures)
|
||||
}
|
||||
|
||||
if f.LDAPGroups == nil {
|
||||
f.LDAPGroups = NewBool(*f.FutureFeatures)
|
||||
}
|
||||
|
||||
if f.MFA == nil {
|
||||
f.MFA = NewBool(*f.FutureFeatures)
|
||||
}
|
||||
|
||||
if f.GoogleOAuth == nil {
|
||||
f.GoogleOAuth = NewBool(*f.FutureFeatures)
|
||||
}
|
||||
|
||||
if f.Office365OAuth == nil {
|
||||
f.Office365OAuth = NewBool(*f.FutureFeatures)
|
||||
}
|
||||
|
||||
if f.OpenId == nil {
|
||||
f.OpenId = NewBool(*f.FutureFeatures)
|
||||
}
|
||||
|
||||
if f.Compliance == nil {
|
||||
f.Compliance = NewBool(*f.FutureFeatures)
|
||||
}
|
||||
|
||||
if f.Cluster == nil {
|
||||
f.Cluster = NewBool(*f.FutureFeatures)
|
||||
}
|
||||
|
||||
if f.Metrics == nil {
|
||||
f.Metrics = NewBool(*f.FutureFeatures)
|
||||
}
|
||||
|
||||
if f.MHPNS == nil {
|
||||
f.MHPNS = NewBool(*f.FutureFeatures)
|
||||
}
|
||||
|
||||
if f.SAML == nil {
|
||||
f.SAML = NewBool(*f.FutureFeatures)
|
||||
}
|
||||
|
||||
if f.Elasticsearch == nil {
|
||||
f.Elasticsearch = NewBool(*f.FutureFeatures)
|
||||
}
|
||||
|
||||
if f.Announcement == nil {
|
||||
f.Announcement = NewBool(true)
|
||||
}
|
||||
|
||||
if f.ThemeManagement == nil {
|
||||
f.ThemeManagement = NewBool(true)
|
||||
}
|
||||
|
||||
if f.EmailNotificationContents == nil {
|
||||
f.EmailNotificationContents = NewBool(*f.FutureFeatures)
|
||||
}
|
||||
|
||||
if f.DataRetention == nil {
|
||||
f.DataRetention = NewBool(*f.FutureFeatures)
|
||||
}
|
||||
|
||||
if f.MessageExport == nil {
|
||||
f.MessageExport = NewBool(*f.FutureFeatures)
|
||||
}
|
||||
|
||||
if f.CustomPermissionsSchemes == nil {
|
||||
f.CustomPermissionsSchemes = NewBool(*f.FutureFeatures)
|
||||
}
|
||||
|
||||
if f.GuestAccounts == nil {
|
||||
f.GuestAccounts = NewBool(*f.FutureFeatures)
|
||||
}
|
||||
|
||||
if f.GuestAccountsPermissions == nil {
|
||||
f.GuestAccountsPermissions = NewBool(*f.FutureFeatures)
|
||||
}
|
||||
|
||||
if f.CustomTermsOfService == nil {
|
||||
f.CustomTermsOfService = NewBool(*f.FutureFeatures)
|
||||
}
|
||||
|
||||
if f.IDLoadedPushNotifications == nil {
|
||||
f.IDLoadedPushNotifications = NewBool(*f.FutureFeatures)
|
||||
}
|
||||
|
||||
if f.LockTeammateNameDisplay == nil {
|
||||
f.LockTeammateNameDisplay = NewBool(*f.FutureFeatures)
|
||||
}
|
||||
|
||||
if f.EnterprisePlugins == nil {
|
||||
f.EnterprisePlugins = NewBool(*f.FutureFeatures)
|
||||
}
|
||||
|
||||
if f.AdvancedLogging == nil {
|
||||
f.AdvancedLogging = NewBool(*f.FutureFeatures)
|
||||
}
|
||||
|
||||
if f.Cloud == nil {
|
||||
f.Cloud = NewBool(false)
|
||||
}
|
||||
|
||||
if f.SharedChannels == nil {
|
||||
f.SharedChannels = NewBool(*f.FutureFeatures)
|
||||
}
|
||||
|
||||
if f.RemoteClusterService == nil {
|
||||
f.RemoteClusterService = NewBool(*f.FutureFeatures)
|
||||
}
|
||||
}
|
||||
|
||||
func (l *License) IsExpired() bool {
|
||||
return l.ExpiresAt < GetMillis()
|
||||
}
|
||||
|
||||
func (l *License) IsPastGracePeriod() bool {
|
||||
timeDiff := GetMillis() - l.ExpiresAt
|
||||
return timeDiff > LICENSE_GRACE_PERIOD
|
||||
}
|
||||
|
||||
func (l *License) IsWithinExpirationPeriod() bool {
|
||||
days := l.DaysToExpiration()
|
||||
return days <= SIXTY_DAYS && days >= FIFTY_EIGHT
|
||||
}
|
||||
|
||||
func (l *License) DaysToExpiration() int {
|
||||
dif := l.ExpiresAt - GetMillis()
|
||||
d, _ := time.ParseDuration(fmt.Sprint(dif) + "ms")
|
||||
days := d.Hours() / 24
|
||||
return int(days)
|
||||
}
|
||||
|
||||
func (l *License) IsStarted() bool {
|
||||
return l.StartsAt < GetMillis()
|
||||
}
|
||||
|
||||
func (l *License) ToJson() string {
|
||||
b, _ := json.Marshal(l)
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func (l *License) IsTrialLicense() bool {
|
||||
return l.IsTrial || (l.ExpiresAt-l.StartsAt) == trialDuration.Milliseconds() || (l.ExpiresAt-l.StartsAt) == adminTrialDuration.Milliseconds()
|
||||
}
|
||||
|
||||
func (l *License) IsSanctionedTrial() bool {
|
||||
duration := l.ExpiresAt - l.StartsAt
|
||||
|
||||
return l.IsTrialLicense() &&
|
||||
(duration >= sanctionedTrialDurationLowerBound.Milliseconds() || duration <= sanctionedTrialDurationUpperBound.Milliseconds())
|
||||
}
|
||||
|
||||
// NewTestLicense returns a license that expires in the future and has the given features.
|
||||
func NewTestLicense(features ...string) *License {
|
||||
ret := &License{
|
||||
ExpiresAt: GetMillis() + 90*24*60*60*1000,
|
||||
Customer: &Customer{},
|
||||
Features: &Features{},
|
||||
}
|
||||
ret.Features.SetDefaults()
|
||||
|
||||
featureMap := map[string]bool{}
|
||||
for _, feature := range features {
|
||||
featureMap[feature] = true
|
||||
}
|
||||
featureJson, _ := json.Marshal(featureMap)
|
||||
json.Unmarshal(featureJson, &ret.Features)
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func LicenseFromJson(data io.Reader) *License {
|
||||
var o *License
|
||||
json.NewDecoder(data).Decode(&o)
|
||||
return o
|
||||
}
|
||||
|
||||
func (lr *LicenseRecord) IsValid() *AppError {
|
||||
if !IsValidId(lr.Id) {
|
||||
return NewAppError("LicenseRecord.IsValid", "model.license_record.is_valid.id.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if lr.CreateAt == 0 {
|
||||
return NewAppError("LicenseRecord.IsValid", "model.license_record.is_valid.create_at.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if lr.Bytes == "" || len(lr.Bytes) > 10000 {
|
||||
return NewAppError("LicenseRecord.IsValid", "model.license_record.is_valid.create_at.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (lr *LicenseRecord) PreSave() {
|
||||
lr.CreateAt = GetMillis()
|
||||
}
|
193
vendor/github.com/mattermost/mattermost-server/v5/model/link_metadata.go
generated
vendored
193
vendor/github.com/mattermost/mattermost-server/v5/model/link_metadata.go
generated
vendored
@ -1,193 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"hash/fnv"
|
||||
"net/http"
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/dyatlov/go-opengraph/opengraph"
|
||||
)
|
||||
|
||||
const (
|
||||
LINK_METADATA_TYPE_IMAGE LinkMetadataType = "image"
|
||||
LINK_METADATA_TYPE_NONE LinkMetadataType = "none"
|
||||
LINK_METADATA_TYPE_OPENGRAPH LinkMetadataType = "opengraph"
|
||||
MAX_IMAGES int = 5
|
||||
)
|
||||
|
||||
type LinkMetadataType string
|
||||
|
||||
// LinkMetadata stores arbitrary data about a link posted in a message. This includes dimensions of linked images
|
||||
// and OpenGraph metadata.
|
||||
type LinkMetadata struct {
|
||||
// Hash is a value computed from the URL and Timestamp for use as a primary key in the database.
|
||||
Hash int64
|
||||
|
||||
URL string
|
||||
Timestamp int64
|
||||
Type LinkMetadataType
|
||||
|
||||
// Data is the actual metadata for the link. It should contain data of one of the following types:
|
||||
// - *model.PostImage if the linked content is an image
|
||||
// - *opengraph.OpenGraph if the linked content is an HTML document
|
||||
// - nil if the linked content has no metadata
|
||||
Data interface{}
|
||||
}
|
||||
|
||||
// truncateText ensure string is 300 chars, truncate and add ellipsis
|
||||
// if it was bigger.
|
||||
func truncateText(original string) string {
|
||||
if utf8.RuneCountInString(original) > 300 {
|
||||
return fmt.Sprintf("%.300s[...]", original)
|
||||
}
|
||||
return original
|
||||
}
|
||||
|
||||
func firstNImages(images []*opengraph.Image, maxImages int) []*opengraph.Image {
|
||||
if maxImages < 0 { // dont break stuff, if it's weird, go for sane defaults
|
||||
maxImages = MAX_IMAGES
|
||||
}
|
||||
numImages := len(images)
|
||||
if numImages > maxImages {
|
||||
return images[0:maxImages]
|
||||
}
|
||||
return images
|
||||
}
|
||||
|
||||
// TruncateOpenGraph ensure OpenGraph metadata doesn't grow too big by
|
||||
// shortening strings, trimming fields and reducing the number of
|
||||
// images.
|
||||
func TruncateOpenGraph(ogdata *opengraph.OpenGraph) *opengraph.OpenGraph {
|
||||
if ogdata != nil {
|
||||
empty := &opengraph.OpenGraph{}
|
||||
ogdata.Title = truncateText(ogdata.Title)
|
||||
ogdata.Description = truncateText(ogdata.Description)
|
||||
ogdata.SiteName = truncateText(ogdata.SiteName)
|
||||
ogdata.Article = empty.Article
|
||||
ogdata.Book = empty.Book
|
||||
ogdata.Profile = empty.Profile
|
||||
ogdata.Determiner = empty.Determiner
|
||||
ogdata.Locale = empty.Locale
|
||||
ogdata.LocalesAlternate = empty.LocalesAlternate
|
||||
ogdata.Images = firstNImages(ogdata.Images, MAX_IMAGES)
|
||||
ogdata.Audios = empty.Audios
|
||||
ogdata.Videos = empty.Videos
|
||||
}
|
||||
return ogdata
|
||||
}
|
||||
|
||||
func (o *LinkMetadata) PreSave() {
|
||||
o.Hash = GenerateLinkMetadataHash(o.URL, o.Timestamp)
|
||||
}
|
||||
|
||||
func (o *LinkMetadata) IsValid() *AppError {
|
||||
if o.URL == "" {
|
||||
return NewAppError("LinkMetadata.IsValid", "model.link_metadata.is_valid.url.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if o.Timestamp == 0 || !isRoundedToNearestHour(o.Timestamp) {
|
||||
return NewAppError("LinkMetadata.IsValid", "model.link_metadata.is_valid.timestamp.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
switch o.Type {
|
||||
case LINK_METADATA_TYPE_IMAGE:
|
||||
if o.Data == nil {
|
||||
return NewAppError("LinkMetadata.IsValid", "model.link_metadata.is_valid.data.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if _, ok := o.Data.(*PostImage); !ok {
|
||||
return NewAppError("LinkMetadata.IsValid", "model.link_metadata.is_valid.data_type.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
case LINK_METADATA_TYPE_NONE:
|
||||
if o.Data != nil {
|
||||
return NewAppError("LinkMetadata.IsValid", "model.link_metadata.is_valid.data_type.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
case LINK_METADATA_TYPE_OPENGRAPH:
|
||||
if o.Data == nil {
|
||||
return NewAppError("LinkMetadata.IsValid", "model.link_metadata.is_valid.data.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if _, ok := o.Data.(*opengraph.OpenGraph); !ok {
|
||||
return NewAppError("LinkMetadata.IsValid", "model.link_metadata.is_valid.data_type.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
default:
|
||||
return NewAppError("LinkMetadata.IsValid", "model.link_metadata.is_valid.type.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeserializeDataToConcreteType converts o.Data from JSON into properly structured data. This is intended to be used
|
||||
// after getting a LinkMetadata object that has been stored in the database.
|
||||
func (o *LinkMetadata) DeserializeDataToConcreteType() error {
|
||||
var b []byte
|
||||
switch t := o.Data.(type) {
|
||||
case []byte:
|
||||
// MySQL uses a byte slice for JSON
|
||||
b = t
|
||||
case string:
|
||||
// Postgres uses a string for JSON
|
||||
b = []byte(t)
|
||||
}
|
||||
|
||||
if b == nil {
|
||||
// Data doesn't need to be fixed
|
||||
return nil
|
||||
}
|
||||
|
||||
var data interface{}
|
||||
var err error
|
||||
|
||||
switch o.Type {
|
||||
case LINK_METADATA_TYPE_IMAGE:
|
||||
image := &PostImage{}
|
||||
|
||||
err = json.Unmarshal(b, &image)
|
||||
|
||||
data = image
|
||||
case LINK_METADATA_TYPE_OPENGRAPH:
|
||||
og := &opengraph.OpenGraph{}
|
||||
|
||||
json.Unmarshal(b, &og)
|
||||
|
||||
data = og
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
o.Data = data
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// FloorToNearestHour takes a timestamp (in milliseconds) and returns it rounded to the previous hour in UTC.
|
||||
func FloorToNearestHour(ms int64) int64 {
|
||||
t := time.Unix(0, ms*int64(1000*1000)).UTC()
|
||||
|
||||
return time.Date(t.Year(), t.Month(), t.Day(), t.Hour(), 0, 0, 0, time.UTC).UnixNano() / int64(time.Millisecond)
|
||||
}
|
||||
|
||||
// isRoundedToNearestHour returns true if the given timestamp (in milliseconds) has been rounded to the nearest hour in UTC.
|
||||
func isRoundedToNearestHour(ms int64) bool {
|
||||
return FloorToNearestHour(ms) == ms
|
||||
}
|
||||
|
||||
// GenerateLinkMetadataHash generates a unique hash for a given URL and timestamp for use as a database key.
|
||||
func GenerateLinkMetadataHash(url string, timestamp int64) int64 {
|
||||
hash := fnv.New32()
|
||||
|
||||
// Note that we ignore write errors here because the Hash interface says that its Write will never return an error
|
||||
binary.Write(hash, binary.LittleEndian, timestamp)
|
||||
hash.Write([]byte(url))
|
||||
|
||||
return int64(hash.Sum32())
|
||||
}
|
570
vendor/github.com/mattermost/mattermost-server/v5/model/manifest.go
generated
vendored
570
vendor/github.com/mattermost/mattermost-server/v5/model/manifest.go
generated
vendored
@ -1,570 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/blang/semver"
|
||||
"github.com/pkg/errors"
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
type PluginOption struct {
|
||||
// The display name for the option.
|
||||
DisplayName string `json:"display_name" yaml:"display_name"`
|
||||
|
||||
// The string value for the option.
|
||||
Value string `json:"value" yaml:"value"`
|
||||
}
|
||||
|
||||
type PluginSettingType int
|
||||
|
||||
const (
|
||||
Bool PluginSettingType = iota
|
||||
Dropdown
|
||||
Generated
|
||||
Radio
|
||||
Text
|
||||
LongText
|
||||
Number
|
||||
Username
|
||||
Custom
|
||||
)
|
||||
|
||||
type PluginSetting struct {
|
||||
// The key that the setting will be assigned to in the configuration file.
|
||||
Key string `json:"key" yaml:"key"`
|
||||
|
||||
// The display name for the setting.
|
||||
DisplayName string `json:"display_name" yaml:"display_name"`
|
||||
|
||||
// The type of the setting.
|
||||
//
|
||||
// "bool" will result in a boolean true or false setting.
|
||||
//
|
||||
// "dropdown" will result in a string setting that allows the user to select from a list of
|
||||
// pre-defined options.
|
||||
//
|
||||
// "generated" will result in a string setting that is set to a random, cryptographically secure
|
||||
// string.
|
||||
//
|
||||
// "radio" will result in a string setting that allows the user to select from a short selection
|
||||
// of pre-defined options.
|
||||
//
|
||||
// "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.
|
||||
//
|
||||
// "number" will result in in integer setting that can be typed in manually.
|
||||
//
|
||||
// "username" will result in a text setting that will autocomplete to a username.
|
||||
//
|
||||
// "custom" will result in a custom defined setting and will load the custom component registered for the Web App System Console.
|
||||
Type string `json:"type" yaml:"type"`
|
||||
|
||||
// The help text to display to the user. Supports Markdown formatting.
|
||||
HelpText string `json:"help_text" yaml:"help_text"`
|
||||
|
||||
// The help text to display alongside the "Regenerate" button for settings of the "generated" type.
|
||||
RegenerateHelpText string `json:"regenerate_help_text,omitempty" yaml:"regenerate_help_text,omitempty"`
|
||||
|
||||
// The placeholder to display for "generated", "text", "longtext", "number" and "username" types when blank.
|
||||
Placeholder string `json:"placeholder" yaml:"placeholder"`
|
||||
|
||||
// The default value of the setting.
|
||||
Default interface{} `json:"default" yaml:"default"`
|
||||
|
||||
// For "radio" or "dropdown" settings, this is the list of pre-defined options that the user can choose
|
||||
// from.
|
||||
Options []*PluginOption `json:"options,omitempty" yaml:"options,omitempty"`
|
||||
}
|
||||
|
||||
type PluginSettingsSchema struct {
|
||||
// Optional text to display above the settings. Supports Markdown formatting.
|
||||
Header string `json:"header" yaml:"header"`
|
||||
|
||||
// Optional text to display below the settings. Supports Markdown formatting.
|
||||
Footer string `json:"footer" yaml:"footer"`
|
||||
|
||||
// A list of setting definitions.
|
||||
Settings []*PluginSetting `json:"settings" yaml:"settings"`
|
||||
}
|
||||
|
||||
// The plugin manifest defines the metadata required to load and present your plugin. The manifest
|
||||
// file should be named plugin.json or plugin.yaml and placed in the top of your
|
||||
// plugin bundle.
|
||||
//
|
||||
// Example plugin.json:
|
||||
//
|
||||
//
|
||||
// {
|
||||
// "id": "com.mycompany.myplugin",
|
||||
// "name": "My Plugin",
|
||||
// "description": "This is my plugin",
|
||||
// "homepage_url": "https://example.com",
|
||||
// "support_url": "https://example.com/support",
|
||||
// "release_notes_url": "https://example.com/releases/v0.0.1",
|
||||
// "icon_path": "assets/logo.svg",
|
||||
// "version": "0.1.0",
|
||||
// "min_server_version": "5.6.0",
|
||||
// "server": {
|
||||
// "executables": {
|
||||
// "linux-amd64": "server/dist/plugin-linux-amd64",
|
||||
// "darwin-amd64": "server/dist/plugin-darwin-amd64",
|
||||
// "windows-amd64": "server/dist/plugin-windows-amd64.exe"
|
||||
// }
|
||||
// },
|
||||
// "webapp": {
|
||||
// "bundle_path": "webapp/dist/main.js"
|
||||
// },
|
||||
// "settings_schema": {
|
||||
// "header": "Some header text",
|
||||
// "footer": "Some footer text",
|
||||
// "settings": [{
|
||||
// "key": "someKey",
|
||||
// "display_name": "Enable Extra Feature",
|
||||
// "type": "bool",
|
||||
// "help_text": "When true, an extra feature will be enabled!",
|
||||
// "default": "false"
|
||||
// }]
|
||||
// },
|
||||
// "props": {
|
||||
// "someKey": "someData"
|
||||
// }
|
||||
// }
|
||||
type Manifest struct {
|
||||
// The id is a globally unique identifier that represents your plugin. Ids must be at least
|
||||
// 3 characters, at most 190 characters and must match ^[a-zA-Z0-9-_\.]+$.
|
||||
// Reverse-DNS notation using a name you control is a good option, e.g. "com.mycompany.myplugin".
|
||||
Id string `json:"id" yaml:"id"`
|
||||
|
||||
// The name to be displayed for the plugin.
|
||||
Name string `json:"name" yaml:"name"`
|
||||
|
||||
// A description of what your plugin is and does.
|
||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||
|
||||
// HomepageURL is an optional link to learn more about the plugin.
|
||||
HomepageURL string `json:"homepage_url,omitempty" yaml:"homepage_url,omitempty"`
|
||||
|
||||
// SupportURL is an optional URL where plugin issues can be reported.
|
||||
SupportURL string `json:"support_url,omitempty" yaml:"support_url,omitempty"`
|
||||
|
||||
// ReleaseNotesURL is an optional URL where a changelog for the release can be found.
|
||||
ReleaseNotesURL string `json:"release_notes_url,omitempty" yaml:"release_notes_url,omitempty"`
|
||||
|
||||
// A relative file path in the bundle that points to the plugins svg icon for use with the Plugin Marketplace.
|
||||
// This should be relative to the root of your bundle and the location of the manifest file. Bitmap image formats are not supported.
|
||||
IconPath string `json:"icon_path,omitempty" yaml:"icon_path,omitempty"`
|
||||
|
||||
// A version number for your plugin. Semantic versioning is recommended: http://semver.org
|
||||
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 *ManifestServer `json:"server,omitempty" yaml:"server,omitempty"`
|
||||
|
||||
// Backend is a deprecated flag for defining the server-side portion of your plugin. Going forward, use Server instead.
|
||||
Backend *ManifestServer `json:"backend,omitempty" yaml:"backend,omitempty"`
|
||||
|
||||
// If your plugin extends the web app, you'll need to define webapp.
|
||||
Webapp *ManifestWebapp `json:"webapp,omitempty" yaml:"webapp,omitempty"`
|
||||
|
||||
// To allow administrators to configure your plugin via the Mattermost system console, you can
|
||||
// provide your settings schema.
|
||||
SettingsSchema *PluginSettingsSchema `json:"settings_schema,omitempty" yaml:"settings_schema,omitempty"`
|
||||
|
||||
// Plugins can store any kind of data in Props to allow other plugins to use it.
|
||||
Props map[string]interface{} `json:"props,omitempty" yaml:"props,omitempty"`
|
||||
|
||||
// RequiredConfig defines any required server configuration fields for the plugin to function properly.
|
||||
//
|
||||
// Use the plugin helpers CheckRequiredServerConfiguration method to enforce this.
|
||||
RequiredConfig *Config `json:"required_configuration,omitempty" yaml:"required_configuration,omitempty"`
|
||||
}
|
||||
|
||||
type ManifestServer struct {
|
||||
// AllExecutables are the paths to your executable binaries, specifying multiple entry
|
||||
// points for different platforms when bundled together in a single plugin.
|
||||
AllExecutables map[string]string `json:"executables,omitempty" yaml:"executables,omitempty"`
|
||||
|
||||
// Executables is a legacy field populated with a subset of supported platform executables.
|
||||
// When unmarshalling, Executables is authoritative for the platform executable paths it
|
||||
// contains, overriding any values in AllExecutables. When marshalling, AllExecutables
|
||||
// is authoritative.
|
||||
//
|
||||
// Code duplication is avoided when (un)marshalling by leveraging type aliases in the
|
||||
// various (Un)Marshal(JSON|YAML) methods, since aliases don't inherit the aliased type's
|
||||
// methods.
|
||||
//
|
||||
// In v6.0, we should remove this field and rename AllExecutables back to Executables.
|
||||
Executables *ManifestExecutables `json:"-" yaml:"-"`
|
||||
|
||||
// Executable is the path to your executable binary. This should be relative to the root
|
||||
// of your bundle and the location of the manifest file.
|
||||
//
|
||||
// On Windows, this file must have a ".exe" extension.
|
||||
//
|
||||
// If your plugin is compiled for multiple platforms, consider bundling them together
|
||||
// and using the Executables field instead.
|
||||
Executable string `json:"executable" yaml:"executable"`
|
||||
}
|
||||
|
||||
func (ms *ManifestServer) MarshalJSON() ([]byte, error) {
|
||||
type auxManifestServer ManifestServer
|
||||
|
||||
// Populate AllExecutables from Executables, if it exists.
|
||||
if ms.Executables != nil {
|
||||
if ms.AllExecutables == nil {
|
||||
ms.AllExecutables = make(map[string]string)
|
||||
}
|
||||
|
||||
ms.AllExecutables["linux-amd64"] = ms.Executables.LinuxAmd64
|
||||
ms.AllExecutables["darwin-amd64"] = ms.Executables.DarwinAmd64
|
||||
ms.AllExecutables["windows-amd64"] = ms.Executables.WindowsAmd64
|
||||
}
|
||||
|
||||
return json.Marshal((*auxManifestServer)(ms))
|
||||
}
|
||||
|
||||
func (ms *ManifestServer) UnmarshalJSON(data []byte) error {
|
||||
type auxManifestServer ManifestServer
|
||||
|
||||
aux := (*auxManifestServer)(ms)
|
||||
if err := json.Unmarshal(data, aux); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(aux.AllExecutables) > 0 {
|
||||
ms.Executables = &ManifestExecutables{
|
||||
LinuxAmd64: aux.AllExecutables["linux-amd64"],
|
||||
DarwinAmd64: aux.AllExecutables["darwin-amd64"],
|
||||
WindowsAmd64: aux.AllExecutables["windows-amd64"],
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ms *ManifestServer) MarshalYAML() ([]byte, error) {
|
||||
type auxManifestServer ManifestServer
|
||||
|
||||
// Populate AllExecutables from Executables, if it exists.
|
||||
if ms.Executables != nil {
|
||||
if ms.AllExecutables == nil {
|
||||
ms.AllExecutables = make(map[string]string)
|
||||
}
|
||||
|
||||
ms.AllExecutables["linux-amd64"] = ms.Executables.LinuxAmd64
|
||||
ms.AllExecutables["darwin-amd64"] = ms.Executables.DarwinAmd64
|
||||
ms.AllExecutables["windows-amd64"] = ms.Executables.WindowsAmd64
|
||||
}
|
||||
|
||||
return yaml.Marshal((*auxManifestServer)(ms))
|
||||
}
|
||||
|
||||
func (ms *ManifestServer) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
||||
type auxManifestServer ManifestServer
|
||||
|
||||
aux := (*auxManifestServer)(ms)
|
||||
if err := unmarshal(&aux); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(aux.AllExecutables) > 0 {
|
||||
ms.Executables = &ManifestExecutables{
|
||||
LinuxAmd64: aux.AllExecutables["linux-amd64"],
|
||||
DarwinAmd64: aux.AllExecutables["darwin-amd64"],
|
||||
WindowsAmd64: aux.AllExecutables["windows-amd64"],
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ManifestExecutables is a legacy structure capturing a subet of the known platform executables.
|
||||
type ManifestExecutables struct {
|
||||
// LinuxAmd64 is the path to your executable binary for the corresponding platform
|
||||
LinuxAmd64 string `json:"linux-amd64,omitempty" yaml:"linux-amd64,omitempty"`
|
||||
// DarwinAmd64 is the path to your executable binary for the corresponding platform
|
||||
DarwinAmd64 string `json:"darwin-amd64,omitempty" yaml:"darwin-amd64,omitempty"`
|
||||
// WindowsAmd64 is the path to your executable binary for the corresponding platform
|
||||
// This file must have a ".exe" extension
|
||||
WindowsAmd64 string `json:"windows-amd64,omitempty" yaml:"windows-amd64,omitempty"`
|
||||
}
|
||||
|
||||
type ManifestWebapp struct {
|
||||
// The path to your webapp bundle. This should be relative to the root of your bundle and the
|
||||
// location of the manifest file.
|
||||
BundlePath string `json:"bundle_path" yaml:"bundle_path"`
|
||||
|
||||
// BundleHash is the 64-bit FNV-1a hash of the webapp bundle, computed when the plugin is loaded
|
||||
BundleHash []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Manifest) ToJson() string {
|
||||
b, _ := json.Marshal(m)
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func ManifestListToJson(m []*Manifest) string {
|
||||
b, _ := json.Marshal(m)
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func ManifestFromJson(data io.Reader) *Manifest {
|
||||
var m *Manifest
|
||||
json.NewDecoder(data).Decode(&m)
|
||||
return m
|
||||
}
|
||||
|
||||
func ManifestListFromJson(data io.Reader) []*Manifest {
|
||||
var manifests []*Manifest
|
||||
json.NewDecoder(data).Decode(&manifests)
|
||||
return manifests
|
||||
}
|
||||
|
||||
func (m *Manifest) HasClient() bool {
|
||||
return m.Webapp != nil
|
||||
}
|
||||
|
||||
func (m *Manifest) ClientManifest() *Manifest {
|
||||
cm := new(Manifest)
|
||||
*cm = *m
|
||||
cm.Name = ""
|
||||
cm.Description = ""
|
||||
cm.Server = nil
|
||||
if cm.Webapp != nil {
|
||||
cm.Webapp = new(ManifestWebapp)
|
||||
*cm.Webapp = *m.Webapp
|
||||
cm.Webapp.BundlePath = "/static/" + m.Id + "/" + fmt.Sprintf("%s_%x_bundle.js", m.Id, m.Webapp.BundleHash)
|
||||
}
|
||||
return cm
|
||||
}
|
||||
|
||||
// GetExecutableForRuntime returns the path to the executable for the given runtime architecture.
|
||||
//
|
||||
// If the manifest defines multiple executables, but none match, or if only a single executable
|
||||
// is defined, the Executable field will be returned. This method does not guarantee that the
|
||||
// resulting binary can actually execute on the given platform.
|
||||
func (m *Manifest) GetExecutableForRuntime(goOs, goArch string) string {
|
||||
server := m.Server
|
||||
|
||||
// Support the deprecated backend parameter.
|
||||
if server == nil {
|
||||
server = m.Backend
|
||||
}
|
||||
|
||||
if server == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
var executable string
|
||||
if len(server.AllExecutables) > 0 {
|
||||
osArch := fmt.Sprintf("%s-%s", goOs, goArch)
|
||||
executable = server.AllExecutables[osArch]
|
||||
}
|
||||
|
||||
if executable == "" {
|
||||
executable = server.Executable
|
||||
}
|
||||
|
||||
return executable
|
||||
}
|
||||
|
||||
func (m *Manifest) HasServer() bool {
|
||||
return m.Server != nil || m.Backend != nil
|
||||
}
|
||||
|
||||
func (m *Manifest) HasWebapp() bool {
|
||||
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
|
||||
}
|
||||
|
||||
func (m *Manifest) IsValid() error {
|
||||
if !IsValidPluginId(m.Id) {
|
||||
return errors.New("invalid plugin ID")
|
||||
}
|
||||
|
||||
if strings.TrimSpace(m.Name) == "" {
|
||||
return errors.New("a plugin name is needed")
|
||||
}
|
||||
|
||||
if m.HomepageURL != "" && !IsValidHttpUrl(m.HomepageURL) {
|
||||
return errors.New("invalid HomepageURL")
|
||||
}
|
||||
|
||||
if m.SupportURL != "" && !IsValidHttpUrl(m.SupportURL) {
|
||||
return errors.New("invalid SupportURL")
|
||||
}
|
||||
|
||||
if m.ReleaseNotesURL != "" && !IsValidHttpUrl(m.ReleaseNotesURL) {
|
||||
return errors.New("invalid ReleaseNotesURL")
|
||||
}
|
||||
|
||||
if m.Version != "" {
|
||||
_, err := semver.Parse(m.Version)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to parse Version")
|
||||
}
|
||||
}
|
||||
|
||||
if m.MinServerVersion != "" {
|
||||
_, err := semver.Parse(m.MinServerVersion)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to parse MinServerVersion")
|
||||
}
|
||||
}
|
||||
|
||||
if m.SettingsSchema != nil {
|
||||
err := m.SettingsSchema.isValid()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "invalid settings schema")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *PluginSettingsSchema) isValid() error {
|
||||
for _, setting := range s.Settings {
|
||||
err := setting.isValid()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *PluginSetting) isValid() error {
|
||||
pluginSettingType, err := convertTypeToPluginSettingType(s.Type)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if s.RegenerateHelpText != "" && pluginSettingType != Generated {
|
||||
return errors.New("should not set RegenerateHelpText for setting type that is not generated")
|
||||
}
|
||||
|
||||
if s.Placeholder != "" && !(pluginSettingType == Generated ||
|
||||
pluginSettingType == Text ||
|
||||
pluginSettingType == LongText ||
|
||||
pluginSettingType == Number ||
|
||||
pluginSettingType == Username) {
|
||||
return errors.New("should not set Placeholder for setting type not in text, generated or username")
|
||||
}
|
||||
|
||||
if s.Options != nil {
|
||||
if pluginSettingType != Radio && pluginSettingType != Dropdown {
|
||||
return errors.New("should not set Options for setting type not in radio or dropdown")
|
||||
}
|
||||
|
||||
for _, option := range s.Options {
|
||||
if option.DisplayName == "" || option.Value == "" {
|
||||
return errors.New("should not have empty Displayname or Value for any option")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func convertTypeToPluginSettingType(t string) (PluginSettingType, error) {
|
||||
var settingType PluginSettingType
|
||||
switch t {
|
||||
case "bool":
|
||||
return Bool, nil
|
||||
case "dropdown":
|
||||
return Dropdown, nil
|
||||
case "generated":
|
||||
return Generated, nil
|
||||
case "radio":
|
||||
return Radio, nil
|
||||
case "text":
|
||||
return Text, nil
|
||||
case "number":
|
||||
return Number, nil
|
||||
case "longtext":
|
||||
return LongText, nil
|
||||
case "username":
|
||||
return Username, nil
|
||||
case "custom":
|
||||
return Custom, nil
|
||||
default:
|
||||
return settingType, errors.New("invalid setting type: " + t)
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
// found.
|
||||
//
|
||||
// Manifests are JSON or YAML files named plugin.json, plugin.yaml, or plugin.yml.
|
||||
func FindManifest(dir string) (manifest *Manifest, path string, err error) {
|
||||
for _, name := range []string{"plugin.yml", "plugin.yaml"} {
|
||||
path = filepath.Join(dir, name)
|
||||
f, ferr := os.Open(path)
|
||||
if ferr != nil {
|
||||
if !os.IsNotExist(ferr) {
|
||||
return nil, "", ferr
|
||||
}
|
||||
continue
|
||||
}
|
||||
b, ioerr := ioutil.ReadAll(f)
|
||||
f.Close()
|
||||
if ioerr != nil {
|
||||
return nil, path, ioerr
|
||||
}
|
||||
var parsed Manifest
|
||||
err = yaml.Unmarshal(b, &parsed)
|
||||
if err != nil {
|
||||
return nil, path, err
|
||||
}
|
||||
manifest = &parsed
|
||||
manifest.Id = strings.ToLower(manifest.Id)
|
||||
return manifest, path, nil
|
||||
}
|
||||
|
||||
path = filepath.Join(dir, "plugin.json")
|
||||
f, ferr := os.Open(path)
|
||||
if ferr != nil {
|
||||
if os.IsNotExist(ferr) {
|
||||
path = ""
|
||||
}
|
||||
return nil, path, ferr
|
||||
}
|
||||
defer f.Close()
|
||||
var parsed Manifest
|
||||
err = json.NewDecoder(f).Decode(&parsed)
|
||||
if err != nil {
|
||||
return nil, path, err
|
||||
}
|
||||
manifest = &parsed
|
||||
manifest.Id = strings.ToLower(manifest.Id)
|
||||
return manifest, path, nil
|
||||
}
|
136
vendor/github.com/mattermost/mattermost-server/v5/model/marketplace_plugin.go
generated
vendored
136
vendor/github.com/mattermost/mattermost-server/v5/model/marketplace_plugin.go
generated
vendored
@ -1,136 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/url"
|
||||
"strconv"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// BaseMarketplacePlugin is a Mattermost plugin received from the Marketplace server.
|
||||
type BaseMarketplacePlugin struct {
|
||||
HomepageURL string `json:"homepage_url"`
|
||||
IconData string `json:"icon_data"`
|
||||
DownloadURL string `json:"download_url"`
|
||||
ReleaseNotesURL string `json:"release_notes_url"`
|
||||
Labels []MarketplaceLabel `json:"labels,omitempty"`
|
||||
Hosting string `json:"hosting"` // Indicated if the plugin is limited to a certain hosting type
|
||||
AuthorType string `json:"author_type"` // The maintainer of the plugin
|
||||
ReleaseStage string `json:"release_stage"` // The stage in the software release cycle that the plugin is in
|
||||
Enterprise bool `json:"enterprise"` // Indicated if the plugin is an enterprise plugin
|
||||
Signature string `json:"signature"` // Signature represents a signature of a plugin saved in base64 encoding.
|
||||
Manifest *Manifest `json:"manifest"`
|
||||
}
|
||||
|
||||
// MarketplaceLabel represents a label shown in the Marketplace UI.
|
||||
type MarketplaceLabel struct {
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
URL string `json:"url"`
|
||||
Color string `json:"color"`
|
||||
}
|
||||
|
||||
// MarketplacePlugin is a state aware Marketplace plugin.
|
||||
type MarketplacePlugin struct {
|
||||
*BaseMarketplacePlugin
|
||||
InstalledVersion string `json:"installed_version"`
|
||||
}
|
||||
|
||||
// BaseMarketplacePluginsFromReader decodes a json-encoded list of plugins from the given io.Reader.
|
||||
func BaseMarketplacePluginsFromReader(reader io.Reader) ([]*BaseMarketplacePlugin, error) {
|
||||
plugins := []*BaseMarketplacePlugin{}
|
||||
decoder := json.NewDecoder(reader)
|
||||
|
||||
if err := decoder.Decode(&plugins); err != nil && err != io.EOF {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return plugins, nil
|
||||
}
|
||||
|
||||
// MarketplacePluginsFromReader decodes a json-encoded list of plugins from the given io.Reader.
|
||||
func MarketplacePluginsFromReader(reader io.Reader) ([]*MarketplacePlugin, error) {
|
||||
plugins := []*MarketplacePlugin{}
|
||||
decoder := json.NewDecoder(reader)
|
||||
|
||||
if err := decoder.Decode(&plugins); err != nil && err != io.EOF {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return plugins, nil
|
||||
}
|
||||
|
||||
// DecodeSignature Decodes signature and returns ReadSeeker.
|
||||
func (plugin *BaseMarketplacePlugin) DecodeSignature() (io.ReadSeeker, error) {
|
||||
signatureBytes, err := base64.StdEncoding.DecodeString(plugin.Signature)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Unable to decode base64 signature.")
|
||||
}
|
||||
return bytes.NewReader(signatureBytes), nil
|
||||
}
|
||||
|
||||
// MarketplacePluginFilter describes the parameters to request a list of plugins.
|
||||
type MarketplacePluginFilter struct {
|
||||
Page int
|
||||
PerPage int
|
||||
Filter string
|
||||
ServerVersion string
|
||||
BuildEnterpriseReady bool
|
||||
EnterprisePlugins bool
|
||||
Cloud bool
|
||||
LocalOnly bool
|
||||
Platform string
|
||||
PluginId string
|
||||
ReturnAllVersions bool
|
||||
}
|
||||
|
||||
// ApplyToURL modifies the given url to include query string parameters for the request.
|
||||
func (filter *MarketplacePluginFilter) ApplyToURL(u *url.URL) {
|
||||
q := u.Query()
|
||||
q.Add("page", strconv.Itoa(filter.Page))
|
||||
if filter.PerPage > 0 {
|
||||
q.Add("per_page", strconv.Itoa(filter.PerPage))
|
||||
}
|
||||
q.Add("filter", filter.Filter)
|
||||
q.Add("server_version", filter.ServerVersion)
|
||||
q.Add("build_enterprise_ready", strconv.FormatBool(filter.BuildEnterpriseReady))
|
||||
q.Add("enterprise_plugins", strconv.FormatBool(filter.EnterprisePlugins))
|
||||
q.Add("cloud", strconv.FormatBool(filter.Cloud))
|
||||
q.Add("local_only", strconv.FormatBool(filter.LocalOnly))
|
||||
q.Add("platform", filter.Platform)
|
||||
q.Add("plugin_id", filter.PluginId)
|
||||
q.Add("return_all_versions", strconv.FormatBool(filter.ReturnAllVersions))
|
||||
u.RawQuery = q.Encode()
|
||||
}
|
||||
|
||||
// InstallMarketplacePluginRequest struct describes parameters of the requested plugin.
|
||||
type InstallMarketplacePluginRequest struct {
|
||||
Id string `json:"id"`
|
||||
Version string `json:"version"`
|
||||
}
|
||||
|
||||
// PluginRequestFromReader decodes a json-encoded plugin request from the given io.Reader.
|
||||
func PluginRequestFromReader(reader io.Reader) (*InstallMarketplacePluginRequest, error) {
|
||||
var r *InstallMarketplacePluginRequest
|
||||
err := json.NewDecoder(reader).Decode(&r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return r, nil
|
||||
}
|
||||
|
||||
// ToJson method will return json from plugin request.
|
||||
func (r *InstallMarketplacePluginRequest) ToJson() (string, error) {
|
||||
b, err := json.Marshal(r)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(b), nil
|
||||
}
|
80
vendor/github.com/mattermost/mattermost-server/v5/model/mention_map.go
generated
vendored
80
vendor/github.com/mattermost/mattermost-server/v5/model/mention_map.go
generated
vendored
@ -1,80 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
type UserMentionMap map[string]string
|
||||
type ChannelMentionMap map[string]string
|
||||
|
||||
const (
|
||||
userMentionsKey = "user_mentions"
|
||||
userMentionsIdsKey = "user_mentions_ids"
|
||||
channelMentionsKey = "channel_mentions"
|
||||
channelMentionsIdsKey = "channel_mentions_ids"
|
||||
)
|
||||
|
||||
func UserMentionMapFromURLValues(values url.Values) (UserMentionMap, error) {
|
||||
return mentionsFromURLValues(values, userMentionsKey, userMentionsIdsKey)
|
||||
}
|
||||
|
||||
func (m UserMentionMap) ToURLValues() url.Values {
|
||||
return mentionsToURLValues(m, userMentionsKey, userMentionsIdsKey)
|
||||
}
|
||||
|
||||
func ChannelMentionMapFromURLValues(values url.Values) (ChannelMentionMap, error) {
|
||||
return mentionsFromURLValues(values, channelMentionsKey, channelMentionsIdsKey)
|
||||
}
|
||||
|
||||
func (m ChannelMentionMap) ToURLValues() url.Values {
|
||||
return mentionsToURLValues(m, channelMentionsKey, channelMentionsIdsKey)
|
||||
}
|
||||
|
||||
func mentionsFromURLValues(values url.Values, mentionKey, idKey string) (map[string]string, error) {
|
||||
mentions, mentionsOk := values[mentionKey]
|
||||
ids, idsOk := values[idKey]
|
||||
|
||||
if !mentionsOk && !idsOk {
|
||||
return map[string]string{}, nil
|
||||
}
|
||||
|
||||
if !mentionsOk {
|
||||
return nil, fmt.Errorf("%s key not found", mentionKey)
|
||||
}
|
||||
|
||||
if !idsOk {
|
||||
return nil, fmt.Errorf("%s key not found", idKey)
|
||||
}
|
||||
|
||||
if len(mentions) != len(ids) {
|
||||
return nil, fmt.Errorf("keys %s and %s have different length", mentionKey, idKey)
|
||||
}
|
||||
|
||||
mentionsMap := make(map[string]string)
|
||||
for i, mention := range mentions {
|
||||
id := ids[i]
|
||||
|
||||
if oldId, ok := mentionsMap[mention]; ok && oldId != id {
|
||||
return nil, fmt.Errorf("key %s has two different values: %s and %s", mention, oldId, id)
|
||||
}
|
||||
|
||||
mentionsMap[mention] = id
|
||||
}
|
||||
|
||||
return mentionsMap, nil
|
||||
}
|
||||
|
||||
func mentionsToURLValues(mentions map[string]string, mentionKey, idKey string) url.Values {
|
||||
values := url.Values{}
|
||||
|
||||
for mention, id := range mentions {
|
||||
values.Add(mentionKey, mention)
|
||||
values.Add(idKey, id)
|
||||
}
|
||||
|
||||
return values
|
||||
}
|
36
vendor/github.com/mattermost/mattermost-server/v5/model/message_export.go
generated
vendored
36
vendor/github.com/mattermost/mattermost-server/v5/model/message_export.go
generated
vendored
@ -1,36 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
type MessageExport struct {
|
||||
TeamId *string
|
||||
TeamName *string
|
||||
TeamDisplayName *string
|
||||
|
||||
ChannelId *string
|
||||
ChannelName *string
|
||||
ChannelDisplayName *string
|
||||
ChannelType *string
|
||||
|
||||
UserId *string
|
||||
UserEmail *string
|
||||
Username *string
|
||||
IsBot bool
|
||||
|
||||
PostId *string
|
||||
PostCreateAt *int64
|
||||
PostUpdateAt *int64
|
||||
PostDeleteAt *int64
|
||||
PostMessage *string
|
||||
PostType *string
|
||||
PostRootId *string
|
||||
PostProps *string
|
||||
PostOriginalId *string
|
||||
PostFileIds StringArray
|
||||
}
|
||||
|
||||
type MessageExportCursor struct {
|
||||
LastPostUpdateAt int64
|
||||
LastPostId string
|
||||
}
|
25
vendor/github.com/mattermost/mattermost-server/v5/model/mfa_secret.go
generated
vendored
25
vendor/github.com/mattermost/mattermost-server/v5/model/mfa_secret.go
generated
vendored
@ -1,25 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
)
|
||||
|
||||
type MfaSecret struct {
|
||||
Secret string `json:"secret"`
|
||||
QRCode string `json:"qr_code"`
|
||||
}
|
||||
|
||||
func (mfa *MfaSecret) ToJson() string {
|
||||
b, _ := json.Marshal(mfa)
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func MfaSecretFromJson(data io.Reader) *MfaSecret {
|
||||
var mfa *MfaSecret
|
||||
json.NewDecoder(data).Decode(&mfa)
|
||||
return mfa
|
||||
}
|
38
vendor/github.com/mattermost/mattermost-server/v5/model/migration.go
generated
vendored
38
vendor/github.com/mattermost/mattermost-server/v5/model/migration.go
generated
vendored
@ -1,38 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
const (
|
||||
ADVANCED_PERMISSIONS_MIGRATION_KEY = "AdvancedPermissionsMigrationComplete"
|
||||
MIGRATION_KEY_ADVANCED_PERMISSIONS_PHASE_2 = "migration_advanced_permissions_phase_2"
|
||||
|
||||
MIGRATION_KEY_EMOJI_PERMISSIONS_SPLIT = "emoji_permissions_split"
|
||||
MIGRATION_KEY_WEBHOOK_PERMISSIONS_SPLIT = "webhook_permissions_split"
|
||||
MIGRATION_KEY_LIST_JOIN_PUBLIC_PRIVATE_TEAMS = "list_join_public_private_teams"
|
||||
MIGRATION_KEY_REMOVE_PERMANENT_DELETE_USER = "remove_permanent_delete_user"
|
||||
MIGRATION_KEY_ADD_BOT_PERMISSIONS = "add_bot_permissions"
|
||||
MIGRATION_KEY_APPLY_CHANNEL_MANAGE_DELETE_TO_CHANNEL_USER = "apply_channel_manage_delete_to_channel_user"
|
||||
MIGRATION_KEY_REMOVE_CHANNEL_MANAGE_DELETE_FROM_TEAM_USER = "remove_channel_manage_delete_from_team_user"
|
||||
MIGRATION_KEY_VIEW_MEMBERS_NEW_PERMISSION = "view_members_new_permission"
|
||||
MIGRATION_KEY_ADD_MANAGE_GUESTS_PERMISSIONS = "add_manage_guests_permissions"
|
||||
MIGRATION_KEY_CHANNEL_MODERATIONS_PERMISSIONS = "channel_moderations_permissions"
|
||||
MIGRATION_KEY_ADD_USE_GROUP_MENTIONS_PERMISSION = "add_use_group_mentions_permission"
|
||||
MIGRATION_KEY_ADD_SYSTEM_CONSOLE_PERMISSIONS = "add_system_console_permissions"
|
||||
MIGRATION_KEY_SIDEBAR_CATEGORIES_PHASE_2 = "migration_sidebar_categories_phase_2"
|
||||
MIGRATION_KEY_ADD_CONVERT_CHANNEL_PERMISSIONS = "add_convert_channel_permissions"
|
||||
MIGRATION_KEY_ADD_SYSTEM_ROLES_PERMISSIONS = "add_system_roles_permissions"
|
||||
MIGRATION_KEY_ADD_BILLING_PERMISSIONS = "add_billing_permissions"
|
||||
MIGRATION_KEY_ADD_MANAGE_SHARED_CHANNEL_PERMISSIONS = "manage_shared_channel_permissions"
|
||||
MIGRATION_KEY_ADD_MANAGE_SECURE_CONNECTIONS_PERMISSIONS = "manage_secure_connections_permissions"
|
||||
MIGRATION_KEY_ADD_DOWNLOAD_COMPLIANCE_EXPORT_RESULTS = "download_compliance_export_results"
|
||||
MIGRATION_KEY_ADD_COMPLIANCE_SUBSECTION_PERMISSIONS = "compliance_subsection_permissions"
|
||||
MIGRATION_KEY_ADD_EXPERIMENTAL_SUBSECTION_PERMISSIONS = "experimental_subsection_permissions"
|
||||
MIGRATION_KEY_ADD_AUTHENTICATION_SUBSECTION_PERMISSIONS = "authentication_subsection_permissions"
|
||||
MIGRATION_KEY_ADD_SITE_SUBSECTION_PERMISSIONS = "site_subsection_permissions"
|
||||
MIGRATION_KEY_ADD_ENVIRONMENT_SUBSECTION_PERMISSIONS = "environment_subsection_permissions"
|
||||
MIGRATION_KEY_ADD_REPORTING_SUBSECTION_PERMISSIONS = "reporting_subsection_permissions"
|
||||
MIGRATION_KEY_ADD_TEST_EMAIL_ANCILLARY_PERMISSION = "test_email_ancillary_permission"
|
||||
MIGRATION_KEY_ADD_ABOUT_SUBSECTION_PERMISSIONS = "about_subsection_permissions"
|
||||
MIGRATION_KEY_ADD_INTEGRATIONS_SUBSECTION_PERMISSIONS = "integrations_subsection_permissions"
|
||||
)
|
151
vendor/github.com/mattermost/mattermost-server/v5/model/oauth.go
generated
vendored
151
vendor/github.com/mattermost/mattermost-server/v5/model/oauth.go
generated
vendored
@ -1,151 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
const (
|
||||
OAUTH_ACTION_SIGNUP = "signup"
|
||||
OAUTH_ACTION_LOGIN = "login"
|
||||
OAUTH_ACTION_EMAIL_TO_SSO = "email_to_sso"
|
||||
OAUTH_ACTION_SSO_TO_EMAIL = "sso_to_email"
|
||||
OAUTH_ACTION_MOBILE = "mobile"
|
||||
)
|
||||
|
||||
type OAuthApp struct {
|
||||
Id string `json:"id"`
|
||||
CreatorId string `json:"creator_id"`
|
||||
CreateAt int64 `json:"create_at"`
|
||||
UpdateAt int64 `json:"update_at"`
|
||||
ClientSecret string `json:"client_secret"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
IconURL string `json:"icon_url"`
|
||||
CallbackUrls StringArray `json:"callback_urls"`
|
||||
Homepage string `json:"homepage"`
|
||||
IsTrusted bool `json:"is_trusted"`
|
||||
}
|
||||
|
||||
// IsValid validates the app and returns an error if it isn't configured
|
||||
// correctly.
|
||||
func (a *OAuthApp) IsValid() *AppError {
|
||||
|
||||
if !IsValidId(a.Id) {
|
||||
return NewAppError("OAuthApp.IsValid", "model.oauth.is_valid.app_id.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if a.CreateAt == 0 {
|
||||
return NewAppError("OAuthApp.IsValid", "model.oauth.is_valid.create_at.app_error", nil, "app_id="+a.Id, http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if a.UpdateAt == 0 {
|
||||
return NewAppError("OAuthApp.IsValid", "model.oauth.is_valid.update_at.app_error", nil, "app_id="+a.Id, http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if !IsValidId(a.CreatorId) {
|
||||
return NewAppError("OAuthApp.IsValid", "model.oauth.is_valid.creator_id.app_error", nil, "app_id="+a.Id, http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if a.ClientSecret == "" || len(a.ClientSecret) > 128 {
|
||||
return NewAppError("OAuthApp.IsValid", "model.oauth.is_valid.client_secret.app_error", nil, "app_id="+a.Id, http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if a.Name == "" || len(a.Name) > 64 {
|
||||
return NewAppError("OAuthApp.IsValid", "model.oauth.is_valid.name.app_error", nil, "app_id="+a.Id, http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if len(a.CallbackUrls) == 0 || len(fmt.Sprintf("%s", a.CallbackUrls)) > 1024 {
|
||||
return NewAppError("OAuthApp.IsValid", "model.oauth.is_valid.callback.app_error", nil, "app_id="+a.Id, http.StatusBadRequest)
|
||||
}
|
||||
|
||||
for _, callback := range a.CallbackUrls {
|
||||
if !IsValidHttpUrl(callback) {
|
||||
return NewAppError("OAuthApp.IsValid", "model.oauth.is_valid.callback.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
}
|
||||
|
||||
if a.Homepage == "" || len(a.Homepage) > 256 || !IsValidHttpUrl(a.Homepage) {
|
||||
return NewAppError("OAuthApp.IsValid", "model.oauth.is_valid.homepage.app_error", nil, "app_id="+a.Id, http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if utf8.RuneCountInString(a.Description) > 512 {
|
||||
return NewAppError("OAuthApp.IsValid", "model.oauth.is_valid.description.app_error", nil, "app_id="+a.Id, http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if a.IconURL != "" {
|
||||
if len(a.IconURL) > 512 || !IsValidHttpUrl(a.IconURL) {
|
||||
return NewAppError("OAuthApp.IsValid", "model.oauth.is_valid.icon_url.app_error", nil, "app_id="+a.Id, http.StatusBadRequest)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// PreSave will set the Id and ClientSecret if missing. It will also fill
|
||||
// in the CreateAt, UpdateAt times. It should be run before saving the app to the db.
|
||||
func (a *OAuthApp) PreSave() {
|
||||
if a.Id == "" {
|
||||
a.Id = NewId()
|
||||
}
|
||||
|
||||
if a.ClientSecret == "" {
|
||||
a.ClientSecret = NewId()
|
||||
}
|
||||
|
||||
a.CreateAt = GetMillis()
|
||||
a.UpdateAt = a.CreateAt
|
||||
}
|
||||
|
||||
// PreUpdate should be run before updating the app in the db.
|
||||
func (a *OAuthApp) PreUpdate() {
|
||||
a.UpdateAt = GetMillis()
|
||||
}
|
||||
|
||||
func (a *OAuthApp) ToJson() string {
|
||||
b, _ := json.Marshal(a)
|
||||
return string(b)
|
||||
}
|
||||
|
||||
// Generate a valid strong etag so the browser can cache the results
|
||||
func (a *OAuthApp) Etag() string {
|
||||
return Etag(a.Id, a.UpdateAt)
|
||||
}
|
||||
|
||||
// Remove any private data from the app object
|
||||
func (a *OAuthApp) Sanitize() {
|
||||
a.ClientSecret = ""
|
||||
}
|
||||
|
||||
func (a *OAuthApp) IsValidRedirectURL(url string) bool {
|
||||
for _, u := range a.CallbackUrls {
|
||||
if u == url {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func OAuthAppFromJson(data io.Reader) *OAuthApp {
|
||||
var app *OAuthApp
|
||||
json.NewDecoder(data).Decode(&app)
|
||||
return app
|
||||
}
|
||||
|
||||
func OAuthAppListToJson(l []*OAuthApp) string {
|
||||
b, _ := json.Marshal(l)
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func OAuthAppListFromJson(data io.Reader) []*OAuthApp {
|
||||
var o []*OAuthApp
|
||||
json.NewDecoder(data).Decode(&o)
|
||||
return o
|
||||
}
|
267
vendor/github.com/mattermost/mattermost-server/v5/model/outgoing_webhook.go
generated
vendored
267
vendor/github.com/mattermost/mattermost-server/v5/model/outgoing_webhook.go
generated
vendored
@ -1,267 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type OutgoingWebhook struct {
|
||||
Id string `json:"id"`
|
||||
Token string `json:"token"`
|
||||
CreateAt int64 `json:"create_at"`
|
||||
UpdateAt int64 `json:"update_at"`
|
||||
DeleteAt int64 `json:"delete_at"`
|
||||
CreatorId string `json:"creator_id"`
|
||||
ChannelId string `json:"channel_id"`
|
||||
TeamId string `json:"team_id"`
|
||||
TriggerWords StringArray `json:"trigger_words"`
|
||||
TriggerWhen int `json:"trigger_when"`
|
||||
CallbackURLs StringArray `json:"callback_urls"`
|
||||
DisplayName string `json:"display_name"`
|
||||
Description string `json:"description"`
|
||||
ContentType string `json:"content_type"`
|
||||
Username string `json:"username"`
|
||||
IconURL string `json:"icon_url"`
|
||||
}
|
||||
|
||||
type OutgoingWebhookPayload struct {
|
||||
Token string `json:"token"`
|
||||
TeamId string `json:"team_id"`
|
||||
TeamDomain string `json:"team_domain"`
|
||||
ChannelId string `json:"channel_id"`
|
||||
ChannelName string `json:"channel_name"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
UserId string `json:"user_id"`
|
||||
UserName string `json:"user_name"`
|
||||
PostId string `json:"post_id"`
|
||||
Text string `json:"text"`
|
||||
TriggerWord string `json:"trigger_word"`
|
||||
FileIds string `json:"file_ids"`
|
||||
}
|
||||
|
||||
type OutgoingWebhookResponse struct {
|
||||
Text *string `json:"text"`
|
||||
Username string `json:"username"`
|
||||
IconURL string `json:"icon_url"`
|
||||
Props StringInterface `json:"props"`
|
||||
Attachments []*SlackAttachment `json:"attachments"`
|
||||
Type string `json:"type"`
|
||||
ResponseType string `json:"response_type"`
|
||||
}
|
||||
|
||||
const OUTGOING_HOOK_RESPONSE_TYPE_COMMENT = "comment"
|
||||
|
||||
func (o *OutgoingWebhookPayload) ToJSON() string {
|
||||
b, _ := json.Marshal(o)
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func (o *OutgoingWebhookPayload) ToFormValues() string {
|
||||
v := url.Values{}
|
||||
v.Set("token", o.Token)
|
||||
v.Set("team_id", o.TeamId)
|
||||
v.Set("team_domain", o.TeamDomain)
|
||||
v.Set("channel_id", o.ChannelId)
|
||||
v.Set("channel_name", o.ChannelName)
|
||||
v.Set("timestamp", strconv.FormatInt(o.Timestamp/1000, 10))
|
||||
v.Set("user_id", o.UserId)
|
||||
v.Set("user_name", o.UserName)
|
||||
v.Set("post_id", o.PostId)
|
||||
v.Set("text", o.Text)
|
||||
v.Set("trigger_word", o.TriggerWord)
|
||||
v.Set("file_ids", o.FileIds)
|
||||
|
||||
return v.Encode()
|
||||
}
|
||||
|
||||
func (o *OutgoingWebhook) ToJson() string {
|
||||
b, _ := json.Marshal(o)
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func OutgoingWebhookFromJson(data io.Reader) *OutgoingWebhook {
|
||||
var o *OutgoingWebhook
|
||||
json.NewDecoder(data).Decode(&o)
|
||||
return o
|
||||
}
|
||||
|
||||
func OutgoingWebhookListToJson(l []*OutgoingWebhook) string {
|
||||
b, _ := json.Marshal(l)
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func OutgoingWebhookListFromJson(data io.Reader) []*OutgoingWebhook {
|
||||
var o []*OutgoingWebhook
|
||||
json.NewDecoder(data).Decode(&o)
|
||||
return o
|
||||
}
|
||||
|
||||
func (o *OutgoingWebhookResponse) ToJson() string {
|
||||
b, _ := json.Marshal(o)
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func OutgoingWebhookResponseFromJson(data io.Reader) (*OutgoingWebhookResponse, error) {
|
||||
var o *OutgoingWebhookResponse
|
||||
err := json.NewDecoder(data).Decode(&o)
|
||||
if err == io.EOF {
|
||||
return nil, nil
|
||||
}
|
||||
return o, err
|
||||
}
|
||||
|
||||
func (o *OutgoingWebhook) IsValid() *AppError {
|
||||
|
||||
if !IsValidId(o.Id) {
|
||||
return NewAppError("OutgoingWebhook.IsValid", "model.outgoing_hook.is_valid.id.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if len(o.Token) != 26 {
|
||||
return NewAppError("OutgoingWebhook.IsValid", "model.outgoing_hook.is_valid.token.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if o.CreateAt == 0 {
|
||||
return NewAppError("OutgoingWebhook.IsValid", "model.outgoing_hook.is_valid.create_at.app_error", nil, "id="+o.Id, http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if o.UpdateAt == 0 {
|
||||
return NewAppError("OutgoingWebhook.IsValid", "model.outgoing_hook.is_valid.update_at.app_error", nil, "id="+o.Id, http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if !IsValidId(o.CreatorId) {
|
||||
return NewAppError("OutgoingWebhook.IsValid", "model.outgoing_hook.is_valid.user_id.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if o.ChannelId != "" && !IsValidId(o.ChannelId) {
|
||||
return NewAppError("OutgoingWebhook.IsValid", "model.outgoing_hook.is_valid.channel_id.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if !IsValidId(o.TeamId) {
|
||||
return NewAppError("OutgoingWebhook.IsValid", "model.outgoing_hook.is_valid.team_id.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if len(fmt.Sprintf("%s", o.TriggerWords)) > 1024 {
|
||||
return NewAppError("OutgoingWebhook.IsValid", "model.outgoing_hook.is_valid.words.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if len(o.TriggerWords) != 0 {
|
||||
for _, triggerWord := range o.TriggerWords {
|
||||
if triggerWord == "" {
|
||||
return NewAppError("OutgoingWebhook.IsValid", "model.outgoing_hook.is_valid.trigger_words.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(o.CallbackURLs) == 0 || len(fmt.Sprintf("%s", o.CallbackURLs)) > 1024 {
|
||||
return NewAppError("OutgoingWebhook.IsValid", "model.outgoing_hook.is_valid.callback.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
for _, callback := range o.CallbackURLs {
|
||||
if !IsValidHttpUrl(callback) {
|
||||
return NewAppError("OutgoingWebhook.IsValid", "model.outgoing_hook.is_valid.url.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
}
|
||||
|
||||
if len(o.DisplayName) > 64 {
|
||||
return NewAppError("OutgoingWebhook.IsValid", "model.outgoing_hook.is_valid.display_name.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if len(o.Description) > 500 {
|
||||
return NewAppError("OutgoingWebhook.IsValid", "model.outgoing_hook.is_valid.description.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if len(o.ContentType) > 128 {
|
||||
return NewAppError("OutgoingWebhook.IsValid", "model.outgoing_hook.is_valid.content_type.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if o.TriggerWhen > 1 {
|
||||
return NewAppError("OutgoingWebhook.IsValid", "model.outgoing_hook.is_valid.content_type.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if len(o.Username) > 64 {
|
||||
return NewAppError("OutgoingWebhook.IsValid", "model.outgoing_hook.username.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if len(o.IconURL) > 1024 {
|
||||
return NewAppError("OutgoingWebhook.IsValid", "model.outgoing_hook.icon_url.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *OutgoingWebhook) PreSave() {
|
||||
if o.Id == "" {
|
||||
o.Id = NewId()
|
||||
}
|
||||
|
||||
if o.Token == "" {
|
||||
o.Token = NewId()
|
||||
}
|
||||
|
||||
o.CreateAt = GetMillis()
|
||||
o.UpdateAt = o.CreateAt
|
||||
}
|
||||
|
||||
func (o *OutgoingWebhook) PreUpdate() {
|
||||
o.UpdateAt = GetMillis()
|
||||
}
|
||||
|
||||
func (o *OutgoingWebhook) TriggerWordExactMatch(word string) bool {
|
||||
if word == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
for _, trigger := range o.TriggerWords {
|
||||
if trigger == word {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (o *OutgoingWebhook) TriggerWordStartsWith(word string) bool {
|
||||
if word == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
for _, trigger := range o.TriggerWords {
|
||||
if strings.HasPrefix(word, trigger) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (o *OutgoingWebhook) GetTriggerWord(word string, isExactMatch bool) (triggerWord string) {
|
||||
if word == "" {
|
||||
return
|
||||
}
|
||||
|
||||
if isExactMatch {
|
||||
for _, trigger := range o.TriggerWords {
|
||||
if trigger == word {
|
||||
triggerWord = trigger
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for _, trigger := range o.TriggerWords {
|
||||
if strings.HasPrefix(word, trigger) {
|
||||
triggerWord = trigger
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return triggerWord
|
||||
}
|
2192
vendor/github.com/mattermost/mattermost-server/v5/model/permission.go
generated
vendored
2192
vendor/github.com/mattermost/mattermost-server/v5/model/permission.go
generated
vendored
File diff suppressed because it is too large
Load Diff
28
vendor/github.com/mattermost/mattermost-server/v5/model/plugin_cluster_event.go
generated
vendored
28
vendor/github.com/mattermost/mattermost-server/v5/model/plugin_cluster_event.go
generated
vendored
@ -1,28 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
const (
|
||||
PluginClusterEventSendTypeReliable = CLUSTER_SEND_RELIABLE
|
||||
PluginClusterEventSendTypeBestEffort = CLUSTER_SEND_BEST_EFFORT
|
||||
)
|
||||
|
||||
// PluginClusterEvent is used to allow intra-cluster plugin communication.
|
||||
type PluginClusterEvent struct {
|
||||
// Id is the unique identifier for the event.
|
||||
Id string
|
||||
// Data is the event payload.
|
||||
Data []byte
|
||||
}
|
||||
|
||||
// PluginClusterEventSendOptions defines some properties that apply when sending
|
||||
// plugin events across a cluster.
|
||||
type PluginClusterEventSendOptions struct {
|
||||
// SendType defines the type of communication channel used to send the event.
|
||||
SendType string
|
||||
// TargetId identifies the cluster node to which the event should be sent.
|
||||
// It should match the cluster id of the receiving instance.
|
||||
// If empty, the event gets broadcasted to all other nodes.
|
||||
TargetId string
|
||||
}
|
25
vendor/github.com/mattermost/mattermost-server/v5/model/plugin_event_data.go
generated
vendored
25
vendor/github.com/mattermost/mattermost-server/v5/model/plugin_event_data.go
generated
vendored
@ -1,25 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
)
|
||||
|
||||
// PluginEventData used to notify peers about plugin changes.
|
||||
type PluginEventData struct {
|
||||
Id string `json:"id"`
|
||||
}
|
||||
|
||||
func (p *PluginEventData) ToJson() string {
|
||||
b, _ := json.Marshal(p)
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func PluginEventDataFromJson(data io.Reader) PluginEventData {
|
||||
var m PluginEventData
|
||||
json.NewDecoder(data).Decode(&m)
|
||||
return m
|
||||
}
|
33
vendor/github.com/mattermost/mattermost-server/v5/model/plugin_key_value.go
generated
vendored
33
vendor/github.com/mattermost/mattermost-server/v5/model/plugin_key_value.go
generated
vendored
@ -1,33 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
const (
|
||||
KEY_VALUE_PLUGIN_ID_MAX_RUNES = 190
|
||||
KEY_VALUE_KEY_MAX_RUNES = 50
|
||||
)
|
||||
|
||||
type PluginKeyValue struct {
|
||||
PluginId string `json:"plugin_id"`
|
||||
Key string `json:"key" db:"PKey"`
|
||||
Value []byte `json:"value" db:"PValue"`
|
||||
ExpireAt int64 `json:"expire_at"`
|
||||
}
|
||||
|
||||
func (kv *PluginKeyValue) IsValid() *AppError {
|
||||
if kv.PluginId == "" || utf8.RuneCountInString(kv.PluginId) > KEY_VALUE_PLUGIN_ID_MAX_RUNES {
|
||||
return NewAppError("PluginKeyValue.IsValid", "model.plugin_key_value.is_valid.plugin_id.app_error", map[string]interface{}{"Max": KEY_VALUE_KEY_MAX_RUNES, "Min": 0}, "key="+kv.Key, http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if kv.Key == "" || utf8.RuneCountInString(kv.Key) > KEY_VALUE_KEY_MAX_RUNES {
|
||||
return NewAppError("PluginKeyValue.IsValid", "model.plugin_key_value.is_valid.key.app_error", map[string]interface{}{"Max": KEY_VALUE_KEY_MAX_RUNES, "Min": 0}, "key="+kv.Key, http.StatusBadRequest)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
47
vendor/github.com/mattermost/mattermost-server/v5/model/plugin_kvset_options.go
generated
vendored
47
vendor/github.com/mattermost/mattermost-server/v5/model/plugin_kvset_options.go
generated
vendored
@ -1,47 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// PluginKVSetOptions contains information on how to store a value in the plugin KV store.
|
||||
type PluginKVSetOptions struct {
|
||||
Atomic bool // Only store the value if the current value matches the oldValue
|
||||
OldValue []byte // The value to compare with the current value. Only used when Atomic is true
|
||||
ExpireInSeconds int64 // Set an expire counter
|
||||
}
|
||||
|
||||
// IsValid returns nil if the chosen options are valid.
|
||||
func (opt *PluginKVSetOptions) IsValid() *AppError {
|
||||
if !opt.Atomic && opt.OldValue != nil {
|
||||
return NewAppError(
|
||||
"PluginKVSetOptions.IsValid",
|
||||
"model.plugin_kvset_options.is_valid.old_value.app_error",
|
||||
nil,
|
||||
"",
|
||||
http.StatusBadRequest,
|
||||
)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewPluginKeyValueFromOptions return a PluginKeyValue given a pluginID, a KV pair and options.
|
||||
func NewPluginKeyValueFromOptions(pluginId, key string, value []byte, opt PluginKVSetOptions) (*PluginKeyValue, *AppError) {
|
||||
expireAt := int64(0)
|
||||
if opt.ExpireInSeconds != 0 {
|
||||
expireAt = GetMillis() + (opt.ExpireInSeconds * 1000)
|
||||
}
|
||||
|
||||
kv := &PluginKeyValue{
|
||||
PluginId: pluginId,
|
||||
Key: key,
|
||||
Value: value,
|
||||
ExpireAt: expireAt,
|
||||
}
|
||||
|
||||
return kv, nil
|
||||
}
|
42
vendor/github.com/mattermost/mattermost-server/v5/model/plugin_status.go
generated
vendored
42
vendor/github.com/mattermost/mattermost-server/v5/model/plugin_status.go
generated
vendored
@ -1,42 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
)
|
||||
|
||||
const (
|
||||
PluginStateNotRunning = 0
|
||||
PluginStateStarting = 1 // unused by server
|
||||
PluginStateRunning = 2
|
||||
PluginStateFailedToStart = 3
|
||||
PluginStateFailedToStayRunning = 4
|
||||
PluginStateStopping = 5 // unused by server
|
||||
)
|
||||
|
||||
// PluginStatus provides a cluster-aware view of installed plugins.
|
||||
type PluginStatus struct {
|
||||
PluginId string `json:"plugin_id"`
|
||||
ClusterId string `json:"cluster_id"`
|
||||
PluginPath string `json:"plugin_path"`
|
||||
State int `json:"state"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Version string `json:"version"`
|
||||
}
|
||||
|
||||
type PluginStatuses []*PluginStatus
|
||||
|
||||
func (m *PluginStatuses) ToJson() string {
|
||||
b, _ := json.Marshal(m)
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func PluginStatusesFromJson(data io.Reader) PluginStatuses {
|
||||
var m PluginStatuses
|
||||
json.NewDecoder(data).Decode(&m)
|
||||
return m
|
||||
}
|
39
vendor/github.com/mattermost/mattermost-server/v5/model/plugin_valid.go
generated
vendored
39
vendor/github.com/mattermost/mattermost-server/v5/model/plugin_valid.go
generated
vendored
@ -1,39 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
const (
|
||||
MinIdLength = 3
|
||||
MaxIdLength = 190
|
||||
ValidIdRegex = `^[a-zA-Z0-9-_\.]+$`
|
||||
)
|
||||
|
||||
// ValidId constrains the set of valid plugin identifiers:
|
||||
// ^[a-zA-Z0-9-_\.]+
|
||||
var validId *regexp.Regexp
|
||||
|
||||
func init() {
|
||||
validId = regexp.MustCompile(ValidIdRegex)
|
||||
}
|
||||
|
||||
// IsValidPluginId verifies that the plugin id has a minimum length of 3, maximum length of 190, and
|
||||
// contains only alphanumeric characters, dashes, underscores and periods.
|
||||
//
|
||||
// These constraints are necessary since the plugin id is used as part of a filesystem path.
|
||||
func IsValidPluginId(id string) bool {
|
||||
if utf8.RuneCountInString(id) < MinIdLength {
|
||||
return false
|
||||
}
|
||||
|
||||
if utf8.RuneCountInString(id) > MaxIdLength {
|
||||
return false
|
||||
}
|
||||
|
||||
return validId.MatchString(id)
|
||||
}
|
29
vendor/github.com/mattermost/mattermost-server/v5/model/plugins_response.go
generated
vendored
29
vendor/github.com/mattermost/mattermost-server/v5/model/plugins_response.go
generated
vendored
@ -1,29 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
)
|
||||
|
||||
type PluginInfo struct {
|
||||
Manifest
|
||||
}
|
||||
|
||||
type PluginsResponse struct {
|
||||
Active []*PluginInfo `json:"active"`
|
||||
Inactive []*PluginInfo `json:"inactive"`
|
||||
}
|
||||
|
||||
func (m *PluginsResponse) ToJson() string {
|
||||
b, _ := json.Marshal(m)
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func PluginsResponseFromJson(data io.Reader) *PluginsResponse {
|
||||
var m *PluginsResponse
|
||||
json.NewDecoder(data).Decode(&m)
|
||||
return m
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user