PLT-2057 User as a first class object (#2648)

* Adding TeamMember to system

* Fixing all unit tests on the backend

* Fixing merge conflicts

* Fixing merge conflict

* Adding javascript unit tests

* Adding TeamMember to system

* Fixing all unit tests on the backend

* Fixing merge conflicts

* Fixing merge conflict

* Adding javascript unit tests

* Adding client side unit test

* Cleaning up the clint side tests

* Fixing msg

* Adding more client side unit tests

* Adding more using tests

* Adding last bit of client side unit tests and adding make cmd

* Fixing bad merge

* Fixing libraries

* Updating to new client side API

* Fixing borken unit test

* Fixing unit tests

* ugg...trying to beat gofmt

* ugg...trying to beat gofmt

* Cleaning up remainder of the server side routes

* Adding inital load api

* Increased coverage of webhook unit tests (#2660)

* Adding loading ... to root html

* Fixing bad merge

* Removing explicit content type so superagent will guess corectly (#2685)

* Fixing merge and unit tests

* Adding create team UI

* Fixing signup flows

* Adding LDAP unit tests and enterprise unit test helper (#2702)

* Add the ability to reset MFA from the commandline (#2706)

* Fixing compliance unit tests

* Fixing client side tests

* Adding open server to system console

* Moving websocket connection

* Fixing unit test

* Fixing unit tests

* Fixing unit tests

* Adding nickname and more LDAP unit tests (#2717)

* Adding join open teams

* Cleaning up all TODOs in the code

* Fixing web sockets

* Removing unused webockets file

* PLT-2533 Add the ability to reset a user's MFA from the system console (#2715)

* Add the ability to reset a user's MFA from the system console

* Add client side unit test for adminResetMfa

* Reorganizing authentication to fix LDAP error message (#2723)

* Fixing failing unit test

* Initial upgrade db code

* Adding upgrade script

* Fixing upgrade script after running on core

* Update OAuth and Claim routes to work with user model changes (#2739)

* Fixing perminant deletion. Adding ability to delete all user and the entire database (#2740)

* Fixing team invite ldap login call (#2741)

* Fixing bluebar and some img stuff

* Fix all the different file upload web utils (#2743)

* Fixing invalid session redirect (#2744)

* Redirect on bad channel name (#2746)

* Fixing a bunch of issue and removing dead code

* Patch to fix error message on leave channel (#2747)

* Setting EnableOpenServer to false by default

* Fixing config

* Fixing upgrade

* Fixing reported bugs

* Bug fixes for PLT-2057

* PLT-2563 Redo password recovery to use a database table (#2745)

* Redo password recovery to use a database table

* Update reset password audits

* Split out admin and user reset password APIs to be separate

* Delete password recovery when user is permanently deleted

* Consolidate password resetting into a single function

* Removed private channels as an option for outgoing webhooks (#2752)

* PLT-2577/PLT-2552 Fixes for backstage (#2753)

* Added URL to incoming webhook list

* Fixed client functions for adding/removing integrations

* Disallowed slash commands without trigger words

* Fixed clientside handling of errors on AddCommand page

* Minor auth cleanup (#2758)

* Changed EditPostModal to just close if you save without making any changes (#2759)

* Renamed client -> Client in async_client.jsx and fixed eslint warnings (#2756)

* Fixed url in channel info modal (#2755)

* Fixing reported issues

* Moving to version 3 of the apis

* Fixing command unit tests (#2760)

* Adding team admins

* Fixing DM issue

* Fixing eslint error

* Properly set EditPostModal's originalText state in all cases (#2762)

* Update client config check to assume features is defined if server is licensed (#2772)

* Fixing url link

* Fixing issue with websocket crashing when sending messages to different teams
Этот коммит содержится в:
Corey Hulen
2016-04-21 22:37:01 -07:00
родитель 5c755463ed
Коммит 2e5617c29b
268 изменённых файлов: 13214 добавлений и 9686 удалений

2
.gitignore поставляемый
Просмотреть файл

@@ -47,6 +47,8 @@ _testmain.go
*mattermost.log *mattermost.log
*npm-debug.log* *npm-debug.log*
.tmp
# Vim temporary files # Vim temporary files
[._]*.s[a-w][a-z] [._]*.s[a-w][a-z]
[._]s[a-w][a-z] [._]s[a-w][a-z]

5
Godeps/Godeps.json сгенерированный
Просмотреть файл

@@ -9,6 +9,11 @@
"ImportPath": "github.com/NYTimes/gziphandler", "ImportPath": "github.com/NYTimes/gziphandler",
"Rev": "a88790d49798560db24af70fb6a10a66e2549a72" "Rev": "a88790d49798560db24af70fb6a10a66e2549a72"
}, },
{
"ImportPath": "github.com/gorilla/handlers",
"Comment": "v1.1-4-gd0f2612",
"Rev": "d0f261246491e3a8613039e90764460448dc05f5"
},
{ {
"ImportPath": "github.com/alecthomas/log4go", "ImportPath": "github.com/alecthomas/log4go",
"Rev": "8e9057c3b25c409a34c0b9737cdc82cbcafeabce" "Rev": "8e9057c3b25c409a34c0b9737cdc82cbcafeabce"

17
Godeps/_workspace/src/github.com/gorilla/handlers/.travis.yml сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,17 @@
language: go
sudo: false
matrix:
include:
- go: 1.4
- go: 1.5
- go: 1.6
install:
- go get golang.org/x/tools/cmd/vet
script:
- go get -t -v ./...
- diff -u <(echo -n) <(gofmt -d .)
- go tool vet .
- go test -v -race ./...

22
Godeps/_workspace/src/github.com/gorilla/handlers/LICENSE сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,22 @@
Copyright (c) 2013 The Gorilla Handlers Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

53
Godeps/_workspace/src/github.com/gorilla/handlers/README.md сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,53 @@
gorilla/handlers
================
[![GoDoc](https://godoc.org/github.com/gorilla/handlers?status.svg)](https://godoc.org/github.com/gorilla/handlers) [![Build Status](https://travis-ci.org/gorilla/handlers.svg?branch=master)](https://travis-ci.org/gorilla/handlers)
Package handlers is a collection of handlers (aka "HTTP middleware") for use
with Go's `net/http` package (or any framework supporting `http.Handler`), including:
* [**LoggingHandler**](https://godoc.org/github.com/gorilla/handlers#LoggingHandler) for logging HTTP requests in the Apache [Common Log
Format](http://httpd.apache.org/docs/2.2/logs.html#common).
* [**CombinedLoggingHandler**](https://godoc.org/github.com/gorilla/handlers#CombinedLoggingHandler) for logging HTTP requests in the Apache [Combined Log
Format](http://httpd.apache.org/docs/2.2/logs.html#combined) commonly used by
both Apache and nginx.
* [**CompressHandler**](https://godoc.org/github.com/gorilla/handlers#CompressHandler) for gzipping responses.
* [**ContentTypeHandler**](https://godoc.org/github.com/gorilla/handlers#ContentTypeHandler) for validating requests against a list of accepted
content types.
* [**MethodHandler**](https://godoc.org/github.com/gorilla/handlers#MethodHandler) for matching HTTP methods against handlers in a
`map[string]http.Handler`
* [**ProxyHeaders**](https://godoc.org/github.com/gorilla/handlers#ProxyHeaders) for populating `r.RemoteAddr` and `r.URL.Scheme` based on the
`X-Forwarded-For`, `X-Real-IP`, `X-Forwarded-Proto` and RFC7239 `Forwarded`
headers when running a Go server behind a HTTP reverse proxy.
* [**CanonicalHost**](https://godoc.org/github.com/gorilla/handlers#CanonicalHost) for re-directing to the preferred host when handling multiple
domains (i.e. multiple CNAME aliases).
* [**RecoveryHandler**](https://godoc.org/github.com/gorilla/handlers#RecoveryHandler) for recovering from unexpected panics.
Other handlers are documented [on the Gorilla
website](http://www.gorillatoolkit.org/pkg/handlers).
## Example
A simple example using `handlers.LoggingHandler` and `handlers.CompressHandler`:
```go
import (
"net/http"
"github.com/gorilla/handlers"
)
func main() {
r := http.NewServeMux()
// Only log requests to our admin dashboard to stdout
r.Handle("/admin", handlers.LoggingHandler(os.Stdout, http.HandlerFunc(ShowAdminDashboard)))
r.HandleFunc("/", ShowIndex)
// Wrap our server with our gzip handler to gzip compress all responses.
http.ListenAndServe(":8000", handlers.CompressHandler(r))
}
```
## License
BSD licensed. See the included LICENSE file for details.

74
Godeps/_workspace/src/github.com/gorilla/handlers/canonical.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,74 @@
package handlers
import (
"net/http"
"net/url"
"strings"
)
type canonical struct {
h http.Handler
domain string
code int
}
// CanonicalHost is HTTP middleware that re-directs requests to the canonical
// domain. It accepts a domain and a status code (e.g. 301 or 302) and
// re-directs clients to this domain. The existing request path is maintained.
//
// Note: If the provided domain is considered invalid by url.Parse or otherwise
// returns an empty scheme or host, clients are not re-directed.
//
// Example:
//
// r := mux.NewRouter()
// canonical := handlers.CanonicalHost("http://www.gorillatoolkit.org", 302)
// r.HandleFunc("/route", YourHandler)
//
// log.Fatal(http.ListenAndServe(":7000", canonical(r)))
//
func CanonicalHost(domain string, code int) func(h http.Handler) http.Handler {
fn := func(h http.Handler) http.Handler {
return canonical{h, domain, code}
}
return fn
}
func (c canonical) ServeHTTP(w http.ResponseWriter, r *http.Request) {
dest, err := url.Parse(c.domain)
if err != nil {
// Call the next handler if the provided domain fails to parse.
c.h.ServeHTTP(w, r)
return
}
if dest.Scheme == "" || dest.Host == "" {
// Call the next handler if the scheme or host are empty.
// Note that url.Parse won't fail on in this case.
c.h.ServeHTTP(w, r)
return
}
if !strings.EqualFold(cleanHost(r.Host), dest.Host) {
// Re-build the destination URL
dest := dest.Scheme + "://" + dest.Host + r.URL.Path
if r.URL.RawQuery != "" {
dest += "?" + r.URL.RawQuery
}
http.Redirect(w, r, dest, c.code)
return
}
c.h.ServeHTTP(w, r)
}
// cleanHost cleans invalid Host headers by stripping anything after '/' or ' '.
// This is backported from Go 1.5 (in response to issue #11206) and attempts to
// mitigate malformed Host headers that do not match the format in RFC7230.
func cleanHost(in string) string {
if i := strings.IndexAny(in, " /"); i != -1 {
return in[:i]
}
return in
}

145
Godeps/_workspace/src/github.com/gorilla/handlers/compress.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,145 @@
// Copyright 2013 The Gorilla Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package handlers
import (
"compress/flate"
"compress/gzip"
"io"
"net/http"
"strings"
)
type compressResponseWriter struct {
io.Writer
http.ResponseWriter
http.Hijacker
http.Flusher
http.CloseNotifier
}
func (w *compressResponseWriter) WriteHeader(c int) {
w.ResponseWriter.Header().Del("Content-Length")
w.ResponseWriter.WriteHeader(c)
}
func (w *compressResponseWriter) Header() http.Header {
return w.ResponseWriter.Header()
}
func (w *compressResponseWriter) Write(b []byte) (int, error) {
h := w.ResponseWriter.Header()
if h.Get("Content-Type") == "" {
h.Set("Content-Type", http.DetectContentType(b))
}
h.Del("Content-Length")
return w.Writer.Write(b)
}
type flusher interface {
Flush() error
}
func (w *compressResponseWriter) Flush() {
// Flush compressed data if compressor supports it.
if f, ok := w.Writer.(flusher); ok {
f.Flush()
}
// Flush HTTP response.
if w.Flusher != nil {
w.Flusher.Flush()
}
}
// CompressHandler gzip compresses HTTP responses for clients that support it
// via the 'Accept-Encoding' header.
func CompressHandler(h http.Handler) http.Handler {
return CompressHandlerLevel(h, gzip.DefaultCompression)
}
// CompressHandlerLevel gzip compresses HTTP responses with specified compression level
// for clients that support it via the 'Accept-Encoding' header.
//
// The compression level should be gzip.DefaultCompression, gzip.NoCompression,
// or any integer value between gzip.BestSpeed and gzip.BestCompression inclusive.
// gzip.DefaultCompression is used in case of invalid compression level.
func CompressHandlerLevel(h http.Handler, level int) http.Handler {
if level < gzip.DefaultCompression || level > gzip.BestCompression {
level = gzip.DefaultCompression
}
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
L:
for _, enc := range strings.Split(r.Header.Get("Accept-Encoding"), ",") {
switch strings.TrimSpace(enc) {
case "gzip":
w.Header().Set("Content-Encoding", "gzip")
w.Header().Add("Vary", "Accept-Encoding")
gw, _ := gzip.NewWriterLevel(w, level)
defer gw.Close()
h, hok := w.(http.Hijacker)
if !hok { /* w is not Hijacker... oh well... */
h = nil
}
f, fok := w.(http.Flusher)
if !fok {
f = nil
}
cn, cnok := w.(http.CloseNotifier)
if !cnok {
cn = nil
}
w = &compressResponseWriter{
Writer: gw,
ResponseWriter: w,
Hijacker: h,
Flusher: f,
CloseNotifier: cn,
}
break L
case "deflate":
w.Header().Set("Content-Encoding", "deflate")
w.Header().Add("Vary", "Accept-Encoding")
fw, _ := flate.NewWriter(w, level)
defer fw.Close()
h, hok := w.(http.Hijacker)
if !hok { /* w is not Hijacker... oh well... */
h = nil
}
f, fok := w.(http.Flusher)
if !fok {
f = nil
}
cn, cnok := w.(http.CloseNotifier)
if !cnok {
cn = nil
}
w = &compressResponseWriter{
Writer: fw,
ResponseWriter: w,
Hijacker: h,
Flusher: f,
CloseNotifier: cn,
}
break L
}
}
h.ServeHTTP(w, r)
})
}

317
Godeps/_workspace/src/github.com/gorilla/handlers/cors.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,317 @@
package handlers
import (
"net/http"
"strconv"
"strings"
)
// CORSOption represents a functional option for configuring the CORS middleware.
type CORSOption func(*cors) error
type cors struct {
h http.Handler
allowedHeaders []string
allowedMethods []string
allowedOrigins []string
allowedOriginValidator OriginValidator
exposedHeaders []string
maxAge int
ignoreOptions bool
allowCredentials bool
}
// OriginValidator takes an origin string and returns whether or not that origin is allowed.
type OriginValidator func(string) bool
var (
defaultCorsMethods = []string{"GET", "HEAD", "POST"}
defaultCorsHeaders = []string{"Accept", "Accept-Language", "Content-Language", "Origin"}
// (WebKit/Safari v9 sends the Origin header by default in AJAX requests)
)
const (
corsOptionMethod string = "OPTIONS"
corsAllowOriginHeader string = "Access-Control-Allow-Origin"
corsExposeHeadersHeader string = "Access-Control-Expose-Headers"
corsMaxAgeHeader string = "Access-Control-Max-Age"
corsAllowMethodsHeader string = "Access-Control-Allow-Methods"
corsAllowHeadersHeader string = "Access-Control-Allow-Headers"
corsAllowCredentialsHeader string = "Access-Control-Allow-Credentials"
corsRequestMethodHeader string = "Access-Control-Request-Method"
corsRequestHeadersHeader string = "Access-Control-Request-Headers"
corsOriginHeader string = "Origin"
corsVaryHeader string = "Vary"
corsOriginMatchAll string = "*"
)
func (ch *cors) ServeHTTP(w http.ResponseWriter, r *http.Request) {
origin := r.Header.Get(corsOriginHeader)
if !ch.isOriginAllowed(origin) {
ch.h.ServeHTTP(w, r)
return
}
if r.Method == corsOptionMethod {
if ch.ignoreOptions {
ch.h.ServeHTTP(w, r)
return
}
if _, ok := r.Header[corsRequestMethodHeader]; !ok {
w.WriteHeader(http.StatusBadRequest)
return
}
method := r.Header.Get(corsRequestMethodHeader)
if !ch.isMatch(method, ch.allowedMethods) {
w.WriteHeader(http.StatusMethodNotAllowed)
return
}
requestHeaders := strings.Split(r.Header.Get(corsRequestHeadersHeader), ",")
allowedHeaders := []string{}
for _, v := range requestHeaders {
canonicalHeader := http.CanonicalHeaderKey(strings.TrimSpace(v))
if canonicalHeader == "" || ch.isMatch(canonicalHeader, defaultCorsHeaders) {
continue
}
if !ch.isMatch(canonicalHeader, ch.allowedHeaders) {
w.WriteHeader(http.StatusForbidden)
return
}
allowedHeaders = append(allowedHeaders, canonicalHeader)
}
if len(allowedHeaders) > 0 {
w.Header().Set(corsAllowHeadersHeader, strings.Join(allowedHeaders, ","))
}
if ch.maxAge > 0 {
w.Header().Set(corsMaxAgeHeader, strconv.Itoa(ch.maxAge))
}
if !ch.isMatch(method, defaultCorsMethods) {
w.Header().Set(corsAllowMethodsHeader, method)
}
} else {
if len(ch.exposedHeaders) > 0 {
w.Header().Set(corsExposeHeadersHeader, strings.Join(ch.exposedHeaders, ","))
}
}
if ch.allowCredentials {
w.Header().Set(corsAllowCredentialsHeader, "true")
}
if len(ch.allowedOrigins) > 1 {
w.Header().Set(corsVaryHeader, corsOriginHeader)
}
w.Header().Set(corsAllowOriginHeader, origin)
if r.Method == corsOptionMethod {
return
}
ch.h.ServeHTTP(w, r)
}
// CORS provides Cross-Origin Resource Sharing middleware.
// Example:
//
// import (
// "net/http"
//
// "github.com/gorilla/handlers"
// "github.com/gorilla/mux"
// )
//
// func main() {
// r := mux.NewRouter()
// r.HandleFunc("/users", UserEndpoint)
// r.HandleFunc("/projects", ProjectEndpoint)
//
// // Apply the CORS middleware to our top-level router, with the defaults.
// http.ListenAndServe(":8000", handlers.CORS()(r))
// }
//
func CORS(opts ...CORSOption) func(http.Handler) http.Handler {
return func(h http.Handler) http.Handler {
ch := parseCORSOptions(opts...)
ch.h = h
return ch
}
}
func parseCORSOptions(opts ...CORSOption) *cors {
ch := &cors{
allowedMethods: defaultCorsMethods,
allowedHeaders: defaultCorsHeaders,
allowedOrigins: []string{corsOriginMatchAll},
}
for _, option := range opts {
option(ch)
}
return ch
}
//
// Functional options for configuring CORS.
//
// AllowedHeaders adds the provided headers to the list of allowed headers in a
// CORS request.
// This is an append operation so the headers Accept, Accept-Language,
// and Content-Language are always allowed.
// Content-Type must be explicitly declared if accepting Content-Types other than
// application/x-www-form-urlencoded, multipart/form-data, or text/plain.
func AllowedHeaders(headers []string) CORSOption {
return func(ch *cors) error {
for _, v := range headers {
normalizedHeader := http.CanonicalHeaderKey(strings.TrimSpace(v))
if normalizedHeader == "" {
continue
}
if !ch.isMatch(normalizedHeader, ch.allowedHeaders) {
ch.allowedHeaders = append(ch.allowedHeaders, normalizedHeader)
}
}
return nil
}
}
// AllowedMethods can be used to explicitly allow methods in the
// Access-Control-Allow-Methods header.
// This is a replacement operation so you must also
// pass GET, HEAD, and POST if you wish to support those methods.
func AllowedMethods(methods []string) CORSOption {
return func(ch *cors) error {
ch.allowedMethods = []string{}
for _, v := range methods {
normalizedMethod := strings.ToUpper(strings.TrimSpace(v))
if normalizedMethod == "" {
continue
}
if !ch.isMatch(normalizedMethod, ch.allowedMethods) {
ch.allowedMethods = append(ch.allowedMethods, normalizedMethod)
}
}
return nil
}
}
// AllowedOrigins sets the allowed origins for CORS requests, as used in the
// 'Allow-Access-Control-Origin' HTTP header.
// Note: Passing in a []string{"*"} will allow any domain.
func AllowedOrigins(origins []string) CORSOption {
return func(ch *cors) error {
for _, v := range origins {
if v == corsOriginMatchAll {
ch.allowedOrigins = []string{corsOriginMatchAll}
return nil
}
}
ch.allowedOrigins = origins
return nil
}
}
// AllowedOriginValidator sets a function for evaluating allowed origins in CORS requests, represented by the
// 'Allow-Access-Control-Origin' HTTP header.
func AllowedOriginValidator(fn OriginValidator) CORSOption {
return func(ch *cors) error {
ch.allowedOriginValidator = fn
return nil
}
}
// ExposeHeaders can be used to specify headers that are available
// and will not be stripped out by the user-agent.
func ExposedHeaders(headers []string) CORSOption {
return func(ch *cors) error {
ch.exposedHeaders = []string{}
for _, v := range headers {
normalizedHeader := http.CanonicalHeaderKey(strings.TrimSpace(v))
if normalizedHeader == "" {
continue
}
if !ch.isMatch(normalizedHeader, ch.exposedHeaders) {
ch.exposedHeaders = append(ch.exposedHeaders, normalizedHeader)
}
}
return nil
}
}
// MaxAge determines the maximum age (in seconds) between preflight requests. A
// maximum of 10 minutes is allowed. An age above this value will default to 10
// minutes.
func MaxAge(age int) CORSOption {
return func(ch *cors) error {
// Maximum of 10 minutes.
if age > 600 {
age = 600
}
ch.maxAge = age
return nil
}
}
// IgnoreOptions causes the CORS middleware to ignore OPTIONS requests, instead
// passing them through to the next handler. This is useful when your application
// or framework has a pre-existing mechanism for responding to OPTIONS requests.
func IgnoreOptions() CORSOption {
return func(ch *cors) error {
ch.ignoreOptions = true
return nil
}
}
// AllowCredentials can be used to specify that the user agent may pass
// authentication details along with the request.
func AllowCredentials() CORSOption {
return func(ch *cors) error {
ch.allowCredentials = true
return nil
}
}
func (ch *cors) isOriginAllowed(origin string) bool {
if origin == "" {
return false
}
if ch.allowedOriginValidator != nil {
return ch.allowedOriginValidator(origin)
}
for _, allowedOrigin := range ch.allowedOrigins {
if allowedOrigin == origin || allowedOrigin == corsOriginMatchAll {
return true
}
}
return false
}
func (ch *cors) isMatch(needle string, haystack []string) bool {
for _, v := range haystack {
if v == needle {
return true
}
}
return false
}

9
Godeps/_workspace/src/github.com/gorilla/handlers/doc.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,9 @@
/*
Package handlers is a collection of handlers (aka "HTTP middleware") for use
with Go's net/http package (or any framework supporting http.Handler).
The package includes handlers for logging in standardised formats, compressing
HTTP responses, validating content types and other useful tools for manipulating
requests and responses.
*/
package handlers

403
Godeps/_workspace/src/github.com/gorilla/handlers/handlers.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,403 @@
// Copyright 2013 The Gorilla Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package handlers
import (
"bufio"
"fmt"
"io"
"net"
"net/http"
"net/url"
"sort"
"strconv"
"strings"
"time"
"unicode/utf8"
)
// MethodHandler is an http.Handler that dispatches to a handler whose key in the
// MethodHandler's map matches the name of the HTTP request's method, eg: GET
//
// If the request's method is OPTIONS and OPTIONS is not a key in the map then
// the handler responds with a status of 200 and sets the Allow header to a
// comma-separated list of available methods.
//
// If the request's method doesn't match any of its keys the handler responds
// with a status of HTTP 405 "Method Not Allowed" and sets the Allow header to a
// comma-separated list of available methods.
type MethodHandler map[string]http.Handler
func (h MethodHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
if handler, ok := h[req.Method]; ok {
handler.ServeHTTP(w, req)
} else {
allow := []string{}
for k := range h {
allow = append(allow, k)
}
sort.Strings(allow)
w.Header().Set("Allow", strings.Join(allow, ", "))
if req.Method == "OPTIONS" {
w.WriteHeader(http.StatusOK)
} else {
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
}
}
}
// loggingHandler is the http.Handler implementation for LoggingHandlerTo and its
// friends
type loggingHandler struct {
writer io.Writer
handler http.Handler
}
// combinedLoggingHandler is the http.Handler implementation for LoggingHandlerTo
// and its friends
type combinedLoggingHandler struct {
writer io.Writer
handler http.Handler
}
func (h loggingHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
t := time.Now()
logger := makeLogger(w)
url := *req.URL
h.handler.ServeHTTP(logger, req)
writeLog(h.writer, req, url, t, logger.Status(), logger.Size())
}
func (h combinedLoggingHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
t := time.Now()
logger := makeLogger(w)
url := *req.URL
h.handler.ServeHTTP(logger, req)
writeCombinedLog(h.writer, req, url, t, logger.Status(), logger.Size())
}
func makeLogger(w http.ResponseWriter) loggingResponseWriter {
var logger loggingResponseWriter = &responseLogger{w: w}
if _, ok := w.(http.Hijacker); ok {
logger = &hijackLogger{responseLogger{w: w}}
}
h, ok1 := logger.(http.Hijacker)
c, ok2 := w.(http.CloseNotifier)
if ok1 && ok2 {
return hijackCloseNotifier{logger, h, c}
}
if ok2 {
return &closeNotifyWriter{logger, c}
}
return logger
}
type loggingResponseWriter interface {
http.ResponseWriter
http.Flusher
Status() int
Size() int
}
// responseLogger is wrapper of http.ResponseWriter that keeps track of its HTTP
// status code and body size
type responseLogger struct {
w http.ResponseWriter
status int
size int
}
func (l *responseLogger) Header() http.Header {
return l.w.Header()
}
func (l *responseLogger) Write(b []byte) (int, error) {
if l.status == 0 {
// The status will be StatusOK if WriteHeader has not been called yet
l.status = http.StatusOK
}
size, err := l.w.Write(b)
l.size += size
return size, err
}
func (l *responseLogger) WriteHeader(s int) {
l.w.WriteHeader(s)
l.status = s
}
func (l *responseLogger) Status() int {
return l.status
}
func (l *responseLogger) Size() int {
return l.size
}
func (l *responseLogger) Flush() {
f, ok := l.w.(http.Flusher)
if ok {
f.Flush()
}
}
type hijackLogger struct {
responseLogger
}
func (l *hijackLogger) Hijack() (net.Conn, *bufio.ReadWriter, error) {
h := l.responseLogger.w.(http.Hijacker)
conn, rw, err := h.Hijack()
if err == nil && l.responseLogger.status == 0 {
// The status will be StatusSwitchingProtocols if there was no error and
// WriteHeader has not been called yet
l.responseLogger.status = http.StatusSwitchingProtocols
}
return conn, rw, err
}
type closeNotifyWriter struct {
loggingResponseWriter
http.CloseNotifier
}
type hijackCloseNotifier struct {
loggingResponseWriter
http.Hijacker
http.CloseNotifier
}
const lowerhex = "0123456789abcdef"
func appendQuoted(buf []byte, s string) []byte {
var runeTmp [utf8.UTFMax]byte
for width := 0; len(s) > 0; s = s[width:] {
r := rune(s[0])
width = 1
if r >= utf8.RuneSelf {
r, width = utf8.DecodeRuneInString(s)
}
if width == 1 && r == utf8.RuneError {
buf = append(buf, `\x`...)
buf = append(buf, lowerhex[s[0]>>4])
buf = append(buf, lowerhex[s[0]&0xF])
continue
}
if r == rune('"') || r == '\\' { // always backslashed
buf = append(buf, '\\')
buf = append(buf, byte(r))
continue
}
if strconv.IsPrint(r) {
n := utf8.EncodeRune(runeTmp[:], r)
buf = append(buf, runeTmp[:n]...)
continue
}
switch r {
case '\a':
buf = append(buf, `\a`...)
case '\b':
buf = append(buf, `\b`...)
case '\f':
buf = append(buf, `\f`...)
case '\n':
buf = append(buf, `\n`...)
case '\r':
buf = append(buf, `\r`...)
case '\t':
buf = append(buf, `\t`...)
case '\v':
buf = append(buf, `\v`...)
default:
switch {
case r < ' ':
buf = append(buf, `\x`...)
buf = append(buf, lowerhex[s[0]>>4])
buf = append(buf, lowerhex[s[0]&0xF])
case r > utf8.MaxRune:
r = 0xFFFD
fallthrough
case r < 0x10000:
buf = append(buf, `\u`...)
for s := 12; s >= 0; s -= 4 {
buf = append(buf, lowerhex[r>>uint(s)&0xF])
}
default:
buf = append(buf, `\U`...)
for s := 28; s >= 0; s -= 4 {
buf = append(buf, lowerhex[r>>uint(s)&0xF])
}
}
}
}
return buf
}
// buildCommonLogLine builds a log entry for req in Apache Common Log Format.
// ts is the timestamp with which the entry should be logged.
// status and size are used to provide the response HTTP status and size.
func buildCommonLogLine(req *http.Request, url url.URL, ts time.Time, status int, size int) []byte {
username := "-"
if url.User != nil {
if name := url.User.Username(); name != "" {
username = name
}
}
host, _, err := net.SplitHostPort(req.RemoteAddr)
if err != nil {
host = req.RemoteAddr
}
uri := req.RequestURI
// Requests using the CONNECT method over HTTP/2.0 must use
// the authority field (aka r.Host) to identify the target.
// Refer: https://httpwg.github.io/specs/rfc7540.html#CONNECT
if req.ProtoMajor == 2 && req.Method == "CONNECT" {
uri = req.Host
}
if uri == "" {
uri = url.RequestURI()
}
buf := make([]byte, 0, 3*(len(host)+len(username)+len(req.Method)+len(uri)+len(req.Proto)+50)/2)
buf = append(buf, host...)
buf = append(buf, " - "...)
buf = append(buf, username...)
buf = append(buf, " ["...)
buf = append(buf, ts.Format("02/Jan/2006:15:04:05 -0700")...)
buf = append(buf, `] "`...)
buf = append(buf, req.Method...)
buf = append(buf, " "...)
buf = appendQuoted(buf, uri)
buf = append(buf, " "...)
buf = append(buf, req.Proto...)
buf = append(buf, `" `...)
buf = append(buf, strconv.Itoa(status)...)
buf = append(buf, " "...)
buf = append(buf, strconv.Itoa(size)...)
return buf
}
// writeLog writes a log entry for req to w in Apache Common Log Format.
// ts is the timestamp with which the entry should be logged.
// status and size are used to provide the response HTTP status and size.
func writeLog(w io.Writer, req *http.Request, url url.URL, ts time.Time, status, size int) {
buf := buildCommonLogLine(req, url, ts, status, size)
buf = append(buf, '\n')
w.Write(buf)
}
// writeCombinedLog writes a log entry for req to w in Apache Combined Log Format.
// ts is the timestamp with which the entry should be logged.
// status and size are used to provide the response HTTP status and size.
func writeCombinedLog(w io.Writer, req *http.Request, url url.URL, ts time.Time, status, size int) {
buf := buildCommonLogLine(req, url, ts, status, size)
buf = append(buf, ` "`...)
buf = appendQuoted(buf, req.Referer())
buf = append(buf, `" "`...)
buf = appendQuoted(buf, req.UserAgent())
buf = append(buf, '"', '\n')
w.Write(buf)
}
// CombinedLoggingHandler return a http.Handler that wraps h and logs requests to out in
// Apache Combined Log Format.
//
// See http://httpd.apache.org/docs/2.2/logs.html#combined for a description of this format.
//
// LoggingHandler always sets the ident field of the log to -
func CombinedLoggingHandler(out io.Writer, h http.Handler) http.Handler {
return combinedLoggingHandler{out, h}
}
// LoggingHandler return a http.Handler that wraps h and logs requests to out in
// Apache Common Log Format (CLF).
//
// See http://httpd.apache.org/docs/2.2/logs.html#common for a description of this format.
//
// LoggingHandler always sets the ident field of the log to -
//
// Example:
//
// r := mux.NewRouter()
// r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
// w.Write([]byte("This is a catch-all route"))
// })
// loggedRouter := handlers.LoggingHandler(os.Stdout, r)
// http.ListenAndServe(":1123", loggedRouter)
//
func LoggingHandler(out io.Writer, h http.Handler) http.Handler {
return loggingHandler{out, h}
}
// isContentType validates the Content-Type header matches the supplied
// contentType. That is, its type and subtype match.
func isContentType(h http.Header, contentType string) bool {
ct := h.Get("Content-Type")
if i := strings.IndexRune(ct, ';'); i != -1 {
ct = ct[0:i]
}
return ct == contentType
}
// ContentTypeHandler wraps and returns a http.Handler, validating the request
// content type is compatible with the contentTypes list. It writes a HTTP 415
// error if that fails.
//
// Only PUT, POST, and PATCH requests are considered.
func ContentTypeHandler(h http.Handler, contentTypes ...string) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if !(r.Method == "PUT" || r.Method == "POST" || r.Method == "PATCH") {
h.ServeHTTP(w, r)
return
}
for _, ct := range contentTypes {
if isContentType(r.Header, ct) {
h.ServeHTTP(w, r)
return
}
}
http.Error(w, fmt.Sprintf("Unsupported content type %q; expected one of %q", r.Header.Get("Content-Type"), contentTypes), http.StatusUnsupportedMediaType)
})
}
const (
// HTTPMethodOverrideHeader is a commonly used
// http header to override a request method.
HTTPMethodOverrideHeader = "X-HTTP-Method-Override"
// HTTPMethodOverrideFormKey is a commonly used
// HTML form key to override a request method.
HTTPMethodOverrideFormKey = "_method"
)
// HTTPMethodOverrideHandler wraps and returns a http.Handler which checks for
// the X-HTTP-Method-Override header or the _method form key, and overrides (if
// valid) request.Method with its value.
//
// This is especially useful for HTTP clients that don't support many http verbs.
// It isn't secure to override e.g a GET to a POST, so only POST requests are
// considered. Likewise, the override method can only be a "write" method: PUT,
// PATCH or DELETE.
//
// Form method takes precedence over header method.
func HTTPMethodOverrideHandler(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Method == "POST" {
om := r.FormValue(HTTPMethodOverrideFormKey)
if om == "" {
om = r.Header.Get(HTTPMethodOverrideHeader)
}
if om == "PUT" || om == "PATCH" || om == "DELETE" {
r.Method = om
}
}
h.ServeHTTP(w, r)
})
}

113
Godeps/_workspace/src/github.com/gorilla/handlers/proxy_headers.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,113 @@
package handlers
import (
"net/http"
"regexp"
"strings"
)
var (
// De-facto standard header keys.
xForwardedFor = http.CanonicalHeaderKey("X-Forwarded-For")
xRealIP = http.CanonicalHeaderKey("X-Real-IP")
xForwardedProto = http.CanonicalHeaderKey("X-Forwarded-Scheme")
)
var (
// RFC7239 defines a new "Forwarded: " header designed to replace the
// existing use of X-Forwarded-* headers.
// e.g. Forwarded: for=192.0.2.60;proto=https;by=203.0.113.43
forwarded = http.CanonicalHeaderKey("Forwarded")
// Allows for a sub-match of the first value after 'for=' to the next
// comma, semi-colon or space. The match is case-insensitive.
forRegex = regexp.MustCompile(`(?i)(?:for=)([^(;|,| )]+)`)
// Allows for a sub-match for the first instance of scheme (http|https)
// prefixed by 'proto='. The match is case-insensitive.
protoRegex = regexp.MustCompile(`(?i)(?:proto=)(https|http)`)
)
// ProxyHeaders inspects common reverse proxy headers and sets the corresponding
// fields in the HTTP request struct. These are X-Forwarded-For and X-Real-IP
// for the remote (client) IP address, X-Forwarded-Proto for the scheme
// (http|https) and the RFC7239 Forwarded header, which may include both client
// IPs and schemes.
//
// NOTE: This middleware should only be used when behind a reverse
// proxy like nginx, HAProxy or Apache. Reverse proxies that don't (or are
// configured not to) strip these headers from client requests, or where these
// headers are accepted "as is" from a remote client (e.g. when Go is not behind
// a proxy), can manifest as a vulnerability if your application uses these
// headers for validating the 'trustworthiness' of a request.
func ProxyHeaders(h http.Handler) http.Handler {
fn := func(w http.ResponseWriter, r *http.Request) {
// Set the remote IP with the value passed from the proxy.
if fwd := getIP(r); fwd != "" {
r.RemoteAddr = fwd
}
// Set the scheme (proto) with the value passed from the proxy.
if scheme := getScheme(r); scheme != "" {
r.URL.Scheme = scheme
}
// Call the next handler in the chain.
h.ServeHTTP(w, r)
}
return http.HandlerFunc(fn)
}
// getIP retrieves the IP from the X-Forwarded-For, X-Real-IP and RFC7239
// Forwarded headers (in that order).
func getIP(r *http.Request) string {
var addr string
if fwd := r.Header.Get(xForwardedFor); fwd != "" {
// Only grab the first (client) address. Note that '192.168.0.1,
// 10.1.1.1' is a valid key for X-Forwarded-For where addresses after
// the first may represent forwarding proxies earlier in the chain.
s := strings.Index(fwd, ", ")
if s == -1 {
s = len(fwd)
}
addr = fwd[:s]
} else if fwd := r.Header.Get(xRealIP); fwd != "" {
// X-Real-IP should only contain one IP address (the client making the
// request).
addr = fwd
} else if fwd := r.Header.Get(forwarded); fwd != "" {
// match should contain at least two elements if the protocol was
// specified in the Forwarded header. The first element will always be
// the 'for=' capture, which we ignore. In the case of multiple IP
// addresses (for=8.8.8.8, 8.8.4.4,172.16.1.20 is valid) we only
// extract the first, which should be the client IP.
if match := forRegex.FindStringSubmatch(fwd); len(match) > 1 {
// IPv6 addresses in Forwarded headers are quoted-strings. We strip
// these quotes.
addr = strings.Trim(match[1], `"`)
}
}
return addr
}
// getScheme retrieves the scheme from the X-Forwarded-Proto and RFC7239
// Forwarded headers (in that order).
func getScheme(r *http.Request) string {
var scheme string
// Retrieve the scheme from X-Forwarded-Proto.
if proto := r.Header.Get(xForwardedProto); proto != "" {
scheme = strings.ToLower(proto)
} else if proto := r.Header.Get(forwarded); proto != "" {
// match should contain at least two elements if the protocol was
// specified in the Forwarded header. The first element will always be
// the 'proto=' capture, which we ignore. In the case of multiple proto
// parameters (invalid) we only extract the first.
if match := protoRegex.FindStringSubmatch(proto); len(match) > 1 {
scheme = strings.ToLower(match[1])
}
}
return scheme
}

86
Godeps/_workspace/src/github.com/gorilla/handlers/recovery.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,86 @@
package handlers
import (
"log"
"net/http"
"runtime/debug"
)
type recoveryHandler struct {
handler http.Handler
logger *log.Logger
printStack bool
}
// RecoveryOption provides a functional approach to define
// configuration for a handler; such as setting the logging
// whether or not to print strack traces on panic.
type RecoveryOption func(http.Handler)
func parseRecoveryOptions(h http.Handler, opts ...RecoveryOption) http.Handler {
for _, option := range opts {
option(h)
}
return h
}
// RecoveryHandler is HTTP middleware that recovers from a panic,
// logs the panic, writes http.StatusInternalServerError, and
// continues to the next handler.
//
// Example:
//
// r := mux.NewRouter()
// r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
// panic("Unexpected error!")
// })
//
// http.ListenAndServe(":1123", handlers.RecoveryHandler()(r))
func RecoveryHandler(opts ...RecoveryOption) func(h http.Handler) http.Handler {
return func(h http.Handler) http.Handler {
r := &recoveryHandler{handler: h}
return parseRecoveryOptions(r, opts...)
}
}
// RecoveryLogger is a functional option to override
// the default logger
func RecoveryLogger(logger *log.Logger) RecoveryOption {
return func(h http.Handler) {
r := h.(*recoveryHandler)
r.logger = logger
}
}
// PrintRecoveryStack is a functional option to enable
// or disable printing stack traces on panic.
func PrintRecoveryStack(print bool) RecoveryOption {
return func(h http.Handler) {
r := h.(*recoveryHandler)
r.printStack = print
}
}
func (h recoveryHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
defer func() {
if err := recover(); err != nil {
w.WriteHeader(http.StatusInternalServerError)
h.log(err)
}
}()
h.handler.ServeHTTP(w, req)
}
func (h recoveryHandler) log(message interface{}) {
if h.logger != nil {
h.logger.Println(message)
} else {
log.Println(message)
}
if h.printStack {
debug.PrintStack()
}
}

Просмотреть файл

@@ -1,4 +1,4 @@
.PHONY: build package run stop run-client run-server stop-client stop-server restart-server restart-client start-docker clean-dist clean nuke check-style check-unit-tests test dist setup-mac prepare-enteprise build-linux build-osx build-windows .PHONY: build package run stop run-client run-server stop-client stop-server restart-server restart-client start-docker clean-dist clean nuke check-style check-unit-tests test dist setup-mac prepare-enteprise run-client-tests setup-run-client-tests cleanup-run-client-tests test-client build-linux build-osx build-windows
# Build Flags # Build Flags
BUILD_NUMBER ?= $(BUILD_NUMBER:) BUILD_NUMBER ?= $(BUILD_NUMBER:)
@@ -63,10 +63,30 @@ start-docker:
echo starting mattermost-postgres; \ echo starting mattermost-postgres; \
docker run --name mattermost-postgres -p 5432:5432 -e POSTGRES_USER=mmuser -e POSTGRES_PASSWORD=mostest \ docker run --name mattermost-postgres -p 5432:5432 -e POSTGRES_USER=mmuser -e POSTGRES_PASSWORD=mostest \
-d postgres:9.4 > /dev/null; \ -d postgres:9.4 > /dev/null; \
sleep 10; \
elif [ $(shell docker ps | grep -ci mattermost-postgres) -eq 0 ]; then \ elif [ $(shell docker ps | grep -ci mattermost-postgres) -eq 0 ]; then \
echo restarting mattermost-postgres; \ echo restarting mattermost-postgres; \
docker start mattermost-postgres > /dev/null; \ docker start mattermost-postgres > /dev/null; \
fi
@echo Ldap test user test.one
@if [ $(shell docker ps -a | grep -ci mattermost-openldap) -eq 0 ]; then \
echo starting mattermost-openldap; \
docker run --name mattermost-openldap -p 389:389 -p 636:636 \
-e LDAP_TLS_VERIFY_CLIENT="never" \
-e LDAP_ORGANISATION="Mattermost Test" \
-e LDAP_DOMAIN="mm.test.com" \
-e LDAP_ADMIN_PASSWORD="mostest" \
-d osixia/openldap:1.1.2 > /dev/null;\
sleep 10; \
docker exec -ti mattermost-openldap bash -c 'echo -e "dn: ou=testusers,dc=mm,dc=test,dc=com\nobjectclass: organizationalunit" | ldapadd -x -D "cn=admin,dc=mm,dc=test,dc=com" -w mostest';\
docker exec -ti mattermost-openldap bash -c 'echo -e "dn: uid=test.one,ou=testusers,dc=mm,dc=test,dc=com\nobjectclass: iNetOrgPerson\nsn: User\ncn: Test1\nmail: success+testone@simulator.amazonses.com" | ldapadd -x -D "cn=admin,dc=mm,dc=test,dc=com" -w mostest';\
docker exec -ti mattermost-openldap bash -c 'ldappasswd -s Password1 -D "cn=admin,dc=mm,dc=test,dc=com" -x "uid=test.one,ou=testusers,dc=mm,dc=test,dc=com" -w mostest';\
docker exec -ti mattermost-openldap bash -c 'echo -e "dn: uid=test.two,ou=testusers,dc=mm,dc=test,dc=com\nobjectclass: iNetOrgPerson\nsn: User\ncn: Test2\nmail: success+testtwo@simulator.amazonses.com" | ldapadd -x -D "cn=admin,dc=mm,dc=test,dc=com" -w mostest';\
docker exec -ti mattermost-openldap bash -c 'ldappasswd -s Password1 -D "cn=admin,dc=mm,dc=test,dc=com" -x "uid=test.two,ou=testusers,dc=mm,dc=test,dc=com" -w mostest';\
docker exec -ti mattermost-openldap bash -c 'echo -e "dn: cn=tgroup,ou=testusers,dc=mm,dc=test,dc=com\nobjectclass: groupOfUniqueNames\nuniqueMember: uid=test.one,ou=testusers,dc=mm,dc=test,dc=com" | ldapadd -x -D "cn=admin,dc=mm,dc=test,dc=com" -w mostest';\
elif [ $(shell docker ps | grep -ci mattermost-openldap) -eq 0 ]; then \
echo restarting mattermost-openldap; \
docker start mattermost-openldap > /dev/null; \
sleep 10; \ sleep 10; \
fi fi
@@ -82,22 +102,33 @@ stop-docker:
echo stopping mattermost-postgres; \ echo stopping mattermost-postgres; \
docker stop mattermost-postgres > /dev/null; \ docker stop mattermost-postgres > /dev/null; \
fi fi
@if [ $(shell docker ps -a | grep -ci mattermost-openldap) -eq 1 ]; then \
echo stopping mattermost-openldap; \
docker stop mattermost-openldap > /dev/null; \
fi
clean-docker: clean-docker:
@echo Removing docker containers @echo Removing docker containers
@if [ $(shell docker ps -a | grep -ci mattermost-mysql) -eq 1 ]; then \ @if [ $(shell docker ps -a | grep -ci mattermost-mysql) -eq 1 ]; then \
echo stopping mattermost-mysql; \ echo removing mattermost-mysql; \
docker stop mattermost-mysql > /dev/null; \ docker stop mattermost-mysql > /dev/null; \
docker rm -v mattermost-mysql > /dev/null; \ docker rm -v mattermost-mysql > /dev/null; \
fi fi
@if [ $(shell docker ps -a | grep -ci mattermost-postgres) -eq 1 ]; then \ @if [ $(shell docker ps -a | grep -ci mattermost-postgres) -eq 1 ]; then \
echo stopping mattermost-postgres; \ echo removing mattermost-postgres; \
docker stop mattermost-postgres > /dev/null; \ docker stop mattermost-postgres > /dev/null; \
docker rm -v mattermost-postgres > /dev/null; \ docker rm -v mattermost-postgres > /dev/null; \
fi fi
@if [ $(shell docker ps -a | grep -ci mattermost-openldap) -eq 1 ]; then \
echo removing mattermost-openldap; \
docker stop mattermost-openldap > /dev/null; \
docker rm -v mattermost-openldap > /dev/null; \
fi
check-style: check-style:
@echo Running GOFMT @echo Running GOFMT
$(eval GOFMT_OUTPUT := $(shell gofmt -d -s api/ model/ store/ utils/ manualtesting/ einterfaces/ mattermost.go 2>&1)) $(eval GOFMT_OUTPUT := $(shell gofmt -d -s api/ model/ store/ utils/ manualtesting/ einterfaces/ mattermost.go 2>&1))
@@ -110,11 +141,32 @@ check-style:
fi fi
test: start-docker test: start-docker
$(GO) test $(GOFLAGS) -run=$(TESTS) -test.v -test.timeout=180s ./api || exit 1 @echo Running tests
$(GO) test $(GOFLAGS) -run=$(TESTS) -test.v -test.timeout=240s ./api || exit 1
$(GO) test $(GOFLAGS) -run=$(TESTS) -test.v -test.timeout=12s ./model || exit 1 $(GO) test $(GOFLAGS) -run=$(TESTS) -test.v -test.timeout=12s ./model || exit 1
$(GO) test $(GOFLAGS) -run=$(TESTS) -test.v -test.timeout=120s ./store || exit 1 $(GO) test $(GOFLAGS) -run=$(TESTS) -test.v -test.timeout=120s ./store || exit 1
$(GO) test $(GOFLAGS) -run=$(TESTS) -test.v -test.timeout=120s ./utils || exit 1 $(GO) test $(GOFLAGS) -run=$(TESTS) -test.v -test.timeout=120s ./utils || exit 1
$(GO) test $(GOFLAGS) -run=$(TESTS) -test.v -test.timeout=120s ./web || exit 1 $(GO) test $(GOFLAGS) -run=$(TESTS) -test.v -test.timeout=120s ./web || exit 1
ifeq ($(BUILD_ENTERPRISE_READY),true)
@echo Running Enterprise tests
$(GO) test $(GOFLAGS) -run=$(TESTS) -test.v -test.timeout=120s $(BUILD_ENTERPRISE_DIR)/ldap || exit 1
$(GO) test $(GOFLAGS) -run=$(TESTS) -test.v -test.timeout=120s $(BUILD_ENTERPRISE_DIR)/compliance || exit 1
endif
setup-run-client-tests:
sed -i'.bak' 's|"EnableOpenServer": false,|"EnableOpenServer": true,|g' config/config.json
cleanup-run-client-tests:
sed -i'.bak' 's|"EnableOpenServer": true,|"EnableOpenServer": false,|g' config/config.json
run-client-tests:
cd $(BUILD_WEBAPP_DIR) && $(MAKE) test
sleep 10
@echo Running client side unit tests
cd $(BUILD_WEBAPP_DIR) && npm test
test-client: setup-run-client-tests run-server run-client-tests stop-server cleanup-run-client-tests
.prebuild: .prebuild:
@echo Preparation for running go code @echo Preparation for running go code
@@ -124,7 +176,7 @@ test: start-docker
prepare-enterprise: prepare-enterprise:
ifeq ($(BUILD_ENTERPRISE_READY),true) ifeq ($(BUILD_ENTERPRISE_READY),true)
@echo Enterprise build selected, perparing @echo Enterprise build selected, preparing
cp $(BUILD_ENTERPRISE_DIR)/imports.go . cp $(BUILD_ENTERPRISE_DIR)/imports.go .
endif endif

Просмотреть файл

@@ -19,24 +19,25 @@ import (
"github.com/mssola/user_agent" "github.com/mssola/user_agent"
) )
func InitAdmin(r *mux.Router) { func InitAdmin() {
l4g.Debug(utils.T("api.admin.init.debug")) l4g.Debug(utils.T("api.admin.init.debug"))
sr := r.PathPrefix("/admin").Subrouter() BaseRoutes.Admin.Handle("/logs", ApiUserRequired(getLogs)).Methods("GET")
sr.Handle("/logs", ApiUserRequired(getLogs)).Methods("GET") BaseRoutes.Admin.Handle("/audits", ApiUserRequired(getAllAudits)).Methods("GET")
sr.Handle("/audits", ApiUserRequired(getAllAudits)).Methods("GET") BaseRoutes.Admin.Handle("/config", ApiUserRequired(getConfig)).Methods("GET")
sr.Handle("/config", ApiUserRequired(getConfig)).Methods("GET") BaseRoutes.Admin.Handle("/save_config", ApiUserRequired(saveConfig)).Methods("POST")
sr.Handle("/save_config", ApiUserRequired(saveConfig)).Methods("POST") BaseRoutes.Admin.Handle("/test_email", ApiUserRequired(testEmail)).Methods("POST")
sr.Handle("/test_email", ApiUserRequired(testEmail)).Methods("POST") BaseRoutes.Admin.Handle("/client_props", ApiAppHandler(getClientConfig)).Methods("GET")
sr.Handle("/client_props", ApiAppHandler(getClientConfig)).Methods("GET") BaseRoutes.Admin.Handle("/log_client", ApiAppHandler(logClient)).Methods("POST")
sr.Handle("/log_client", ApiAppHandler(logClient)).Methods("POST") BaseRoutes.Admin.Handle("/analytics/{id:[A-Za-z0-9]+}/{name:[A-Za-z0-9_]+}", ApiUserRequired(getAnalytics)).Methods("GET")
sr.Handle("/analytics/{id:[A-Za-z0-9]+}/{name:[A-Za-z0-9_]+}", ApiUserRequired(getAnalytics)).Methods("GET") BaseRoutes.Admin.Handle("/analytics/{name:[A-Za-z0-9_]+}", ApiUserRequired(getAnalytics)).Methods("GET")
sr.Handle("/analytics/{name:[A-Za-z0-9_]+}", ApiUserRequired(getAnalytics)).Methods("GET") BaseRoutes.Admin.Handle("/save_compliance_report", ApiUserRequired(saveComplianceReport)).Methods("POST")
sr.Handle("/save_compliance_report", ApiUserRequired(saveComplianceReport)).Methods("POST") BaseRoutes.Admin.Handle("/compliance_reports", ApiUserRequired(getComplianceReports)).Methods("GET")
sr.Handle("/compliance_reports", ApiUserRequired(getComplianceReports)).Methods("GET") BaseRoutes.Admin.Handle("/download_compliance_report/{id:[A-Za-z0-9]+}", ApiUserRequired(downloadComplianceReport)).Methods("GET")
sr.Handle("/download_compliance_report/{id:[A-Za-z0-9]+}", ApiUserRequired(downloadComplianceReport)).Methods("GET") BaseRoutes.Admin.Handle("/upload_brand_image", ApiAdminSystemRequired(uploadBrandImage)).Methods("POST")
sr.Handle("/upload_brand_image", ApiAdminSystemRequired(uploadBrandImage)).Methods("POST") BaseRoutes.Admin.Handle("/get_brand_image", ApiAppHandlerTrustRequester(getBrandImage)).Methods("GET")
sr.Handle("/get_brand_image", ApiAppHandlerTrustRequester(getBrandImage)).Methods("GET") BaseRoutes.Admin.Handle("/reset_mfa", ApiAdminSystemRequired(adminResetMfa)).Methods("POST")
BaseRoutes.Admin.Handle("/reset_password", ApiAdminSystemRequired(adminResetPassword)).Methods("POST")
} }
func getLogs(c *Context, w http.ResponseWriter, r *http.Request) { func getLogs(c *Context, w http.ResponseWriter, r *http.Request) {
@@ -374,7 +375,7 @@ func getAnalytics(c *Context, w http.ResponseWriter, r *http.Request) {
iHookChan := Srv.Store.Webhook().AnalyticsIncomingCount(teamId) iHookChan := Srv.Store.Webhook().AnalyticsIncomingCount(teamId)
oHookChan := Srv.Store.Webhook().AnalyticsOutgoingCount(teamId) oHookChan := Srv.Store.Webhook().AnalyticsOutgoingCount(teamId)
commandChan := Srv.Store.Command().AnalyticsCommandCount(teamId) commandChan := Srv.Store.Command().AnalyticsCommandCount(teamId)
sessionChan := Srv.Store.Session().AnalyticsSessionCount(teamId) sessionChan := Srv.Store.Session().AnalyticsSessionCount()
if r := <-fileChan; r.Err != nil { if r := <-fileChan; r.Err != nil {
c.Err = r.Err c.Err = r.Err
@@ -498,3 +499,51 @@ func getBrandImage(c *Context, w http.ResponseWriter, r *http.Request) {
w.Write(img) w.Write(img)
} }
} }
func adminResetMfa(c *Context, w http.ResponseWriter, r *http.Request) {
props := model.MapFromJson(r.Body)
userId := props["user_id"]
if len(userId) != 26 {
c.SetInvalidParam("adminResetMfa", "user_id")
return
}
if err := DeactivateMfa(userId); err != nil {
c.Err = err
return
}
c.LogAudit("")
rdata := map[string]string{}
rdata["status"] = "ok"
w.Write([]byte(model.MapToJson(rdata)))
}
func adminResetPassword(c *Context, w http.ResponseWriter, r *http.Request) {
props := model.MapFromJson(r.Body)
userId := props["user_id"]
if len(userId) != 26 {
c.SetInvalidParam("adminResetPassword", "user_id")
return
}
newPassword := props["new_password"]
if len(newPassword) < model.MIN_PASSWORD_LENGTH {
c.SetInvalidParam("adminResetPassword", "new_password")
return
}
if err := ResetPassword(c, userId, newPassword); err != nil {
c.Err = err
return
}
c.LogAudit("")
rdata := map[string]string{}
rdata["status"] = "ok"
w.Write([]byte(model.MapToJson(rdata)))
}

Просмотреть файл

@@ -7,33 +7,18 @@ import (
"github.com/mattermost/platform/model" "github.com/mattermost/platform/model"
"github.com/mattermost/platform/store" "github.com/mattermost/platform/store"
"github.com/mattermost/platform/utils" "github.com/mattermost/platform/utils"
"strings"
"testing" "testing"
) )
func TestGetLogs(t *testing.T) { func TestGetLogs(t *testing.T) {
Setup() th := Setup().InitSystemAdmin().InitBasic()
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} if _, err := th.BasicClient.GetLogs(); err == nil {
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
user := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user.Id))
Client.LoginByEmail(team.Name, user.Email, "pwd")
if _, err := Client.GetLogs(); err == nil {
t.Fatal("Shouldn't have permissions") t.Fatal("Shouldn't have permissions")
} }
c := &Context{} if logs, err := th.SystemAdminClient.GetLogs(); err != nil {
c.RequestId = model.NewId()
c.IpAddress = "cmd_line"
UpdateRoles(c, user, model.ROLE_SYSTEM_ADMIN)
Client.LoginByEmail(team.Name, user.Email, "pwd")
if logs, err := Client.GetLogs(); err != nil {
t.Fatal(err) t.Fatal(err)
} else if len(logs.Data.([]string)) <= 0 { } else if len(logs.Data.([]string)) <= 0 {
t.Fatal() t.Fatal()
@@ -41,29 +26,13 @@ func TestGetLogs(t *testing.T) {
} }
func TestGetAllAudits(t *testing.T) { func TestGetAllAudits(t *testing.T) {
Setup() th := Setup().InitBasic().InitSystemAdmin()
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} if _, err := th.BasicClient.GetAllAudits(); err == nil {
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
user := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user.Id))
Client.LoginByEmail(team.Name, user.Email, "pwd")
if _, err := Client.GetAllAudits(); err == nil {
t.Fatal("Shouldn't have permissions") t.Fatal("Shouldn't have permissions")
} }
c := &Context{} if audits, err := th.SystemAdminClient.GetAllAudits(); err != nil {
c.RequestId = model.NewId()
c.IpAddress = "cmd_line"
UpdateRoles(c, user, model.ROLE_SYSTEM_ADMIN)
Client.LoginByEmail(team.Name, user.Email, "pwd")
if audits, err := Client.GetAllAudits(); err != nil {
t.Fatal(err) t.Fatal(err)
} else if len(audits.Data.(model.Audits)) <= 0 { } else if len(audits.Data.(model.Audits)) <= 0 {
t.Fatal() t.Fatal()
@@ -71,9 +40,9 @@ func TestGetAllAudits(t *testing.T) {
} }
func TestGetClientProperties(t *testing.T) { func TestGetClientProperties(t *testing.T) {
Setup() th := Setup().InitBasic()
if result, err := Client.GetClientProperties(); err != nil { if result, err := th.BasicClient.GetClientProperties(); err != nil {
t.Fatal(err) t.Fatal(err)
} else { } else {
props := result.Data.(map[string]string) props := result.Data.(map[string]string)
@@ -85,29 +54,13 @@ func TestGetClientProperties(t *testing.T) {
} }
func TestGetConfig(t *testing.T) { func TestGetConfig(t *testing.T) {
Setup() th := Setup().InitBasic().InitSystemAdmin()
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} if _, err := th.BasicClient.GetConfig(); err == nil {
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
user := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user.Id))
Client.LoginByEmail(team.Name, user.Email, "pwd")
if _, err := Client.GetConfig(); err == nil {
t.Fatal("Shouldn't have permissions") t.Fatal("Shouldn't have permissions")
} }
c := &Context{} if result, err := th.SystemAdminClient.GetConfig(); err != nil {
c.RequestId = model.NewId()
c.IpAddress = "cmd_line"
UpdateRoles(c, user, model.ROLE_SYSTEM_ADMIN)
Client.LoginByEmail(team.Name, user.Email, "pwd")
if result, err := Client.GetConfig(); err != nil {
t.Fatal(err) t.Fatal(err)
} else { } else {
cfg := result.Data.(*model.Config) cfg := result.Data.(*model.Config)
@@ -119,29 +72,15 @@ func TestGetConfig(t *testing.T) {
} }
func TestSaveConfig(t *testing.T) { func TestSaveConfig(t *testing.T) {
Setup() th := Setup().InitBasic().InitSystemAdmin()
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} if _, err := th.BasicClient.SaveConfig(utils.Cfg); err == nil {
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
user := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user.Id))
Client.LoginByEmail(team.Name, user.Email, "pwd")
if _, err := Client.SaveConfig(utils.Cfg); err == nil {
t.Fatal("Shouldn't have permissions") t.Fatal("Shouldn't have permissions")
} }
c := &Context{} *utils.Cfg.TeamSettings.EnableOpenServer = false
c.RequestId = model.NewId()
c.IpAddress = "cmd_line"
UpdateRoles(c, user, model.ROLE_SYSTEM_ADMIN)
Client.LoginByEmail(team.Name, user.Email, "pwd") if result, err := th.SystemAdminClient.SaveConfig(utils.Cfg); err != nil {
if result, err := Client.SaveConfig(utils.Cfg); err != nil {
t.Fatal(err) t.Fatal(err)
} else { } else {
cfg := result.Data.(*model.Config) cfg := result.Data.(*model.Config)
@@ -150,66 +89,31 @@ func TestSaveConfig(t *testing.T) {
t.Fatal() t.Fatal()
} }
} }
*utils.Cfg.TeamSettings.EnableOpenServer = true
} }
func TestEmailTest(t *testing.T) { func TestEmailTest(t *testing.T) {
Setup() th := Setup().InitBasic().InitSystemAdmin()
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} if _, err := th.BasicClient.TestEmail(utils.Cfg); err == nil {
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
user := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user.Id))
Client.LoginByEmail(team.Name, user.Email, "pwd")
if _, err := Client.TestEmail(utils.Cfg); err == nil {
t.Fatal("Shouldn't have permissions") t.Fatal("Shouldn't have permissions")
} }
c := &Context{} if _, err := th.SystemAdminClient.TestEmail(utils.Cfg); err != nil {
c.RequestId = model.NewId()
c.IpAddress = "cmd_line"
UpdateRoles(c, user, model.ROLE_SYSTEM_ADMIN)
Client.LoginByEmail(team.Name, user.Email, "pwd")
if _, err := Client.TestEmail(utils.Cfg); err != nil {
t.Fatal(err) t.Fatal(err)
} }
} }
func TestGetTeamAnalyticsStandard(t *testing.T) { func TestGetTeamAnalyticsStandard(t *testing.T) {
Setup() th := Setup().InitBasic().InitSystemAdmin()
th.CreatePrivateChannel(th.BasicClient, th.BasicTeam)
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} if _, err := th.BasicClient.GetTeamAnalytics(th.BasicTeam.Id, "standard"); err == nil {
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
user := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user.Id))
Client.LoginByEmail(team.Name, user.Email, "pwd")
channel1 := &model.Channel{DisplayName: "TestGetPosts", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_PRIVATE, TeamId: team.Id}
channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel)
post1 := &model.Post{ChannelId: channel1.Id, Message: "a" + model.NewId() + "a"}
post1 = Client.Must(Client.CreatePost(post1)).Data.(*model.Post)
if _, err := Client.GetTeamAnalytics(team.Id, "standard"); err == nil {
t.Fatal("Shouldn't have permissions") t.Fatal("Shouldn't have permissions")
} }
c := &Context{} if result, err := th.SystemAdminClient.GetTeamAnalytics(th.BasicTeam.Id, "standard"); err != nil {
c.RequestId = model.NewId()
c.IpAddress = "cmd_line"
UpdateRoles(c, user, model.ROLE_SYSTEM_ADMIN)
Client.LoginByEmail(team.Name, user.Email, "pwd")
if result, err := Client.GetTeamAnalytics(team.Id, "standard"); err != nil {
t.Fatal(err) t.Fatal(err)
} else { } else {
rows := result.Data.(model.AnalyticsRows) rows := result.Data.(model.AnalyticsRows)
@@ -219,7 +123,7 @@ func TestGetTeamAnalyticsStandard(t *testing.T) {
t.Fatal() t.Fatal()
} }
if rows[0].Value != 2 { if rows[0].Value != 3 {
t.Log(rows.ToJson()) t.Log(rows.ToJson())
t.Fatal() t.Fatal()
} }
@@ -249,7 +153,7 @@ func TestGetTeamAnalyticsStandard(t *testing.T) {
t.Fatal() t.Fatal()
} }
if rows[3].Value != 1 { if rows[3].Value != 2 {
t.Log(rows.ToJson()) t.Log(rows.ToJson())
t.Fatal() t.Fatal()
} }
@@ -265,7 +169,7 @@ func TestGetTeamAnalyticsStandard(t *testing.T) {
} }
} }
if result, err := Client.GetSystemAnalytics("standard"); err != nil { if result, err := th.SystemAdminClient.GetSystemAnalytics("standard"); err != nil {
t.Fatal(err) t.Fatal(err)
} else { } else {
rows := result.Data.(model.AnalyticsRows) rows := result.Data.(model.AnalyticsRows)
@@ -275,7 +179,7 @@ func TestGetTeamAnalyticsStandard(t *testing.T) {
t.Fatal() t.Fatal()
} }
if rows[0].Value < 2 { if rows[0].Value < 3 {
t.Log(rows.ToJson()) t.Log(rows.ToJson())
t.Fatal() t.Fatal()
} }
@@ -323,39 +227,17 @@ func TestGetTeamAnalyticsStandard(t *testing.T) {
} }
func TestGetPostCount(t *testing.T) { func TestGetPostCount(t *testing.T) {
Setup() th := Setup().InitBasic().InitSystemAdmin()
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN}
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
user := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user.Id))
Client.LoginByEmail(team.Name, user.Email, "pwd")
channel1 := &model.Channel{DisplayName: "TestGetPosts", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_PRIVATE, TeamId: team.Id}
channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel)
post1 := &model.Post{ChannelId: channel1.Id, Message: "a" + model.NewId() + "a"}
post1 = Client.Must(Client.CreatePost(post1)).Data.(*model.Post)
// manually update creation time, since it's always set to 0 upon saving and we only retrieve posts < today // manually update creation time, since it's always set to 0 upon saving and we only retrieve posts < today
Srv.Store.(*store.SqlStore).GetMaster().Exec("UPDATE Posts SET CreateAt = :CreateAt WHERE ChannelId = :ChannelId", Srv.Store.(*store.SqlStore).GetMaster().Exec("UPDATE Posts SET CreateAt = :CreateAt WHERE ChannelId = :ChannelId",
map[string]interface{}{"ChannelId": channel1.Id, "CreateAt": utils.MillisFromTime(utils.Yesterday())}) map[string]interface{}{"ChannelId": th.BasicChannel.Id, "CreateAt": utils.MillisFromTime(utils.Yesterday())})
if _, err := Client.GetTeamAnalytics(team.Id, "post_counts_day"); err == nil { if _, err := th.BasicClient.GetTeamAnalytics(th.BasicTeam.Id, "post_counts_day"); err == nil {
t.Fatal("Shouldn't have permissions") t.Fatal("Shouldn't have permissions")
} }
c := &Context{} if result, err := th.SystemAdminClient.GetTeamAnalytics(th.BasicTeam.Id, "post_counts_day"); err != nil {
c.RequestId = model.NewId()
c.IpAddress = "cmd_line"
UpdateRoles(c, user, model.ROLE_SYSTEM_ADMIN)
Client.LoginByEmail(team.Name, user.Email, "pwd")
if result, err := Client.GetTeamAnalytics(team.Id, "post_counts_day"); err != nil {
t.Fatal(err) t.Fatal(err)
} else { } else {
rows := result.Data.(model.AnalyticsRows) rows := result.Data.(model.AnalyticsRows)
@@ -368,39 +250,17 @@ func TestGetPostCount(t *testing.T) {
} }
func TestUserCountsWithPostsByDay(t *testing.T) { func TestUserCountsWithPostsByDay(t *testing.T) {
Setup() th := Setup().InitBasic().InitSystemAdmin()
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN}
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
user := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user.Id))
Client.LoginByEmail(team.Name, user.Email, "pwd")
channel1 := &model.Channel{DisplayName: "TestGetPosts", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_PRIVATE, TeamId: team.Id}
channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel)
post1 := &model.Post{ChannelId: channel1.Id, Message: "a" + model.NewId() + "a"}
post1 = Client.Must(Client.CreatePost(post1)).Data.(*model.Post)
// manually update creation time, since it's always set to 0 upon saving and we only retrieve posts < today // manually update creation time, since it's always set to 0 upon saving and we only retrieve posts < today
Srv.Store.(*store.SqlStore).GetMaster().Exec("UPDATE Posts SET CreateAt = :CreateAt WHERE ChannelId = :ChannelId", Srv.Store.(*store.SqlStore).GetMaster().Exec("UPDATE Posts SET CreateAt = :CreateAt WHERE ChannelId = :ChannelId",
map[string]interface{}{"ChannelId": channel1.Id, "CreateAt": utils.MillisFromTime(utils.Yesterday())}) map[string]interface{}{"ChannelId": th.BasicChannel.Id, "CreateAt": utils.MillisFromTime(utils.Yesterday())})
if _, err := Client.GetTeamAnalytics(team.Id, "user_counts_with_posts_day"); err == nil { if _, err := th.BasicClient.GetTeamAnalytics(th.BasicTeam.Id, "user_counts_with_posts_day"); err == nil {
t.Fatal("Shouldn't have permissions") t.Fatal("Shouldn't have permissions")
} }
c := &Context{} if result, err := th.SystemAdminClient.GetTeamAnalytics(th.BasicTeam.Id, "user_counts_with_posts_day"); err != nil {
c.RequestId = model.NewId()
c.IpAddress = "cmd_line"
UpdateRoles(c, user, model.ROLE_SYSTEM_ADMIN)
Client.LoginByEmail(team.Name, user.Email, "pwd")
if result, err := Client.GetTeamAnalytics(team.Id, "user_counts_with_posts_day"); err != nil {
t.Fatal(err) t.Fatal(err)
} else { } else {
rows := result.Data.(model.AnalyticsRows) rows := result.Data.(model.AnalyticsRows)
@@ -413,38 +273,15 @@ func TestUserCountsWithPostsByDay(t *testing.T) {
} }
func TestGetTeamAnalyticsExtra(t *testing.T) { func TestGetTeamAnalyticsExtra(t *testing.T) {
Setup() th := Setup().InitBasic().InitSystemAdmin()
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} th.CreatePost(th.BasicClient, th.BasicChannel)
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
user := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"} if _, err := th.BasicClient.GetTeamAnalytics("", "extra_counts"); err == nil {
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user.Id))
Client.LoginByEmail(team.Name, user.Email, "pwd")
channel1 := &model.Channel{DisplayName: "TestGetPosts", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_PRIVATE, TeamId: team.Id}
channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel)
post1 := &model.Post{ChannelId: channel1.Id, Message: "a" + model.NewId() + "a"}
post1 = Client.Must(Client.CreatePost(post1)).Data.(*model.Post)
post2 := &model.Post{ChannelId: channel1.Id, Message: "#test a" + model.NewId() + "a"}
post2 = Client.Must(Client.CreatePost(post2)).Data.(*model.Post)
if _, err := Client.GetTeamAnalytics("", "extra_counts"); err == nil {
t.Fatal("Shouldn't have permissions") t.Fatal("Shouldn't have permissions")
} }
c := &Context{} if result, err := th.SystemAdminClient.GetTeamAnalytics(th.BasicTeam.Id, "extra_counts"); err != nil {
c.RequestId = model.NewId()
c.IpAddress = "cmd_line"
UpdateRoles(c, user, model.ROLE_SYSTEM_ADMIN)
Client.LoginByEmail(team.Name, user.Email, "pwd")
if result, err := Client.GetTeamAnalytics(team.Id, "extra_counts"); err != nil {
t.Fatal(err) t.Fatal(err)
} else { } else {
rows := result.Data.(model.AnalyticsRows) rows := result.Data.(model.AnalyticsRows)
@@ -464,7 +301,7 @@ func TestGetTeamAnalyticsExtra(t *testing.T) {
t.Fatal() t.Fatal()
} }
if rows[1].Value != 1 { if rows[1].Value != 0 {
t.Log(rows.ToJson()) t.Log(rows.ToJson())
t.Fatal() t.Fatal()
} }
@@ -510,7 +347,7 @@ func TestGetTeamAnalyticsExtra(t *testing.T) {
} }
} }
if result, err := Client.GetSystemAnalytics("extra_counts"); err != nil { if result, err := th.SystemAdminClient.GetSystemAnalytics("extra_counts"); err != nil {
t.Fatal(err) t.Fatal(err)
} else { } else {
rows := result.Data.(model.AnalyticsRows) rows := result.Data.(model.AnalyticsRows)
@@ -525,11 +362,6 @@ func TestGetTeamAnalyticsExtra(t *testing.T) {
t.Fatal() t.Fatal()
} }
if rows[1].Value < 1 {
t.Log(rows.ToJson())
t.Fatal()
}
if rows[2].Name != "incoming_webhook_count" { if rows[2].Name != "incoming_webhook_count" {
t.Log(rows.ToJson()) t.Log(rows.ToJson())
t.Fatal() t.Fatal()
@@ -551,3 +383,73 @@ func TestGetTeamAnalyticsExtra(t *testing.T) {
} }
} }
} }
func TestAdminResetMfa(t *testing.T) {
th := Setup().InitBasic().InitSystemAdmin()
if _, err := th.BasicClient.AdminResetMfa("12345678901234567890123456"); err == nil {
t.Fatal("should have failed - not an admin")
}
if _, err := th.SystemAdminClient.AdminResetMfa(""); err == nil {
t.Fatal("should have failed - empty user id")
}
if _, err := th.SystemAdminClient.AdminResetMfa("12345678901234567890123456"); err == nil {
t.Fatal("should have failed - bad user id")
}
if _, err := th.SystemAdminClient.AdminResetMfa(th.BasicUser.Id); err == nil {
t.Fatal("should have failed - not licensed or configured")
}
// need to add more test cases when enterprise bits can be loaded into tests
}
func TestAdminResetPassword(t *testing.T) {
th := Setup().InitSystemAdmin()
Client := th.SystemAdminClient
team := th.SystemAdminTeam
user := &model.User{Email: strings.ToLower(model.NewId()) + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
LinkUserToTeam(user, team)
store.Must(Srv.Store.User().VerifyEmail(user.Id))
if _, err := Client.AdminResetPassword("", "newpwd"); err == nil {
t.Fatal("Should have errored - empty user id")
}
if _, err := Client.AdminResetPassword("123", "newpwd"); err == nil {
t.Fatal("Should have errored - bad user id")
}
if _, err := Client.AdminResetPassword("12345678901234567890123456", "newpwd"); err == nil {
t.Fatal("Should have errored - bad user id")
}
if _, err := Client.AdminResetPassword("12345678901234567890123456", "newp"); err == nil {
t.Fatal("Should have errored - password too short")
}
user2 := &model.User{Email: strings.ToLower(model.NewId()) + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", AuthData: "1", AuthService: "random"}
user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User)
LinkUserToTeam(user2, team)
store.Must(Srv.Store.User().VerifyEmail(user2.Id))
if _, err := Client.AdminResetPassword(user2.Id, "newpwd"); err == nil {
t.Fatal("should have errored - SSO user can't reset password")
}
if _, err := Client.AdminResetPassword(user.Id, "newpwd"); err != nil {
t.Fatal(err)
}
Client.Logout()
Client.Must(Client.LoginById(user.Id, "newpwd"))
Client.SetTeamId(team.Id)
if _, err := Client.AdminResetPassword(user.Id, "newpwd"); err == nil {
t.Fatal("Should have errored - not sytem admin")
}
}

Просмотреть файл

@@ -6,6 +6,7 @@ package api
import ( import (
"net/http" "net/http"
"github.com/gorilla/mux"
"github.com/mattermost/platform/model" "github.com/mattermost/platform/model"
"github.com/mattermost/platform/utils" "github.com/mattermost/platform/utils"
@@ -13,20 +14,71 @@ import (
_ "github.com/nicksnyder/go-i18n/i18n" _ "github.com/nicksnyder/go-i18n/i18n"
) )
type Routes struct {
Root *mux.Router // ''
ApiRoot *mux.Router // 'api/v3'
Users *mux.Router // 'api/v3/users'
NeedUser *mux.Router // 'api/v3/users/{user_id:[A-Za-z0-9]+}'
Teams *mux.Router // 'api/v3/teams'
NeedTeam *mux.Router // 'api/v3/teams/{team_id:[A-Za-z0-9]+}'
Channels *mux.Router // 'api/v3/teams/{team_id:[A-Za-z0-9]+}/channels'
NeedChannel *mux.Router // 'api/v3/teams/{team_id:[A-Za-z0-9]+}/channels/{channel_id:[A-Za-z0-9]+}'
Posts *mux.Router // 'api/v3/teams/{team_id:[A-Za-z0-9]+}/channels/{channel_id:[A-Za-z0-9]+}/posts'
NeedPost *mux.Router // 'api/v3/teams/{team_id:[A-Za-z0-9]+}/channels/{channel_id:[A-Za-z0-9]+}/posts/{post_id:[A-Za-z0-9]+}'
Commands *mux.Router // 'api/v3/teams/{team_id:[A-Za-z0-9]+}/commands'
Hooks *mux.Router // 'api/v3/teams/{team_id:[A-Za-z0-9]+}/hooks'
Files *mux.Router // 'api/v3/teams/{team_id:[A-Za-z0-9]+}/files'
OAuth *mux.Router // 'api/v3/oauth'
Admin *mux.Router // 'api/v3/admin'
Preferences *mux.Router // 'api/v3/preferences'
License *mux.Router // 'api/v3/license'
}
var BaseRoutes *Routes
func InitApi() { func InitApi() {
r := Srv.Router.PathPrefix("/api/v1").Subrouter() BaseRoutes = &Routes{}
InitUser(r) BaseRoutes.Root = Srv.Router
InitTeam(r) BaseRoutes.ApiRoot = Srv.Router.PathPrefix(model.API_URL_SUFFIX).Subrouter()
InitChannel(r) BaseRoutes.Users = BaseRoutes.ApiRoot.PathPrefix("/users").Subrouter()
InitPost(r) BaseRoutes.NeedUser = BaseRoutes.Users.PathPrefix("/{user_id:[A-Za-z0-9]+}").Subrouter()
InitWebSocket(r) BaseRoutes.Teams = BaseRoutes.ApiRoot.PathPrefix("/teams").Subrouter()
InitFile(r) BaseRoutes.NeedTeam = BaseRoutes.Teams.PathPrefix("/{team_id:[A-Za-z0-9]+}").Subrouter()
InitCommand(r) BaseRoutes.Channels = BaseRoutes.NeedTeam.PathPrefix("/channels").Subrouter()
InitAdmin(r) BaseRoutes.NeedChannel = BaseRoutes.Channels.PathPrefix("/{channel_id:[A-Za-z0-9]+}").Subrouter()
InitOAuth(r) BaseRoutes.Posts = BaseRoutes.NeedChannel.PathPrefix("/posts").Subrouter()
InitWebhook(r) BaseRoutes.NeedPost = BaseRoutes.Posts.PathPrefix("/{post_id:[A-Za-z0-9]+}").Subrouter()
InitPreference(r) BaseRoutes.Commands = BaseRoutes.NeedTeam.PathPrefix("/commands").Subrouter()
InitLicense(r) BaseRoutes.Files = BaseRoutes.NeedTeam.PathPrefix("/files").Subrouter()
BaseRoutes.Hooks = BaseRoutes.NeedTeam.PathPrefix("/hooks").Subrouter()
BaseRoutes.OAuth = BaseRoutes.ApiRoot.PathPrefix("/oauth").Subrouter()
BaseRoutes.Admin = BaseRoutes.ApiRoot.PathPrefix("/admin").Subrouter()
BaseRoutes.Preferences = BaseRoutes.ApiRoot.PathPrefix("/preferences").Subrouter()
BaseRoutes.License = BaseRoutes.ApiRoot.PathPrefix("/license").Subrouter()
InitUser()
InitTeam()
InitChannel()
InitPost()
InitWebSocket()
InitFile()
InitCommand()
InitAdmin()
InitOAuth()
InitWebhook()
InitPreference()
InitLicense()
// 404 on any api route before web.go has a chance to serve it // 404 on any api route before web.go has a chance to serve it
Srv.Router.Handle("/api/{anything:.*}", http.HandlerFunc(Handle404)) Srv.Router.Handle("/api/{anything:.*}", http.HandlerFunc(Handle404))

Просмотреть файл

@@ -1,47 +0,0 @@
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api
import (
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/store"
"github.com/mattermost/platform/utils"
)
var Client *model.Client
func Setup() {
if Srv == nil {
utils.LoadConfig("config.json")
utils.InitTranslations()
utils.Cfg.TeamSettings.MaxUsersPerTeam = 50
NewServer()
StartServer()
InitApi()
Client = model.NewClient("http://localhost" + utils.Cfg.ServiceSettings.ListenAddress)
Srv.Store.MarkSystemRanUnitTests()
}
}
func SetupBenchmark() (*model.Team, *model.User, *model.Channel) {
Setup()
team := &model.Team{DisplayName: "Benchmark Team", Name: "z-z-" + model.NewId() + "a", Email: "benchmark@nowhere.com", Type: model.TEAM_OPEN}
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
user := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Mr. Benchmarker", Password: "pwd"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user.Id))
Client.LoginByEmail(team.Name, user.Email, "pwd")
channel := &model.Channel{DisplayName: "Benchmark Channel", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
channel = Client.Must(Client.CreateChannel(channel)).Data.(*model.Channel)
return team, user, channel
}
func TearDown() {
if Srv != nil {
StopServer()
}
}

223
api/apitestlib.go Обычный файл
Просмотреть файл

@@ -0,0 +1,223 @@
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api
import (
"time"
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/store"
"github.com/mattermost/platform/utils"
l4g "github.com/alecthomas/log4go"
)
type TestHelper struct {
BasicClient *model.Client
BasicTeam *model.Team
BasicUser *model.User
BasicUser2 *model.User
BasicChannel *model.Channel
BasicPost *model.Post
SystemAdminClient *model.Client
SystemAdminTeam *model.Team
SystemAdminUser *model.User
SystemAdminChannel *model.Channel
}
func SetupEnterprise(platformDir string) *TestHelper {
if Srv == nil {
utils.LoadConfig(platformDir + "/config/config.json")
utils.InitTranslationsWithDir(platformDir + "/i18n")
utils.Cfg.TeamSettings.MaxUsersPerTeam = 50
utils.DisableDebugLogForTest()
utils.License.Features.SetDefaults()
NewServer()
StartServer()
utils.InitHTMLWithDir(platformDir + "/templates")
InitApi()
utils.EnableDebugLogForTest()
Srv.Store.MarkSystemRanUnitTests()
*utils.Cfg.TeamSettings.EnableOpenServer = true
}
return &TestHelper{}
}
func Setup() *TestHelper {
if Srv == nil {
utils.LoadConfig("config.json")
utils.InitTranslations()
utils.Cfg.TeamSettings.MaxUsersPerTeam = 50
utils.DisableDebugLogForTest()
NewServer()
StartServer()
InitApi()
utils.EnableDebugLogForTest()
Srv.Store.MarkSystemRanUnitTests()
*utils.Cfg.TeamSettings.EnableOpenServer = true
}
return &TestHelper{}
}
func (me *TestHelper) InitBasic() *TestHelper {
me.BasicClient = me.CreateClient()
me.BasicTeam = me.CreateTeam(me.BasicClient)
me.BasicUser = me.CreateUser(me.BasicClient)
LinkUserToTeam(me.BasicUser, me.BasicTeam)
me.BasicUser2 = me.CreateUser(me.BasicClient)
LinkUserToTeam(me.BasicUser2, me.BasicTeam)
me.BasicClient.SetTeamId(me.BasicTeam.Id)
me.LoginBasic()
me.BasicChannel = me.CreateChannel(me.BasicClient, me.BasicTeam)
me.BasicPost = me.CreatePost(me.BasicClient, me.BasicChannel)
return me
}
func (me *TestHelper) InitSystemAdmin() *TestHelper {
me.SystemAdminClient = me.CreateClient()
me.SystemAdminTeam = me.CreateTeam(me.SystemAdminClient)
me.SystemAdminUser = me.CreateUser(me.SystemAdminClient)
LinkUserToTeam(me.SystemAdminUser, me.SystemAdminTeam)
me.SystemAdminClient.SetTeamId(me.SystemAdminTeam.Id)
c := &Context{}
c.RequestId = model.NewId()
c.IpAddress = "cmd_line"
UpdateRoles(c, me.SystemAdminUser, model.ROLE_SYSTEM_ADMIN)
me.SystemAdminUser.Password = "Password1"
me.LoginSystemAdmin()
me.SystemAdminChannel = me.CreateChannel(me.SystemAdminClient, me.SystemAdminTeam)
return me
}
func (me *TestHelper) CreateClient() *model.Client {
return model.NewClient("http://localhost" + utils.Cfg.ServiceSettings.ListenAddress)
}
func (me *TestHelper) CreateTeam(client *model.Client) *model.Team {
id := model.NewId()
team := &model.Team{
DisplayName: "dn_" + id,
Name: "name" + id,
Email: "success+" + id + "@simulator.amazonses.com",
Type: model.TEAM_OPEN,
}
utils.DisableDebugLogForTest()
r := client.Must(client.CreateTeam(team)).Data.(*model.Team)
utils.EnableDebugLogForTest()
return r
}
func (me *TestHelper) CreateUser(client *model.Client) *model.User {
id := model.NewId()
user := &model.User{
Email: "success+" + id + "@simulator.amazonses.com",
Username: "un_" + id,
Nickname: "nn_" + id,
Password: "Password1",
}
utils.DisableDebugLogForTest()
ruser := client.Must(client.CreateUser(user, "")).Data.(*model.User)
ruser.Password = "Password1"
store.Must(Srv.Store.User().VerifyEmail(ruser.Id))
utils.EnableDebugLogForTest()
return ruser
}
func LinkUserToTeam(user *model.User, team *model.Team) {
utils.DisableDebugLogForTest()
err := JoinUserToTeam(team, user)
if err != nil {
l4g.Error(err.Error())
l4g.Close()
time.Sleep(time.Second)
panic(err)
}
utils.EnableDebugLogForTest()
}
func UpdateUserToTeamAdmin(user *model.User, team *model.Team) {
utils.DisableDebugLogForTest()
tm := &model.TeamMember{TeamId: team.Id, UserId: user.Id, Roles: model.ROLE_TEAM_ADMIN}
if tmr := <-Srv.Store.Team().UpdateMember(tm); tmr.Err != nil {
l4g.Error(tmr.Err.Error())
l4g.Close()
time.Sleep(time.Second)
panic(tmr.Err)
}
}
func (me *TestHelper) CreateChannel(client *model.Client, team *model.Team) *model.Channel {
return me.createChannel(client, team, model.CHANNEL_OPEN)
}
func (me *TestHelper) CreatePrivateChannel(client *model.Client, team *model.Team) *model.Channel {
return me.createChannel(client, team, model.CHANNEL_PRIVATE)
}
func (me *TestHelper) createChannel(client *model.Client, team *model.Team, channelType string) *model.Channel {
id := model.NewId()
channel := &model.Channel{
DisplayName: "dn_" + id,
Name: "name_" + id,
Type: channelType,
TeamId: team.Id,
}
utils.DisableDebugLogForTest()
r := client.Must(client.CreateChannel(channel)).Data.(*model.Channel)
utils.EnableDebugLogForTest()
return r
}
func (me *TestHelper) CreatePost(client *model.Client, channel *model.Channel) *model.Post {
id := model.NewId()
post := &model.Post{
ChannelId: channel.Id,
Message: "message_" + id,
}
utils.DisableDebugLogForTest()
r := client.Must(client.CreatePost(post)).Data.(*model.Post)
utils.EnableDebugLogForTest()
return r
}
func (me *TestHelper) LoginBasic() {
utils.DisableDebugLogForTest()
me.BasicClient.Must(me.BasicClient.LoginByEmail(me.BasicTeam.Name, me.BasicUser.Email, me.BasicUser.Password))
utils.EnableDebugLogForTest()
}
func (me *TestHelper) LoginBasic2() {
utils.DisableDebugLogForTest()
me.BasicClient.Must(me.BasicClient.LoginByEmail(me.BasicTeam.Name, me.BasicUser2.Email, me.BasicUser2.Password))
utils.EnableDebugLogForTest()
}
func (me *TestHelper) LoginSystemAdmin() {
utils.DisableDebugLogForTest()
me.SystemAdminClient.Must(me.SystemAdminClient.LoginByEmail(me.SystemAdminTeam.Name, me.SystemAdminUser.Email, me.SystemAdminUser.Password))
utils.EnableDebugLogForTest()
}
func TearDown() {
if Srv != nil {
StopServer()
}
}

99
api/authentication.go Обычный файл
Просмотреть файл

@@ -0,0 +1,99 @@
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api
import (
"github.com/mattermost/platform/einterfaces"
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/utils"
)
func checkPasswordAndAllCriteria(user *model.User, password string, mfaToken string) *model.AppError {
if err := checkUserPassword(user, password); err != nil {
return err
}
if err := checkUserAdditionalAuthenticationCriteria(user, mfaToken); err != nil {
return err
}
return nil
}
func checkUserPassword(user *model.User, password string) *model.AppError {
if !model.ComparePassword(user.Password, password) {
if result := <-Srv.Store.User().UpdateFailedPasswordAttempts(user.Id, user.FailedAttempts+1); result.Err != nil {
return result.Err
}
return model.NewLocAppError("checkUserPassword", "api.user.check_user_password.invalid.app_error", nil, "user_id="+user.Id)
} else {
if result := <-Srv.Store.User().UpdateFailedPasswordAttempts(user.Id, 0); result.Err != nil {
return result.Err
}
return nil
}
}
func checkUserAdditionalAuthenticationCriteria(user *model.User, mfaToken string) *model.AppError {
if err := checkUserMfa(user, mfaToken); err != nil {
return err
}
if err := checkEmailVerified(user); err != nil {
return err
}
if err := checkUserNotDisabled(user); err != nil {
return err
}
if err := checkUserLoginAttempts(user); err != nil {
return err
}
return nil
}
func checkUserMfa(user *model.User, token string) *model.AppError {
if !user.MfaActive || !utils.IsLicensed || !*utils.License.Features.MFA || !*utils.Cfg.ServiceSettings.EnableMultifactorAuthentication {
return nil
}
mfaInterface := einterfaces.GetMfaInterface()
if mfaInterface == nil {
return model.NewLocAppError("checkUserMfa", "api.user.check_user_mfa.not_available.app_error", nil, "")
}
if ok, err := mfaInterface.ValidateToken(user.MfaSecret, token); err != nil {
return err
} else if !ok {
return model.NewLocAppError("checkUserMfa", "api.user.check_user_mfa.bad_code.app_error", nil, "")
}
return nil
}
func checkUserLoginAttempts(user *model.User) *model.AppError {
if user.FailedAttempts >= utils.Cfg.ServiceSettings.MaximumLoginAttempts {
return model.NewLocAppError("checkUserLoginAttempts", "api.user.check_user_login_attempts.too_many.app_error", nil, "user_id="+user.Id)
}
return nil
}
func checkEmailVerified(user *model.User) *model.AppError {
if !user.EmailVerified && utils.Cfg.EmailSettings.RequireEmailVerification {
return model.NewLocAppError("Login", "api.user.login.not_verified.app_error", nil, "user_id="+user.Id)
}
return nil
}
func checkUserNotDisabled(user *model.User) *model.AppError {
if user.DeleteAt > 0 {
return model.NewLocAppError("Login", "api.user.login.inactive.app_error", nil, "user_id="+user.Id)
}
return nil
}

Просмотреть файл

@@ -10,7 +10,7 @@ import (
type AutoChannelCreator struct { type AutoChannelCreator struct {
client *model.Client client *model.Client
teamID string team *model.Team
Fuzzy bool Fuzzy bool
DisplayNameLen utils.Range DisplayNameLen utils.Range
DisplayNameCharset string DisplayNameCharset string
@@ -19,10 +19,10 @@ type AutoChannelCreator struct {
ChannelType string ChannelType string
} }
func NewAutoChannelCreator(client *model.Client, teamID string) *AutoChannelCreator { func NewAutoChannelCreator(client *model.Client, team *model.Team) *AutoChannelCreator {
return &AutoChannelCreator{ return &AutoChannelCreator{
client: client, client: client,
teamID: teamID, team: team,
Fuzzy: false, Fuzzy: false,
DisplayNameLen: CHANNEL_DISPLAY_NAME_LEN, DisplayNameLen: CHANNEL_DISPLAY_NAME_LEN,
DisplayNameCharset: utils.ALPHANUMERIC, DisplayNameCharset: utils.ALPHANUMERIC,
@@ -42,13 +42,17 @@ func (cfg *AutoChannelCreator) createRandomChannel() (*model.Channel, bool) {
name := utils.RandomName(cfg.NameLen, cfg.NameCharset) name := utils.RandomName(cfg.NameLen, cfg.NameCharset)
channel := &model.Channel{ channel := &model.Channel{
TeamId: cfg.teamID, TeamId: cfg.team.Id,
DisplayName: displayName, DisplayName: displayName,
Name: name, Name: name,
Type: cfg.ChannelType} Type: cfg.ChannelType}
println(cfg.client.GetTeamRoute())
result, err := cfg.client.CreateChannel(channel) result, err := cfg.client.CreateChannel(channel)
if err != nil { if err != nil {
err.Translate(utils.T)
println(err.Error())
println(err.DetailedError)
return nil, false return nil, false
} }
return result.Data.(*model.Channel), true return result.Data.(*model.Channel), true

Просмотреть файл

@@ -28,14 +28,15 @@ func CreateTestEnvironmentWithTeams(client *model.Client, rangeTeams utils.Range
environment := TestEnvironment{teams, make([]TeamEnvironment, len(teams))} environment := TestEnvironment{teams, make([]TeamEnvironment, len(teams))}
for i, team := range teams { for i, team := range teams {
userCreator := NewAutoUserCreator(client, team.Id) userCreator := NewAutoUserCreator(client, team)
userCreator.Fuzzy = fuzzy userCreator.Fuzzy = fuzzy
randomUser, err := userCreator.createRandomUser() randomUser, err := userCreator.createRandomUser()
if err != true { if err != true {
return TestEnvironment{}, false return TestEnvironment{}, false
} }
client.LoginById(randomUser.Id, USER_PASSWORD) client.LoginById(randomUser.Id, USER_PASSWORD)
teamEnvironment, err := CreateTestEnvironmentInTeam(client, team.Id, rangeChannels, rangeUsers, rangePosts, fuzzy) client.SetTeamId(team.Id)
teamEnvironment, err := CreateTestEnvironmentInTeam(client, team, rangeChannels, rangeUsers, rangePosts, fuzzy)
if err != true { if err != true {
return TestEnvironment{}, false return TestEnvironment{}, false
} }
@@ -45,7 +46,7 @@ func CreateTestEnvironmentWithTeams(client *model.Client, rangeTeams utils.Range
return environment, true return environment, true
} }
func CreateTestEnvironmentInTeam(client *model.Client, teamID string, rangeChannels utils.Range, rangeUsers utils.Range, rangePosts utils.Range, fuzzy bool) (TeamEnvironment, bool) { func CreateTestEnvironmentInTeam(client *model.Client, team *model.Team, rangeChannels utils.Range, rangeUsers utils.Range, rangePosts utils.Range, fuzzy bool) (TeamEnvironment, bool) {
rand.Seed(time.Now().UTC().UnixNano()) rand.Seed(time.Now().UTC().UnixNano())
// We need to create at least one user // We need to create at least one user
@@ -53,7 +54,7 @@ func CreateTestEnvironmentInTeam(client *model.Client, teamID string, rangeChann
rangeUsers.Begin = 1 rangeUsers.Begin = 1
} }
userCreator := NewAutoUserCreator(client, teamID) userCreator := NewAutoUserCreator(client, team)
userCreator.Fuzzy = fuzzy userCreator.Fuzzy = fuzzy
users, err := userCreator.CreateTestUsers(rangeUsers) users, err := userCreator.CreateTestUsers(rangeUsers)
if err != true { if err != true {
@@ -64,7 +65,7 @@ func CreateTestEnvironmentInTeam(client *model.Client, teamID string, rangeChann
usernames[i] = user.Username usernames[i] = user.Username
} }
channelCreator := NewAutoChannelCreator(client, teamID) channelCreator := NewAutoChannelCreator(client, team)
channelCreator.Fuzzy = fuzzy channelCreator.Fuzzy = fuzzy
channels, err := channelCreator.CreateTestChannels(rangeChannels) channels, err := channelCreator.CreateTestChannels(rangeChannels)
@@ -79,6 +80,7 @@ func CreateTestEnvironmentInTeam(client *model.Client, teamID string, rangeChann
if err != true { if err != true {
return TeamEnvironment{}, false return TeamEnvironment{}, false
} }
numPosts := utils.RandIntFromRange(rangePosts) numPosts := utils.RandIntFromRange(rangePosts)
numImages := utils.RandIntFromRange(rangePosts) / 4 numImages := utils.RandIntFromRange(rangePosts) / 4
for j := 0; j < numPosts; j++ { for j := 0; j < numPosts; j++ {

Просмотреть файл

@@ -74,7 +74,7 @@ func (cfg *AutoPostCreator) UploadTestFile() ([]string, bool) {
return nil, false return nil, false
} }
resp, appErr := cfg.client.UploadFile("/files/upload", body.Bytes(), writer.FormDataContentType()) resp, appErr := cfg.client.UploadPostAttachment(body.Bytes(), writer.FormDataContentType())
if appErr != nil { if appErr != nil {
return nil, false return nil, false
} }

Просмотреть файл

@@ -42,11 +42,11 @@ func (cfg *AutoTeamCreator) createRandomTeam() (*model.Team, bool) {
var teamDisplayName string var teamDisplayName string
var teamName string var teamName string
if cfg.Fuzzy { if cfg.Fuzzy {
teamEmail = utils.FuzzEmail() teamEmail = "success+" + model.NewId() + "simulator.amazonses.com"
teamDisplayName = utils.FuzzName() teamDisplayName = utils.FuzzName()
teamName = utils.FuzzName() teamName = utils.FuzzName()
} else { } else {
teamEmail = utils.RandomEmail(cfg.EmailLength, cfg.EmailCharset) teamEmail = "success+" + model.NewId() + "simulator.amazonses.com"
teamDisplayName = utils.RandomName(cfg.NameLength, cfg.NameCharset) teamDisplayName = utils.RandomName(cfg.NameLength, cfg.NameCharset)
teamName = utils.RandomName(cfg.NameLength, cfg.NameCharset) + model.NewId() teamName = utils.RandomName(cfg.NameLength, cfg.NameCharset) + model.NewId()
} }

Просмотреть файл

@@ -7,11 +7,13 @@ import (
"github.com/mattermost/platform/model" "github.com/mattermost/platform/model"
"github.com/mattermost/platform/store" "github.com/mattermost/platform/store"
"github.com/mattermost/platform/utils" "github.com/mattermost/platform/utils"
l4g "github.com/alecthomas/log4go"
) )
type AutoUserCreator struct { type AutoUserCreator struct {
client *model.Client client *model.Client
teamID string team *model.Team
EmailLength utils.Range EmailLength utils.Range
EmailCharset string EmailCharset string
NameLength utils.Range NameLength utils.Range
@@ -19,10 +21,10 @@ type AutoUserCreator struct {
Fuzzy bool Fuzzy bool
} }
func NewAutoUserCreator(client *model.Client, teamID string) *AutoUserCreator { func NewAutoUserCreator(client *model.Client, team *model.Team) *AutoUserCreator {
return &AutoUserCreator{ return &AutoUserCreator{
client: client, client: client,
teamID: teamID, team: team,
EmailLength: USER_EMAIL_LEN, EmailLength: USER_EMAIL_LEN,
EmailCharset: utils.LOWERCASE, EmailCharset: utils.LOWERCASE,
NameLength: USER_NAME_LEN, NameLength: USER_NAME_LEN,
@@ -33,7 +35,7 @@ func NewAutoUserCreator(client *model.Client, teamID string) *AutoUserCreator {
// Basic test team and user so you always know one // Basic test team and user so you always know one
func CreateBasicUser(client *model.Client) *model.AppError { func CreateBasicUser(client *model.Client) *model.AppError {
result, _ := client.FindTeamByName(BTEST_TEAM_NAME, true) result, _ := client.FindTeamByName(BTEST_TEAM_NAME)
if result.Data.(bool) == false { if result.Data.(bool) == false {
newteam := &model.Team{DisplayName: BTEST_TEAM_DISPLAY_NAME, Name: BTEST_TEAM_NAME, Email: BTEST_TEAM_EMAIL, Type: BTEST_TEAM_TYPE} newteam := &model.Team{DisplayName: BTEST_TEAM_DISPLAY_NAME, Name: BTEST_TEAM_NAME, Email: BTEST_TEAM_EMAIL, Type: BTEST_TEAM_TYPE}
result, err := client.CreateTeam(newteam) result, err := client.CreateTeam(newteam)
@@ -41,12 +43,14 @@ func CreateBasicUser(client *model.Client) *model.AppError {
return err return err
} }
basicteam := result.Data.(*model.Team) basicteam := result.Data.(*model.Team)
newuser := &model.User{TeamId: basicteam.Id, Email: BTEST_USER_EMAIL, Nickname: BTEST_USER_NAME, Password: BTEST_USER_PASSWORD} newuser := &model.User{Email: BTEST_USER_EMAIL, Nickname: BTEST_USER_NAME, Password: BTEST_USER_PASSWORD}
result, err = client.CreateUser(newuser, "") result, err = client.CreateUser(newuser, "")
if err != nil { if err != nil {
return err return err
} }
store.Must(Srv.Store.User().VerifyEmail(result.Data.(*model.User).Id)) ruser := result.Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(ruser.Id))
store.Must(Srv.Store.Team().SaveMember(&model.TeamMember{TeamId: basicteam.Id, UserId: ruser.Id}))
} }
return nil return nil
} }
@@ -55,25 +59,30 @@ func (cfg *AutoUserCreator) createRandomUser() (*model.User, bool) {
var userEmail string var userEmail string
var userName string var userName string
if cfg.Fuzzy { if cfg.Fuzzy {
userEmail = utils.RandString(FUZZ_USER_EMAIL_PREFIX_LEN, utils.LOWERCASE) + "-" + utils.FuzzEmail() userEmail = "success+" + model.NewId() + "simulator.amazonses.com"
userName = utils.FuzzName() userName = utils.FuzzName()
} else { } else {
userEmail = utils.RandomEmail(cfg.EmailLength, cfg.EmailCharset) userEmail = "success+" + model.NewId() + "simulator.amazonses.com"
userName = utils.RandomName(cfg.NameLength, cfg.NameCharset) userName = utils.RandomName(cfg.NameLength, cfg.NameCharset)
} }
user := &model.User{ user := &model.User{
TeamId: cfg.teamID,
Email: userEmail, Email: userEmail,
Nickname: userName, Nickname: userName,
Password: USER_PASSWORD} Password: USER_PASSWORD}
result, err := cfg.client.CreateUser(user, "") result, err := cfg.client.CreateUserWithInvite(user, "", "", cfg.team.InviteId)
if err != nil { if err != nil {
err.Translate(utils.T)
l4g.Error(err.Error())
return nil, false return nil, false
} }
ruser := result.Data.(*model.User)
// We need to cheat to verify the user's email // We need to cheat to verify the user's email
store.Must(Srv.Store.User().VerifyEmail(result.Data.(*model.User).Id)) store.Must(Srv.Store.User().VerifyEmail(ruser.Id))
return result.Data.(*model.User), true return result.Data.(*model.User), true
} }

Просмотреть файл

@@ -18,29 +18,28 @@ const (
defaultExtraMemberLimit = 100 defaultExtraMemberLimit = 100
) )
func InitChannel(r *mux.Router) { func InitChannel() {
l4g.Debug(utils.T("api.channel.init.debug")) l4g.Debug(utils.T("api.channel.init.debug"))
sr := r.PathPrefix("/channels").Subrouter() BaseRoutes.Channels.Handle("/", ApiUserRequiredActivity(getChannels, false)).Methods("GET")
sr.Handle("/", ApiUserRequiredActivity(getChannels, false)).Methods("GET") BaseRoutes.Channels.Handle("/more", ApiUserRequired(getMoreChannels)).Methods("GET")
sr.Handle("/more", ApiUserRequired(getMoreChannels)).Methods("GET") BaseRoutes.Channels.Handle("/counts", ApiUserRequiredActivity(getChannelCounts, false)).Methods("GET")
sr.Handle("/counts", ApiUserRequiredActivity(getChannelCounts, false)).Methods("GET") BaseRoutes.Channels.Handle("/create", ApiUserRequired(createChannel)).Methods("POST")
sr.Handle("/create", ApiUserRequired(createChannel)).Methods("POST") BaseRoutes.Channels.Handle("/create_direct", ApiUserRequired(createDirectChannel)).Methods("POST")
sr.Handle("/create_direct", ApiUserRequired(createDirectChannel)).Methods("POST") BaseRoutes.Channels.Handle("/update", ApiUserRequired(updateChannel)).Methods("POST")
sr.Handle("/update", ApiUserRequired(updateChannel)).Methods("POST") BaseRoutes.Channels.Handle("/update_header", ApiUserRequired(updateChannelHeader)).Methods("POST")
sr.Handle("/update_header", ApiUserRequired(updateChannelHeader)).Methods("POST") BaseRoutes.Channels.Handle("/update_purpose", ApiUserRequired(updateChannelPurpose)).Methods("POST")
sr.Handle("/update_purpose", ApiUserRequired(updateChannelPurpose)).Methods("POST") BaseRoutes.Channels.Handle("/update_notify_props", ApiUserRequired(updateNotifyProps)).Methods("POST")
sr.Handle("/update_notify_props", ApiUserRequired(updateNotifyProps)).Methods("POST")
sr.Handle("/{id:[A-Za-z0-9]+}/", ApiUserRequiredActivity(getChannel, false)).Methods("GET")
sr.Handle("/{id:[A-Za-z0-9]+}/extra_info", ApiUserRequired(getChannelExtraInfo)).Methods("GET")
sr.Handle("/{id:[A-Za-z0-9]+}/extra_info/{member_limit:-?[0-9]+}", ApiUserRequired(getChannelExtraInfo)).Methods("GET")
sr.Handle("/{id:[A-Za-z0-9]+}/join", ApiUserRequired(join)).Methods("POST")
sr.Handle("/{id:[A-Za-z0-9]+}/leave", ApiUserRequired(leave)).Methods("POST")
sr.Handle("/{id:[A-Za-z0-9]+}/delete", ApiUserRequired(deleteChannel)).Methods("POST")
sr.Handle("/{id:[A-Za-z0-9]+}/add", ApiUserRequired(addMember)).Methods("POST")
sr.Handle("/{id:[A-Za-z0-9]+}/remove", ApiUserRequired(removeMember)).Methods("POST")
sr.Handle("/{id:[A-Za-z0-9]+}/update_last_viewed_at", ApiUserRequired(updateLastViewedAt)).Methods("POST")
BaseRoutes.NeedChannel.Handle("/", ApiUserRequiredActivity(getChannel, false)).Methods("GET")
BaseRoutes.NeedChannel.Handle("/extra_info", ApiUserRequired(getChannelExtraInfo)).Methods("GET")
BaseRoutes.NeedChannel.Handle("/extra_info/{member_limit:-?[0-9]+}", ApiUserRequired(getChannelExtraInfo)).Methods("GET")
BaseRoutes.NeedChannel.Handle("/join", ApiUserRequired(join)).Methods("POST")
BaseRoutes.NeedChannel.Handle("/leave", ApiUserRequired(leave)).Methods("POST")
BaseRoutes.NeedChannel.Handle("/delete", ApiUserRequired(deleteChannel)).Methods("POST")
BaseRoutes.NeedChannel.Handle("/add", ApiUserRequired(addMember)).Methods("POST")
BaseRoutes.NeedChannel.Handle("/remove", ApiUserRequired(removeMember)).Methods("POST")
BaseRoutes.NeedChannel.Handle("/update_last_viewed_at", ApiUserRequired(updateLastViewedAt)).Methods("POST")
} }
func createChannel(c *Context, w http.ResponseWriter, r *http.Request) { func createChannel(c *Context, w http.ResponseWriter, r *http.Request) {
@@ -52,6 +51,10 @@ func createChannel(c *Context, w http.ResponseWriter, r *http.Request) {
return return
} }
if len(channel.TeamId) == 0 {
channel.TeamId = c.TeamId
}
if !c.HasPermissionsToTeam(channel.TeamId, "createChannel") { if !c.HasPermissionsToTeam(channel.TeamId, "createChannel") {
return return
} }
@@ -107,10 +110,6 @@ func createDirectChannel(c *Context, w http.ResponseWriter, r *http.Request) {
return return
} }
if !c.HasPermissionsToTeam(c.Session.TeamId, "createDirectChannel") {
return
}
if sc, err := CreateDirectChannel(c, userId); err != nil { if sc, err := CreateDirectChannel(c, userId); err != nil {
c.Err = err c.Err = err
return return
@@ -131,7 +130,7 @@ func CreateDirectChannel(c *Context, otherUserId string) (*model.Channel, *model
channel.DisplayName = "" channel.DisplayName = ""
channel.Name = model.GetDMNameFromIds(otherUserId, c.Session.UserId) channel.Name = model.GetDMNameFromIds(otherUserId, c.Session.UserId)
channel.TeamId = c.Session.TeamId channel.TeamId = c.TeamId
channel.Header = "" channel.Header = ""
channel.Type = model.CHANNEL_DIRECT channel.Type = model.CHANNEL_DIRECT
@@ -214,7 +213,7 @@ func updateChannel(c *Context, w http.ResponseWriter, r *http.Request) {
if oldChannel.Name == model.DEFAULT_CHANNEL { if oldChannel.Name == model.DEFAULT_CHANNEL {
if (len(channel.Name) > 0 && channel.Name != oldChannel.Name) || (len(channel.Type) > 0 && channel.Type != oldChannel.Type) { if (len(channel.Name) > 0 && channel.Name != oldChannel.Name) || (len(channel.Type) > 0 && channel.Type != oldChannel.Type) {
c.Err = model.NewLocAppError("updateChannel", "api.channel.update_channel.tried.app_error", map[string]interface{}{"Channel": model.DEFAULT_CHANNEL}, "") c.Err = model.NewLocAppError("updateChannel", "api.channel.update_channel.tried.app_error", map[string]interface{}{"Channel": model.DEFAULT_CHANNEL}, "")
c.Err.StatusCode = http.StatusForbidden c.Err.StatusCode = http.StatusBadRequest
return return
} }
} }
@@ -367,7 +366,7 @@ func getChannels(c *Context, w http.ResponseWriter, r *http.Request) {
// user is already in the team // user is already in the team
if result := <-Srv.Store.Channel().GetChannels(c.Session.TeamId, c.Session.UserId); result.Err != nil { if result := <-Srv.Store.Channel().GetChannels(c.TeamId, c.Session.UserId); result.Err != nil {
if result.Err.Id == "store.sql_channel.get_channels.not_found.app_error" { if result.Err.Id == "store.sql_channel.get_channels.not_found.app_error" {
// lets make sure the user is valid // lets make sure the user is valid
if result := <-Srv.Store.User().Get(c.Session.UserId); result.Err != nil { if result := <-Srv.Store.User().Get(c.Session.UserId); result.Err != nil {
@@ -392,7 +391,7 @@ func getMoreChannels(c *Context, w http.ResponseWriter, r *http.Request) {
// user is already in the team // user is already in the team
if result := <-Srv.Store.Channel().GetMoreChannels(c.Session.TeamId, c.Session.UserId); result.Err != nil { if result := <-Srv.Store.Channel().GetMoreChannels(c.TeamId, c.Session.UserId); result.Err != nil {
c.Err = result.Err c.Err = result.Err
return return
} else if HandleEtag(result.Data.(*model.ChannelList).Etag(), w, r) { } else if HandleEtag(result.Data.(*model.ChannelList).Etag(), w, r) {
@@ -408,7 +407,7 @@ func getChannelCounts(c *Context, w http.ResponseWriter, r *http.Request) {
// user is already in the team // user is already in the team
if result := <-Srv.Store.Channel().GetChannelCounts(c.Session.TeamId, c.Session.UserId); result.Err != nil { if result := <-Srv.Store.Channel().GetChannelCounts(c.TeamId, c.Session.UserId); result.Err != nil {
c.Err = model.NewLocAppError("getChannelCounts", "api.channel.get_channel_counts.app_error", nil, result.Err.Message) c.Err = model.NewLocAppError("getChannelCounts", "api.channel.get_channel_counts.app_error", nil, result.Err.Message)
return return
} else if HandleEtag(result.Data.(*model.ChannelCounts).Etag(), w, r) { } else if HandleEtag(result.Data.(*model.ChannelCounts).Etag(), w, r) {
@@ -423,7 +422,7 @@ func getChannelCounts(c *Context, w http.ResponseWriter, r *http.Request) {
func join(c *Context, w http.ResponseWriter, r *http.Request) { func join(c *Context, w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r) params := mux.Vars(r)
channelId := params["id"] channelId := params["channel_id"]
JoinChannel(c, channelId, "") JoinChannel(c, channelId, "")
@@ -498,7 +497,7 @@ func AddUserToChannel(user *model.User, channel *model.Channel) (*model.ChannelM
} }
go func() { go func() {
UpdateChannelAccessCache(channel.TeamId, user.Id, channel.Id) InvalidateCacheForUser(user.Id)
message := model.NewMessage(channel.TeamId, channel.Id, user.Id, model.ACTION_USER_ADDED) message := model.NewMessage(channel.TeamId, channel.Id, user.Id, model.ACTION_USER_ADDED)
PublishAndForget(message) PublishAndForget(message)
@@ -507,12 +506,12 @@ func AddUserToChannel(user *model.User, channel *model.Channel) (*model.ChannelM
return newMember, nil return newMember, nil
} }
func JoinDefaultChannels(user *model.User, channelRole string) *model.AppError { func JoinDefaultChannels(teamId string, user *model.User, channelRole string) *model.AppError {
// We don't call JoinChannel here since c.Session is not populated on user creation // We don't call JoinChannel here since c.Session is not populated on user creation
var err *model.AppError = nil var err *model.AppError = nil
if result := <-Srv.Store.Channel().GetByName(user.TeamId, "town-square"); result.Err != nil { if result := <-Srv.Store.Channel().GetByName(teamId, "town-square"); result.Err != nil {
err = result.Err err = result.Err
} else { } else {
cm := &model.ChannelMember{ChannelId: result.Data.(*model.Channel).Id, UserId: user.Id, cm := &model.ChannelMember{ChannelId: result.Data.(*model.Channel).Id, UserId: user.Id,
@@ -523,7 +522,7 @@ func JoinDefaultChannels(user *model.User, channelRole string) *model.AppError {
} }
} }
if result := <-Srv.Store.Channel().GetByName(user.TeamId, "off-topic"); result.Err != nil { if result := <-Srv.Store.Channel().GetByName(teamId, "off-topic"); result.Err != nil {
err = result.Err err = result.Err
} else { } else {
cm := &model.ChannelMember{ChannelId: result.Data.(*model.Channel).Id, UserId: user.Id, cm := &model.ChannelMember{ChannelId: result.Data.(*model.Channel).Id, UserId: user.Id,
@@ -540,7 +539,7 @@ func JoinDefaultChannels(user *model.User, channelRole string) *model.AppError {
func leave(c *Context, w http.ResponseWriter, r *http.Request) { func leave(c *Context, w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r) params := mux.Vars(r)
id := params["id"] id := params["channel_id"]
sc := Srv.Store.Channel().Get(id) sc := Srv.Store.Channel().Get(id)
uc := Srv.Store.User().Get(c.Session.UserId) uc := Srv.Store.User().Get(c.Session.UserId)
@@ -561,13 +560,13 @@ func leave(c *Context, w http.ResponseWriter, r *http.Request) {
if channel.Type == model.CHANNEL_DIRECT { if channel.Type == model.CHANNEL_DIRECT {
c.Err = model.NewLocAppError("leave", "api.channel.leave.direct.app_error", nil, "") c.Err = model.NewLocAppError("leave", "api.channel.leave.direct.app_error", nil, "")
c.Err.StatusCode = http.StatusForbidden c.Err.StatusCode = http.StatusBadRequest
return return
} }
if channel.Name == model.DEFAULT_CHANNEL { if channel.Name == model.DEFAULT_CHANNEL {
c.Err = model.NewLocAppError("leave", "api.channel.leave.default.app_error", map[string]interface{}{"Channel": model.DEFAULT_CHANNEL}, "") c.Err = model.NewLocAppError("leave", "api.channel.leave.default.app_error", map[string]interface{}{"Channel": model.DEFAULT_CHANNEL}, "")
c.Err.StatusCode = http.StatusForbidden c.Err.StatusCode = http.StatusBadRequest
return return
} }
@@ -589,7 +588,7 @@ func leave(c *Context, w http.ResponseWriter, r *http.Request) {
func deleteChannel(c *Context, w http.ResponseWriter, r *http.Request) { func deleteChannel(c *Context, w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r) params := mux.Vars(r)
id := params["id"] id := params["channel_id"]
sc := Srv.Store.Channel().Get(id) sc := Srv.Store.Channel().Get(id)
scm := Srv.Store.Channel().GetMember(id, c.Session.UserId) scm := Srv.Store.Channel().GetMember(id, c.Session.UserId)
@@ -637,7 +636,7 @@ func deleteChannel(c *Context, w http.ResponseWriter, r *http.Request) {
if channel.Name == model.DEFAULT_CHANNEL { if channel.Name == model.DEFAULT_CHANNEL {
c.Err = model.NewLocAppError("deleteChannel", "api.channel.delete_channel.cannot.app_error", map[string]interface{}{"Channel": model.DEFAULT_CHANNEL}, "") c.Err = model.NewLocAppError("deleteChannel", "api.channel.delete_channel.cannot.app_error", map[string]interface{}{"Channel": model.DEFAULT_CHANNEL}, "")
c.Err.StatusCode = http.StatusForbidden c.Err.StatusCode = http.StatusBadRequest
return return
} }
@@ -682,7 +681,7 @@ func deleteChannel(c *Context, w http.ResponseWriter, r *http.Request) {
func updateLastViewedAt(c *Context, w http.ResponseWriter, r *http.Request) { func updateLastViewedAt(c *Context, w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r) params := mux.Vars(r)
id := params["id"] id := params["channel_id"]
Srv.Store.Channel().UpdateLastViewedAt(id, c.Session.UserId) Srv.Store.Channel().UpdateLastViewedAt(id, c.Session.UserId)
@@ -695,7 +694,7 @@ func updateLastViewedAt(c *Context, w http.ResponseWriter, r *http.Request) {
Srv.Store.Preference().Save(&model.Preferences{preference}) Srv.Store.Preference().Save(&model.Preferences{preference})
message := model.NewMessage(c.Session.TeamId, id, c.Session.UserId, model.ACTION_CHANNEL_VIEWED) message := model.NewMessage(c.TeamId, id, c.Session.UserId, model.ACTION_CHANNEL_VIEWED)
message.Add("channel_id", id) message.Add("channel_id", id)
PublishAndForget(message) PublishAndForget(message)
@@ -707,9 +706,9 @@ func updateLastViewedAt(c *Context, w http.ResponseWriter, r *http.Request) {
func getChannel(c *Context, w http.ResponseWriter, r *http.Request) { func getChannel(c *Context, w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r) params := mux.Vars(r)
id := params["id"] id := params["channel_id"]
//pchan := Srv.Store.Channel().CheckPermissionsTo(c.Session.TeamId, id, c.Session.UserId) //pchan := Srv.Store.Channel().CheckPermissionsTo(c.TeamId, id, c.Session.UserId)
cchan := Srv.Store.Channel().Get(id) cchan := Srv.Store.Channel().Get(id)
cmchan := Srv.Store.Channel().GetMember(id, c.Session.UserId) cmchan := Srv.Store.Channel().GetMember(id, c.Session.UserId)
@@ -737,7 +736,7 @@ func getChannel(c *Context, w http.ResponseWriter, r *http.Request) {
func getChannelExtraInfo(c *Context, w http.ResponseWriter, r *http.Request) { func getChannelExtraInfo(c *Context, w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r) params := mux.Vars(r)
id := params["id"] id := params["channel_id"]
var memberLimit int var memberLimit int
if memberLimitString, ok := params["member_limit"]; !ok { if memberLimitString, ok := params["member_limit"]; !ok {
@@ -781,7 +780,7 @@ func getChannelExtraInfo(c *Context, w http.ResponseWriter, r *http.Request) {
extraMembers := ecmresult.Data.([]model.ExtraMember) extraMembers := ecmresult.Data.([]model.ExtraMember)
memberCount := ccmresult.Data.(int64) memberCount := ccmresult.Data.(int64)
if !c.HasPermissionsToTeam(channel.TeamId, "getChannelExtraInfo") { if len(channel.TeamId) > 0 && !c.HasPermissionsToTeam(channel.TeamId, "getChannelExtraInfo") {
return return
} }
@@ -803,7 +802,7 @@ func getChannelExtraInfo(c *Context, w http.ResponseWriter, r *http.Request) {
func addMember(c *Context, w http.ResponseWriter, r *http.Request) { func addMember(c *Context, w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r) params := mux.Vars(r)
id := params["id"] id := params["channel_id"]
data := model.MapFromJson(r.Body) data := model.MapFromJson(r.Body)
userId := data["user_id"] userId := data["user_id"]
@@ -813,7 +812,7 @@ func addMember(c *Context, w http.ResponseWriter, r *http.Request) {
return return
} }
cchan := Srv.Store.Channel().CheckPermissionsTo(c.Session.TeamId, id, c.Session.UserId) cchan := Srv.Store.Channel().CheckPermissionsTo(c.TeamId, id, c.Session.UserId)
sc := Srv.Store.Channel().Get(id) sc := Srv.Store.Channel().Get(id)
ouc := Srv.Store.User().Get(c.Session.UserId) ouc := Srv.Store.User().Get(c.Session.UserId)
nuc := Srv.Store.User().Get(userId) nuc := Srv.Store.User().Get(userId)
@@ -857,7 +856,7 @@ func addMember(c *Context, w http.ResponseWriter, r *http.Request) {
func removeMember(c *Context, w http.ResponseWriter, r *http.Request) { func removeMember(c *Context, w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r) params := mux.Vars(r)
channelId := params["id"] channelId := params["channel_id"]
data := model.MapFromJson(r.Body) data := model.MapFromJson(r.Body)
userIdToRemove := data["user_id"] userIdToRemove := data["user_id"]
@@ -914,7 +913,7 @@ func RemoveUserFromChannel(userIdToRemove string, removerUserId string, channel
return cmresult.Err return cmresult.Err
} }
UpdateChannelAccessCacheAndForget(channel.TeamId, userIdToRemove, channel.Id) InvalidateCacheForUser(userIdToRemove)
message := model.NewMessage(channel.TeamId, channel.Id, userIdToRemove, model.ACTION_USER_REMOVED) message := model.NewMessage(channel.TeamId, channel.Id, userIdToRemove, model.ACTION_USER_REMOVED)
message.Add("remover_id", removerUserId) message.Add("remover_id", removerUserId)
@@ -938,7 +937,7 @@ func updateNotifyProps(c *Context, w http.ResponseWriter, r *http.Request) {
return return
} }
cchan := Srv.Store.Channel().CheckPermissionsTo(c.Session.TeamId, channelId, c.Session.UserId) cchan := Srv.Store.Channel().CheckPermissionsTo(c.TeamId, channelId, c.Session.UserId)
if !c.HasPermissionsToUser(userId, "updateNotifyLevel") { if !c.HasPermissionsToUser(userId, "updateNotifyLevel") {
return return

Просмотреть файл

@@ -12,61 +12,47 @@ import (
const ( const (
NUM_CHANNELS = 140 NUM_CHANNELS = 140
NUM_USERS = 40
) )
func BenchmarkCreateChannel(b *testing.B) { func BenchmarkCreateChannel(b *testing.B) {
var ( th := Setup().InitBasic()
NUM_CHANNELS_RANGE = utils.Range{NUM_CHANNELS, NUM_CHANNELS}
)
team, _, _ := SetupBenchmark()
channelCreator := NewAutoChannelCreator(Client, team.Id) channelCreator := NewAutoChannelCreator(th.BasicClient, th.BasicTeam)
// Benchmark Start
b.ResetTimer() b.ResetTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
channelCreator.CreateTestChannels(NUM_CHANNELS_RANGE) channelCreator.CreateTestChannels(utils.Range{NUM_CHANNELS, NUM_CHANNELS})
} }
} }
func BenchmarkCreateDirectChannel(b *testing.B) { func BenchmarkCreateDirectChannel(b *testing.B) {
var ( th := Setup().InitBasic()
NUM_CHANNELS_RANGE = utils.Range{NUM_CHANNELS, NUM_CHANNELS}
)
team, _, _ := SetupBenchmark()
userCreator := NewAutoUserCreator(Client, team.Id) userCreator := NewAutoUserCreator(th.BasicClient, th.BasicTeam)
users, err := userCreator.CreateTestUsers(NUM_CHANNELS_RANGE) users, err := userCreator.CreateTestUsers(utils.Range{NUM_USERS, NUM_USERS})
if err == false { if err == false {
b.Fatal("Could not create users") b.Fatal("Could not create users")
} }
data := make([]map[string]string, len(users))
for i := range data {
newmap := map[string]string{
"user_id": users[i].Id,
}
data[i] = newmap
}
// Benchmark Start // Benchmark Start
b.ResetTimer() b.ResetTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
for j := 0; j < NUM_CHANNELS; j++ { for j := 0; j < NUM_USERS; j++ {
Client.CreateDirectChannel(data[j]) th.BasicClient.CreateDirectChannel(users[j].Id)
} }
} }
} }
func BenchmarkUpdateChannel(b *testing.B) { func BenchmarkUpdateChannel(b *testing.B) {
th := Setup().InitBasic()
var ( var (
NUM_CHANNELS_RANGE = utils.Range{NUM_CHANNELS, NUM_CHANNELS} NUM_CHANNELS_RANGE = utils.Range{NUM_CHANNELS, NUM_CHANNELS}
CHANNEL_HEADER_LEN = 50 CHANNEL_HEADER_LEN = 50
) )
team, _, _ := SetupBenchmark()
channelCreator := NewAutoChannelCreator(Client, team.Id) channelCreator := NewAutoChannelCreator(th.BasicClient, th.BasicTeam)
channels, valid := channelCreator.CreateTestChannels(NUM_CHANNELS_RANGE) channels, valid := channelCreator.CreateTestChannels(NUM_CHANNELS_RANGE)
if valid == false { if valid == false {
b.Fatal("Unable to create test channels") b.Fatal("Unable to create test channels")
@@ -80,7 +66,7 @@ func BenchmarkUpdateChannel(b *testing.B) {
b.ResetTimer() b.ResetTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
for j := range channels { for j := range channels {
if _, err := Client.UpdateChannel(channels[j]); err != nil { if _, err := th.BasicClient.UpdateChannel(channels[j]); err != nil {
b.Fatal(err) b.Fatal(err)
} }
} }
@@ -88,12 +74,13 @@ func BenchmarkUpdateChannel(b *testing.B) {
} }
func BenchmarkGetChannels(b *testing.B) { func BenchmarkGetChannels(b *testing.B) {
th := Setup().InitBasic()
var ( var (
NUM_CHANNELS_RANGE = utils.Range{NUM_CHANNELS, NUM_CHANNELS} NUM_CHANNELS_RANGE = utils.Range{NUM_CHANNELS, NUM_CHANNELS}
) )
team, _, _ := SetupBenchmark()
channelCreator := NewAutoChannelCreator(Client, team.Id) channelCreator := NewAutoChannelCreator(th.BasicClient, th.BasicTeam)
_, valid := channelCreator.CreateTestChannels(NUM_CHANNELS_RANGE) _, valid := channelCreator.CreateTestChannels(NUM_CHANNELS_RANGE)
if valid == false { if valid == false {
b.Fatal("Unable to create test channels") b.Fatal("Unable to create test channels")
@@ -102,17 +89,18 @@ func BenchmarkGetChannels(b *testing.B) {
// Benchmark Start // Benchmark Start
b.ResetTimer() b.ResetTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
Client.Must(Client.GetChannels("")) th.BasicClient.Must(th.BasicClient.GetChannels(""))
} }
} }
func BenchmarkGetMoreChannels(b *testing.B) { func BenchmarkGetMoreChannels(b *testing.B) {
th := Setup().InitBasic()
var ( var (
NUM_CHANNELS_RANGE = utils.Range{NUM_CHANNELS, NUM_CHANNELS} NUM_CHANNELS_RANGE = utils.Range{NUM_CHANNELS, NUM_CHANNELS}
) )
team, _, _ := SetupBenchmark()
channelCreator := NewAutoChannelCreator(Client, team.Id) channelCreator := NewAutoChannelCreator(th.BasicClient, th.BasicTeam)
_, valid := channelCreator.CreateTestChannels(NUM_CHANNELS_RANGE) _, valid := channelCreator.CreateTestChannels(NUM_CHANNELS_RANGE)
if valid == false { if valid == false {
b.Fatal("Unable to create test channels") b.Fatal("Unable to create test channels")
@@ -121,44 +109,47 @@ func BenchmarkGetMoreChannels(b *testing.B) {
// Benchmark Start // Benchmark Start
b.ResetTimer() b.ResetTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
Client.Must(Client.GetMoreChannels("")) th.BasicClient.Must(th.BasicClient.GetMoreChannels(""))
} }
} }
func BenchmarkJoinChannel(b *testing.B) { func BenchmarkJoinChannel(b *testing.B) {
th := Setup().InitBasic()
var ( var (
NUM_CHANNELS_RANGE = utils.Range{NUM_CHANNELS, NUM_CHANNELS} NUM_CHANNELS_RANGE = utils.Range{NUM_CHANNELS, NUM_CHANNELS}
) )
team, _, _ := SetupBenchmark()
channelCreator := NewAutoChannelCreator(Client, team.Id) channelCreator := NewAutoChannelCreator(th.BasicClient, th.BasicTeam)
channels, valid := channelCreator.CreateTestChannels(NUM_CHANNELS_RANGE) channels, valid := channelCreator.CreateTestChannels(NUM_CHANNELS_RANGE)
if valid == false { if valid == false {
b.Fatal("Unable to create test channels") b.Fatal("Unable to create test channels")
} }
// Secondary test user to join channels created by primary test user // Secondary test user to join channels created by primary test user
user := &model.User{TeamId: team.Id, Email: "success+" + model.NewId() + "@simulator.amazonses.com", Nickname: "That Guy", Password: "pwd"} user := &model.User{Email: "success+" + model.NewId() + "@simulator.amazonses.com", Nickname: "That Guy", Password: "pwd"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User) user = th.BasicClient.Must(th.BasicClient.CreateUser(user, "")).Data.(*model.User)
LinkUserToTeam(user, th.BasicTeam)
store.Must(Srv.Store.User().VerifyEmail(user.Id)) store.Must(Srv.Store.User().VerifyEmail(user.Id))
Client.LoginByEmail(team.Name, user.Email, "pwd") th.BasicClient.LoginByEmail(th.BasicTeam.Name, user.Email, "pwd")
// Benchmark Start // Benchmark Start
b.ResetTimer() b.ResetTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
for j := range channels { for j := range channels {
Client.Must(Client.JoinChannel(channels[j].Id)) th.BasicClient.Must(th.BasicClient.JoinChannel(channels[j].Id))
} }
} }
} }
func BenchmarkDeleteChannel(b *testing.B) { func BenchmarkDeleteChannel(b *testing.B) {
th := Setup().InitBasic()
var ( var (
NUM_CHANNELS_RANGE = utils.Range{NUM_CHANNELS, NUM_CHANNELS} NUM_CHANNELS_RANGE = utils.Range{NUM_CHANNELS, NUM_CHANNELS}
) )
team, _, _ := SetupBenchmark()
channelCreator := NewAutoChannelCreator(Client, team.Id) channelCreator := NewAutoChannelCreator(th.BasicClient, th.BasicTeam)
channels, valid := channelCreator.CreateTestChannels(NUM_CHANNELS_RANGE) channels, valid := channelCreator.CreateTestChannels(NUM_CHANNELS_RANGE)
if valid == false { if valid == false {
b.Fatal("Unable to create test channels") b.Fatal("Unable to create test channels")
@@ -168,18 +159,19 @@ func BenchmarkDeleteChannel(b *testing.B) {
b.ResetTimer() b.ResetTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
for j := range channels { for j := range channels {
Client.Must(Client.DeleteChannel(channels[j].Id)) th.BasicClient.Must(th.BasicClient.DeleteChannel(channels[j].Id))
} }
} }
} }
func BenchmarkGetChannelExtraInfo(b *testing.B) { func BenchmarkGetChannelExtraInfo(b *testing.B) {
th := Setup().InitBasic()
var ( var (
NUM_CHANNELS_RANGE = utils.Range{NUM_CHANNELS, NUM_CHANNELS} NUM_CHANNELS_RANGE = utils.Range{NUM_CHANNELS, NUM_CHANNELS}
) )
team, _, _ := SetupBenchmark()
channelCreator := NewAutoChannelCreator(Client, team.Id) channelCreator := NewAutoChannelCreator(th.BasicClient, th.BasicTeam)
channels, valid := channelCreator.CreateTestChannels(NUM_CHANNELS_RANGE) channels, valid := channelCreator.CreateTestChannels(NUM_CHANNELS_RANGE)
if valid == false { if valid == false {
b.Fatal("Unable to create test channels") b.Fatal("Unable to create test channels")
@@ -189,22 +181,23 @@ func BenchmarkGetChannelExtraInfo(b *testing.B) {
b.ResetTimer() b.ResetTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
for j := range channels { for j := range channels {
Client.Must(Client.GetChannelExtraInfo(channels[j].Id, -1, "")) th.BasicClient.Must(th.BasicClient.GetChannelExtraInfo(channels[j].Id, -1, ""))
} }
} }
} }
func BenchmarkAddChannelMember(b *testing.B) { func BenchmarkAddChannelMember(b *testing.B) {
th := Setup().InitBasic()
var ( var (
NUM_USERS = 100 NUM_USERS = 100
NUM_USERS_RANGE = utils.Range{NUM_USERS, NUM_USERS} NUM_USERS_RANGE = utils.Range{NUM_USERS, NUM_USERS}
) )
team, _, _ := SetupBenchmark()
channel := &model.Channel{DisplayName: "Test Channel", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} channel := &model.Channel{DisplayName: "Test Channel", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: th.BasicTeam.Id}
channel = Client.Must(Client.CreateChannel(channel)).Data.(*model.Channel) channel = th.BasicClient.Must(th.BasicClient.CreateChannel(channel)).Data.(*model.Channel)
userCreator := NewAutoUserCreator(Client, team.Id) userCreator := NewAutoUserCreator(th.BasicClient, th.BasicTeam)
users, valid := userCreator.CreateTestUsers(NUM_USERS_RANGE) users, valid := userCreator.CreateTestUsers(NUM_USERS_RANGE)
if valid == false { if valid == false {
b.Fatal("Unable to create test users") b.Fatal("Unable to create test users")
@@ -214,7 +207,7 @@ func BenchmarkAddChannelMember(b *testing.B) {
b.ResetTimer() b.ResetTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
for j := range users { for j := range users {
if _, err := Client.AddChannelMember(channel.Id, users[j].Id); err != nil { if _, err := th.BasicClient.AddChannelMember(channel.Id, users[j].Id); err != nil {
b.Fatal(err) b.Fatal(err)
} }
} }
@@ -223,23 +216,24 @@ func BenchmarkAddChannelMember(b *testing.B) {
// Is this benchmark failing? Raise your file ulimit! 2048 worked for me. // Is this benchmark failing? Raise your file ulimit! 2048 worked for me.
func BenchmarkRemoveChannelMember(b *testing.B) { func BenchmarkRemoveChannelMember(b *testing.B) {
th := Setup().InitBasic()
var ( var (
NUM_USERS = 140 NUM_USERS = 140
NUM_USERS_RANGE = utils.Range{NUM_USERS, NUM_USERS} NUM_USERS_RANGE = utils.Range{NUM_USERS, NUM_USERS}
) )
team, _, _ := SetupBenchmark()
channel := &model.Channel{DisplayName: "Test Channel", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} channel := &model.Channel{DisplayName: "Test Channel", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: th.BasicTeam.Id}
channel = Client.Must(Client.CreateChannel(channel)).Data.(*model.Channel) channel = th.BasicClient.Must(th.BasicClient.CreateChannel(channel)).Data.(*model.Channel)
userCreator := NewAutoUserCreator(Client, team.Id) userCreator := NewAutoUserCreator(th.BasicClient, th.BasicTeam)
users, valid := userCreator.CreateTestUsers(NUM_USERS_RANGE) users, valid := userCreator.CreateTestUsers(NUM_USERS_RANGE)
if valid == false { if valid == false {
b.Fatal("Unable to create test users") b.Fatal("Unable to create test users")
} }
for i := range users { for i := range users {
if _, err := Client.AddChannelMember(channel.Id, users[i].Id); err != nil { if _, err := th.BasicClient.AddChannelMember(channel.Id, users[i].Id); err != nil {
b.Fatal(err) b.Fatal(err)
} }
} }
@@ -248,7 +242,7 @@ func BenchmarkRemoveChannelMember(b *testing.B) {
b.ResetTimer() b.ResetTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
for j := range users { for j := range users {
if _, err := Client.RemoveChannelMember(channel.Id, users[j].Id); err != nil { if _, err := th.BasicClient.RemoveChannelMember(channel.Id, users[j].Id); err != nil {
b.Fatal(err) b.Fatal(err)
} }
} }
@@ -256,12 +250,13 @@ func BenchmarkRemoveChannelMember(b *testing.B) {
} }
func BenchmarkUpdateNotifyProps(b *testing.B) { func BenchmarkUpdateNotifyProps(b *testing.B) {
th := Setup().InitBasic()
var ( var (
NUM_CHANNELS_RANGE = utils.Range{NUM_CHANNELS, NUM_CHANNELS} NUM_CHANNELS_RANGE = utils.Range{NUM_CHANNELS, NUM_CHANNELS}
) )
team, user, _ := SetupBenchmark()
channelCreator := NewAutoChannelCreator(Client, team.Id) channelCreator := NewAutoChannelCreator(th.BasicClient, th.BasicTeam)
channels, valid := channelCreator.CreateTestChannels(NUM_CHANNELS_RANGE) channels, valid := channelCreator.CreateTestChannels(NUM_CHANNELS_RANGE)
if valid == false { if valid == false {
b.Fatal("Unable to create test channels") b.Fatal("Unable to create test channels")
@@ -272,7 +267,7 @@ func BenchmarkUpdateNotifyProps(b *testing.B) {
for i := range data { for i := range data {
newmap := map[string]string{ newmap := map[string]string{
"channel_id": channels[i].Id, "channel_id": channels[i].Id,
"user_id": user.Id, "user_id": th.BasicUser.Id,
"desktop": model.CHANNEL_NOTIFY_MENTION, "desktop": model.CHANNEL_NOTIFY_MENTION,
"mark_unread": model.CHANNEL_MARK_UNREAD_MENTION, "mark_unread": model.CHANNEL_MARK_UNREAD_MENTION,
} }
@@ -283,7 +278,7 @@ func BenchmarkUpdateNotifyProps(b *testing.B) {
b.ResetTimer() b.ResetTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
for j := range channels { for j := range channels {
Client.Must(Client.UpdateNotifyProps(data[j])) th.BasicClient.Must(th.BasicClient.UpdateNotifyProps(data[j]))
} }
} }
} }

Просмотреть файл

@@ -14,19 +14,13 @@ import (
) )
func TestCreateChannel(t *testing.T) { func TestCreateChannel(t *testing.T) {
Setup() th := Setup().InitBasic()
Client := th.BasicClient
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} team := th.BasicTeam
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team) Client.Must(Client.Logout())
team2 := th.CreateTeam(th.BasicClient)
team2 := &model.Team{DisplayName: "Name Team 2", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} th.LoginBasic()
team2 = Client.Must(Client.CreateTeam(team2)).Data.(*model.Team) th.BasicClient.SetTeamId(team.Id)
user := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user.Id))
Client.LoginByEmail(team.Name, user.Email, "pwd")
channel := model.Channel{DisplayName: "Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} channel := model.Channel{DisplayName: "Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
rchannel, err := Client.CreateChannel(&channel) rchannel, err := Client.CreateChannel(&channel)
@@ -63,7 +57,7 @@ func TestCreateChannel(t *testing.T) {
} }
} }
if _, err := Client.DoApiPost("/channels/create", "garbage"); err == nil { if _, err := Client.DoApiPost(Client.GetTeamRoute()+"/channels/create", "garbage"); err == nil {
t.Fatal("should have been an error") t.Fatal("should have been an error")
} }
@@ -94,25 +88,12 @@ func TestCreateChannel(t *testing.T) {
} }
func TestCreateDirectChannel(t *testing.T) { func TestCreateDirectChannel(t *testing.T) {
Setup() th := Setup().InitBasic()
Client := th.BasicClient
user := th.BasicUser
user2 := th.BasicUser2
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} rchannel, err := Client.CreateDirectChannel(th.BasicUser2.Id)
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
user := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user.Id))
user2 := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user2.Id))
Client.LoginByEmail(team.Name, user.Email, "pwd")
data := make(map[string]string)
data["user_id"] = user2.Id
rchannel, err := Client.CreateDirectChannel(data)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@@ -132,47 +113,31 @@ func TestCreateDirectChannel(t *testing.T) {
t.Fatal("channel type was not direct") t.Fatal("channel type was not direct")
} }
if _, err := Client.CreateDirectChannel(data); err == nil { if _, err := Client.CreateDirectChannel(th.BasicUser2.Id); err == nil {
t.Fatal("channel already exists and should have failed") t.Fatal("channel already exists and should have failed")
} }
data["user_id"] = "junk" if _, err := Client.CreateDirectChannel("junk"); err == nil {
if _, err := Client.CreateDirectChannel(data); err == nil {
t.Fatal("should have failed with bad user id") t.Fatal("should have failed with bad user id")
} }
data["user_id"] = "12345678901234567890123456" if _, err := Client.CreateDirectChannel("12345678901234567890123456"); err == nil {
if _, err := Client.CreateDirectChannel(data); err == nil {
t.Fatal("should have failed with non-existent user") t.Fatal("should have failed with non-existent user")
} }
} }
func TestUpdateChannel(t *testing.T) { func TestUpdateChannel(t *testing.T) {
Setup() th := Setup().InitBasic()
Client := th.BasicClient
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} team := th.BasicTeam
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team) user := th.BasicUser
user2 := th.CreateUser(th.BasicClient)
userTeamAdmin := &model.User{TeamId: team.Id, Email: team.Email, Nickname: "Corey Hulen", Password: "pwd"}
userTeamAdmin = Client.Must(Client.CreateUser(userTeamAdmin, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(userTeamAdmin.Id))
userChannelAdmin := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
userChannelAdmin = Client.Must(Client.CreateUser(userChannelAdmin, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(userChannelAdmin.Id))
userStd := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
userStd = Client.Must(Client.CreateUser(userStd, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(userStd.Id))
userStd.Roles = ""
Client.LoginByEmail(team.Name, userChannelAdmin.Email, "pwd")
channel1 := &model.Channel{DisplayName: "A Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} channel1 := &model.Channel{DisplayName: "A Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel) channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel)
Client.AddChannelMember(channel1.Id, userTeamAdmin.Id) Client.AddChannelMember(channel1.Id, user.Id)
header := "a" + model.NewId() + "a" header := "a" + model.NewId() + "a"
purpose := "a" + model.NewId() + "a" purpose := "a" + model.NewId() + "a"
@@ -191,25 +156,6 @@ func TestUpdateChannel(t *testing.T) {
t.Fatal("Channel admin failed to skip displayName") t.Fatal("Channel admin failed to skip displayName")
} }
Client.LoginByEmail(team.Name, userTeamAdmin.Email, "pwd")
header = "b" + model.NewId() + "b"
purpose = "b" + model.NewId() + "b"
upChannel1 = &model.Channel{Id: channel1.Id, Header: header, Purpose: purpose}
upChannel1 = Client.Must(Client.UpdateChannel(upChannel1)).Data.(*model.Channel)
if upChannel1.Header != header {
t.Fatal("Team admin failed to update header")
}
if upChannel1.Purpose != purpose {
t.Fatal("Team admin failed to update purpose")
}
if upChannel1.DisplayName != channel1.DisplayName {
t.Fatal("Team admin failed to skip displayName")
}
rget := Client.Must(Client.GetChannels("")) rget := Client.Must(Client.GetChannels(""))
data := rget.Data.(*model.ChannelList) data := rget.Data.(*model.ChannelList)
for _, c := range data.Channels { for _, c := range data.Channels {
@@ -223,7 +169,7 @@ func TestUpdateChannel(t *testing.T) {
} }
} }
Client.LoginByEmail(team.Name, userStd.Email, "pwd") Client.LoginByEmail(team.Name, user2.Email, user2.Password)
if _, err := Client.UpdateChannel(upChannel1); err == nil { if _, err := Client.UpdateChannel(upChannel1); err == nil {
t.Fatal("Standard User should have failed to update") t.Fatal("Standard User should have failed to update")
@@ -231,16 +177,9 @@ func TestUpdateChannel(t *testing.T) {
} }
func TestUpdateChannelHeader(t *testing.T) { func TestUpdateChannelHeader(t *testing.T) {
Setup() th := Setup().InitBasic()
Client := th.BasicClient
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} team := th.BasicTeam
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
user := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user.Id))
Client.LoginByEmail(team.Name, user.Email, "pwd")
channel1 := &model.Channel{DisplayName: "A Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} channel1 := &model.Channel{DisplayName: "A Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel) channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel)
@@ -276,11 +215,7 @@ func TestUpdateChannelHeader(t *testing.T) {
t.Fatal("should have errored on bad channel header") t.Fatal("should have errored on bad channel header")
} }
user2 := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"} th.LoginBasic2()
user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user2.Id))
Client.LoginByEmail(team.Name, user2.Email, "pwd")
data["channel_id"] = channel1.Id data["channel_id"] = channel1.Id
data["channel_header"] = "new header" data["channel_header"] = "new header"
@@ -290,16 +225,9 @@ func TestUpdateChannelHeader(t *testing.T) {
} }
func TestUpdateChannelPurpose(t *testing.T) { func TestUpdateChannelPurpose(t *testing.T) {
Setup() th := Setup().InitBasic()
Client := th.BasicClient
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} team := th.BasicTeam
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
user := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user.Id))
Client.LoginByEmail(team.Name, user.Email, "pwd")
channel1 := &model.Channel{DisplayName: "A Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} channel1 := &model.Channel{DisplayName: "A Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel) channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel)
@@ -335,11 +263,7 @@ func TestUpdateChannelPurpose(t *testing.T) {
t.Fatal("should have errored on bad channel purpose") t.Fatal("should have errored on bad channel purpose")
} }
user2 := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"} th.LoginBasic2()
user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user2.Id))
Client.LoginByEmail(team.Name, user2.Email, "pwd")
data["channel_id"] = channel1.Id data["channel_id"] = channel1.Id
data["channel_purpose"] = "new purpose" data["channel_purpose"] = "new purpose"
@@ -349,16 +273,9 @@ func TestUpdateChannelPurpose(t *testing.T) {
} }
func TestGetChannel(t *testing.T) { func TestGetChannel(t *testing.T) {
Setup() th := Setup().InitBasic()
Client := th.BasicClient
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} team := th.BasicTeam
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
user := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user.Id))
Client.LoginByEmail(team.Name, user.Email, "pwd")
channel1 := &model.Channel{DisplayName: "A Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} channel1 := &model.Channel{DisplayName: "A Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel) channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel)
@@ -412,16 +329,9 @@ func TestGetChannel(t *testing.T) {
} }
func TestGetMoreChannel(t *testing.T) { func TestGetMoreChannel(t *testing.T) {
Setup() th := Setup().InitBasic()
Client := th.BasicClient
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} team := th.BasicTeam
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user1.Id))
Client.LoginByEmail(team.Name, user1.Email, "pwd")
channel1 := &model.Channel{DisplayName: "A Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} channel1 := &model.Channel{DisplayName: "A Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel) channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel)
@@ -429,11 +339,7 @@ func TestGetMoreChannel(t *testing.T) {
channel2 := &model.Channel{DisplayName: "B Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} channel2 := &model.Channel{DisplayName: "B Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
channel2 = Client.Must(Client.CreateChannel(channel2)).Data.(*model.Channel) channel2 = Client.Must(Client.CreateChannel(channel2)).Data.(*model.Channel)
user2 := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"} th.LoginBasic2()
user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user2.Id))
Client.LoginByEmail(team.Name, user2.Email, "pwd")
rget := Client.Must(Client.GetMoreChannels("")) rget := Client.Must(Client.GetMoreChannels(""))
data := rget.Data.(*model.ChannelList) data := rget.Data.(*model.ChannelList)
@@ -456,16 +362,9 @@ func TestGetMoreChannel(t *testing.T) {
} }
func TestGetChannelCounts(t *testing.T) { func TestGetChannelCounts(t *testing.T) {
Setup() th := Setup().InitBasic()
Client := th.BasicClient
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} team := th.BasicTeam
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
user := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user.Id))
Client.LoginByEmail(team.Name, user.Email, "pwd")
channel1 := &model.Channel{DisplayName: "A Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} channel1 := &model.Channel{DisplayName: "A Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel) channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel)
@@ -478,11 +377,11 @@ func TestGetChannelCounts(t *testing.T) {
} else { } else {
counts := result.Data.(*model.ChannelCounts) counts := result.Data.(*model.ChannelCounts)
if len(counts.Counts) != 4 { if len(counts.Counts) != 5 {
t.Fatal("wrong number of channel counts") t.Fatal("wrong number of channel counts")
} }
if len(counts.UpdateTimes) != 4 { if len(counts.UpdateTimes) != 5 {
t.Fatal("wrong number of channel update times") t.Fatal("wrong number of channel update times")
} }
@@ -497,16 +396,9 @@ func TestGetChannelCounts(t *testing.T) {
} }
func TestJoinChannel(t *testing.T) { func TestJoinChannel(t *testing.T) {
Setup() th := Setup().InitBasic()
Client := th.BasicClient
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} team := th.BasicTeam
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user1.Id))
Client.LoginByEmail(team.Name, user1.Email, "pwd")
channel1 := &model.Channel{DisplayName: "A Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} channel1 := &model.Channel{DisplayName: "A Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel) channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel)
@@ -514,11 +406,7 @@ func TestJoinChannel(t *testing.T) {
channel3 := &model.Channel{DisplayName: "B Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_PRIVATE, TeamId: team.Id} channel3 := &model.Channel{DisplayName: "B Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_PRIVATE, TeamId: team.Id}
channel3 = Client.Must(Client.CreateChannel(channel3)).Data.(*model.Channel) channel3 = Client.Must(Client.CreateChannel(channel3)).Data.(*model.Channel)
user2 := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"} th.LoginBasic2()
user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user2.Id))
Client.LoginByEmail(team.Name, user2.Email, "pwd")
Client.Must(Client.JoinChannel(channel1.Id)) Client.Must(Client.JoinChannel(channel1.Id))
@@ -526,13 +414,10 @@ func TestJoinChannel(t *testing.T) {
t.Fatal("shouldn't be able to join secret group") t.Fatal("shouldn't be able to join secret group")
} }
data := make(map[string]string) rchannel := Client.Must(Client.CreateDirectChannel(th.BasicUser.Id)).Data.(*model.Channel)
data["user_id"] = user1.Id
rchannel := Client.Must(Client.CreateDirectChannel(data)).Data.(*model.Channel)
user3 := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
user3 = Client.Must(Client.CreateUser(user3, "")).Data.(*model.User)
user3 := th.CreateUser(th.BasicClient)
LinkUserToTeam(user3, team)
Client.LoginByEmail(team.Name, user3.Email, "pwd") Client.LoginByEmail(team.Name, user3.Email, "pwd")
if _, err := Client.JoinChannel(rchannel.Id); err == nil { if _, err := Client.JoinChannel(rchannel.Id); err == nil {
@@ -541,16 +426,9 @@ func TestJoinChannel(t *testing.T) {
} }
func TestLeaveChannel(t *testing.T) { func TestLeaveChannel(t *testing.T) {
Setup() th := Setup().InitBasic()
Client := th.BasicClient
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} team := th.BasicTeam
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user1.Id))
Client.LoginByEmail(team.Name, user1.Email, "pwd")
channel1 := &model.Channel{DisplayName: "A Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} channel1 := &model.Channel{DisplayName: "A Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel) channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel)
@@ -558,20 +436,14 @@ func TestLeaveChannel(t *testing.T) {
channel3 := &model.Channel{DisplayName: "B Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_PRIVATE, TeamId: team.Id} channel3 := &model.Channel{DisplayName: "B Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_PRIVATE, TeamId: team.Id}
channel3 = Client.Must(Client.CreateChannel(channel3)).Data.(*model.Channel) channel3 = Client.Must(Client.CreateChannel(channel3)).Data.(*model.Channel)
user2 := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"} th.LoginBasic2()
user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user2.Id))
Client.LoginByEmail(team.Name, user2.Email, "pwd")
Client.Must(Client.JoinChannel(channel1.Id)) Client.Must(Client.JoinChannel(channel1.Id))
// No error if you leave a channel you cannot see // No error if you leave a channel you cannot see
Client.Must(Client.LeaveChannel(channel3.Id)) Client.Must(Client.LeaveChannel(channel3.Id))
data := make(map[string]string) rchannel := Client.Must(Client.CreateDirectChannel(th.BasicUser.Id)).Data.(*model.Channel)
data["user_id"] = user1.Id
rchannel := Client.Must(Client.CreateDirectChannel(data)).Data.(*model.Channel)
if _, err := Client.LeaveChannel(rchannel.Id); err == nil { if _, err := Client.LeaveChannel(rchannel.Id); err == nil {
t.Fatal("should have errored, cannot leave direct channel") t.Fatal("should have errored, cannot leave direct channel")
@@ -590,20 +462,12 @@ func TestLeaveChannel(t *testing.T) {
} }
func TestDeleteChannel(t *testing.T) { func TestDeleteChannel(t *testing.T) {
Setup() th := Setup().InitBasic()
Client := th.BasicClient
team := th.BasicTeam
userTeamAdmin := th.BasicUser
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} th.LoginBasic2()
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
userTeamAdmin := &model.User{TeamId: team.Id, Email: team.Email, Nickname: "Corey Hulen", Password: "pwd"}
userTeamAdmin = Client.Must(Client.CreateUser(userTeamAdmin, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(userTeamAdmin.Id))
userChannelAdmin := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
userChannelAdmin = Client.Must(Client.CreateUser(userChannelAdmin, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(userChannelAdmin.Id))
Client.LoginByEmail(team.Name, userChannelAdmin.Email, "pwd")
channelMadeByCA := &model.Channel{DisplayName: "C Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} channelMadeByCA := &model.Channel{DisplayName: "C Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
channelMadeByCA = Client.Must(Client.CreateChannel(channelMadeByCA)).Data.(*model.Channel) channelMadeByCA = Client.Must(Client.CreateChannel(channelMadeByCA)).Data.(*model.Channel)
@@ -631,11 +495,9 @@ func TestDeleteChannel(t *testing.T) {
t.Fatal("should have failed to post to deleted channel") t.Fatal("should have failed to post to deleted channel")
} }
userStd := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"} userStd := th.CreateUser(th.BasicClient)
userStd = Client.Must(Client.CreateUser(userStd, "")).Data.(*model.User) LinkUserToTeam(userStd, team)
store.Must(Srv.Store.User().VerifyEmail(userStd.Id)) Client.LoginByEmail(team.Name, userStd.Email, userStd.Password)
Client.LoginByEmail(team.Name, userStd.Email, "pwd")
if _, err := Client.JoinChannel(channel1.Id); err == nil { if _, err := Client.JoinChannel(channel1.Id); err == nil {
t.Fatal("should have failed to join deleted channel") t.Fatal("should have failed to join deleted channel")
@@ -660,16 +522,9 @@ func TestDeleteChannel(t *testing.T) {
} }
func TestGetChannelExtraInfo(t *testing.T) { func TestGetChannelExtraInfo(t *testing.T) {
Setup() th := Setup().InitBasic()
Client := th.BasicClient
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} team := th.BasicTeam
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
user := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user.Id))
Client.LoginByEmail(team.Name, user.Email, "pwd")
channel1 := &model.Channel{DisplayName: "A Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} channel1 := &model.Channel{DisplayName: "A Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel) channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel)
@@ -701,8 +556,10 @@ func TestGetChannelExtraInfo(t *testing.T) {
Client2 := model.NewClient("http://localhost" + utils.Cfg.ServiceSettings.ListenAddress) Client2 := model.NewClient("http://localhost" + utils.Cfg.ServiceSettings.ListenAddress)
user2 := &model.User{TeamId: team.Id, Email: "success+" + model.NewId() + "@simulator.amazonses.com", Nickname: "Tester 2", Password: "pwd"} user2 := &model.User{Email: "success+" + model.NewId() + "@simulator.amazonses.com", Nickname: "Tester 2", Password: "pwd"}
user2 = Client2.Must(Client2.CreateUser(user2, "")).Data.(*model.User) user2 = Client2.Must(Client2.CreateUser(user2, "")).Data.(*model.User)
LinkUserToTeam(user2, team)
Client2.SetTeamId(team.Id)
store.Must(Srv.Store.User().VerifyEmail(user2.Id)) store.Must(Srv.Store.User().VerifyEmail(user2.Id))
Client2.LoginByEmail(team.Name, user2.Email, "pwd") Client2.LoginByEmail(team.Name, user2.Email, "pwd")
@@ -784,24 +641,14 @@ func TestGetChannelExtraInfo(t *testing.T) {
} }
func TestAddChannelMember(t *testing.T) { func TestAddChannelMember(t *testing.T) {
Setup() th := Setup().InitBasic()
Client := th.BasicClient
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} team := th.BasicTeam
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team) user2 := th.BasicUser2
user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user1.Id))
Client.LoginByEmail(team.Name, user1.Email, "pwd")
channel1 := &model.Channel{DisplayName: "A Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} channel1 := &model.Channel{DisplayName: "A Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel) channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel)
user2 := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user2.Id))
if _, err := Client.AddChannelMember(channel1.Id, user2.Id); err != nil { if _, err := Client.AddChannelMember(channel1.Id, user2.Id); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@@ -825,13 +672,13 @@ func TestAddChannelMember(t *testing.T) {
channel2 := &model.Channel{DisplayName: "A Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} channel2 := &model.Channel{DisplayName: "A Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
channel2 = Client.Must(Client.CreateChannel(channel2)).Data.(*model.Channel) channel2 = Client.Must(Client.CreateChannel(channel2)).Data.(*model.Channel)
Client.LoginByEmail(team.Name, user2.Email, "pwd") th.LoginBasic2()
if _, err := Client.AddChannelMember(channel2.Id, user2.Id); err == nil { if _, err := Client.AddChannelMember(channel2.Id, user2.Id); err == nil {
t.Fatal("Should have errored, user not in channel") t.Fatal("Should have errored, user not in channel")
} }
Client.LoginByEmail(team.Name, user1.Email, "pwd") th.LoginBasic()
Client.Must(Client.DeleteChannel(channel2.Id)) Client.Must(Client.DeleteChannel(channel2.Id))
@@ -842,34 +689,24 @@ func TestAddChannelMember(t *testing.T) {
} }
func TestRemoveChannelMember(t *testing.T) { func TestRemoveChannelMember(t *testing.T) {
Setup() th := Setup().InitBasic()
Client := th.BasicClient
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} team := th.BasicTeam
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team) user2 := th.BasicUser2
UpdateUserToTeamAdmin(user2, team)
userTeamAdmin := &model.User{TeamId: team.Id, Email: team.Email, Nickname: "Corey Hulen", Password: "pwd"}
userTeamAdmin = Client.Must(Client.CreateUser(userTeamAdmin, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(userTeamAdmin.Id))
userChannelAdmin := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
userChannelAdmin = Client.Must(Client.CreateUser(userChannelAdmin, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(userChannelAdmin.Id))
Client.LoginByEmail(team.Name, userChannelAdmin.Email, "pwd")
channelMadeByCA := &model.Channel{DisplayName: "A Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} channelMadeByCA := &model.Channel{DisplayName: "A Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
channelMadeByCA = Client.Must(Client.CreateChannel(channelMadeByCA)).Data.(*model.Channel) channelMadeByCA = Client.Must(Client.CreateChannel(channelMadeByCA)).Data.(*model.Channel)
Client.Must(Client.AddChannelMember(channelMadeByCA.Id, userTeamAdmin.Id)) Client.Must(Client.AddChannelMember(channelMadeByCA.Id, user2.Id))
Client.LoginByEmail(team.Name, userTeamAdmin.Email, "pwd") th.LoginBasic2()
channel1 := &model.Channel{DisplayName: "A Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} channel1 := &model.Channel{DisplayName: "A Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel) channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel)
userStd := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"} userStd := th.CreateUser(th.BasicClient)
userStd = Client.Must(Client.CreateUser(userStd, "")).Data.(*model.User) LinkUserToTeam(userStd, team)
store.Must(Srv.Store.User().VerifyEmail(userStd.Id))
Client.Must(Client.AddChannelMember(channel1.Id, userStd.Id)) Client.Must(Client.AddChannelMember(channel1.Id, userStd.Id))
@@ -894,13 +731,13 @@ func TestRemoveChannelMember(t *testing.T) {
channel2 := &model.Channel{DisplayName: "A Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} channel2 := &model.Channel{DisplayName: "A Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
channel2 = Client.Must(Client.CreateChannel(channel2)).Data.(*model.Channel) channel2 = Client.Must(Client.CreateChannel(channel2)).Data.(*model.Channel)
Client.LoginByEmail(team.Name, userStd.Email, "pwd") Client.LoginByEmail(team.Name, userStd.Email, userStd.Password)
if _, err := Client.RemoveChannelMember(channel2.Id, userStd.Id); err == nil { if _, err := Client.RemoveChannelMember(channel2.Id, userStd.Id); err == nil {
t.Fatal("Should have errored, user not channel admin") t.Fatal("Should have errored, user not channel admin")
} }
Client.LoginByEmail(team.Name, userTeamAdmin.Email, "pwd") th.LoginBasic2()
Client.Must(Client.AddChannelMember(channel2.Id, userStd.Id)) Client.Must(Client.AddChannelMember(channel2.Id, userStd.Id))
Client.Must(Client.DeleteChannel(channel2.Id)) Client.Must(Client.DeleteChannel(channel2.Id))
@@ -912,16 +749,11 @@ func TestRemoveChannelMember(t *testing.T) {
} }
func TestUpdateNotifyProps(t *testing.T) { func TestUpdateNotifyProps(t *testing.T) {
Setup() th := Setup().InitBasic()
Client := th.BasicClient
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} team := th.BasicTeam
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team) user := th.BasicUser
user2 := th.BasicUser2
user := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user.Id))
Client.LoginByEmail(team.Name, user.Email, "pwd")
channel1 := &model.Channel{DisplayName: "A Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} channel1 := &model.Channel{DisplayName: "A Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel) channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel)
@@ -1019,10 +851,7 @@ func TestUpdateNotifyProps(t *testing.T) {
t.Fatal("Should have errored - bad mark unread level") t.Fatal("Should have errored - bad mark unread level")
} }
user2 := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"} th.LoginBasic2()
user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User)
Client.LoginByEmail(team.Name, user2.Email, "pwd")
data["channel_id"] = channel1.Id data["channel_id"] = channel1.Id
data["user_id"] = user2.Id data["user_id"] = user2.Id
@@ -1034,16 +863,9 @@ func TestUpdateNotifyProps(t *testing.T) {
} }
func TestFuzzyChannel(t *testing.T) { func TestFuzzyChannel(t *testing.T) {
Setup() th := Setup().InitBasic()
Client := th.BasicClient
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} team := th.BasicTeam
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
user := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user.Id))
Client.LoginByEmail(team.Name, user.Email, "pwd")
// Strings that should pass as acceptable channel names // Strings that should pass as acceptable channel names
var fuzzyStringsPass = []string{ var fuzzyStringsPass = []string{

Просмотреть файл

@@ -12,7 +12,7 @@ import (
"strings" "strings"
l4g "github.com/alecthomas/log4go" l4g "github.com/alecthomas/log4go"
"github.com/gorilla/mux"
"github.com/mattermost/platform/model" "github.com/mattermost/platform/model"
"github.com/mattermost/platform/utils" "github.com/mattermost/platform/utils"
) )
@@ -38,23 +38,21 @@ func GetCommandProvider(name string) CommandProvider {
return nil return nil
} }
func InitCommand(r *mux.Router) { func InitCommand() {
l4g.Debug(utils.T("api.command.init.debug")) l4g.Debug(utils.T("api.command.init.debug"))
sr := r.PathPrefix("/commands").Subrouter() BaseRoutes.Commands.Handle("/execute", ApiUserRequired(executeCommand)).Methods("POST")
BaseRoutes.Commands.Handle("/list", ApiUserRequired(listCommands)).Methods("GET")
sr.Handle("/execute", ApiUserRequired(executeCommand)).Methods("POST") BaseRoutes.Commands.Handle("/create", ApiUserRequired(createCommand)).Methods("POST")
sr.Handle("/list", ApiUserRequired(listCommands)).Methods("GET") BaseRoutes.Commands.Handle("/list_team_commands", ApiUserRequired(listTeamCommands)).Methods("GET")
BaseRoutes.Commands.Handle("/regen_token", ApiUserRequired(regenCommandToken)).Methods("POST")
BaseRoutes.Commands.Handle("/delete", ApiUserRequired(deleteCommand)).Methods("POST")
sr.Handle("/create", ApiUserRequired(createCommand)).Methods("POST") BaseRoutes.Teams.Handle("/command_test", ApiAppHandler(testCommand)).Methods("POST")
sr.Handle("/list_team_commands", ApiUserRequired(listTeamCommands)).Methods("GET") BaseRoutes.Teams.Handle("/command_test", ApiAppHandler(testCommand)).Methods("GET")
sr.Handle("/regen_token", ApiUserRequired(regenCommandToken)).Methods("POST") BaseRoutes.Teams.Handle("/command_test_e", ApiAppHandler(testEphemeralCommand)).Methods("POST")
sr.Handle("/delete", ApiUserRequired(deleteCommand)).Methods("POST") BaseRoutes.Teams.Handle("/command_test_e", ApiAppHandler(testEphemeralCommand)).Methods("GET")
sr.Handle("/test", ApiAppHandler(testCommand)).Methods("POST")
sr.Handle("/test", ApiAppHandler(testCommand)).Methods("GET")
sr.Handle("/test_e", ApiAppHandler(testEphemeralCommand)).Methods("POST")
sr.Handle("/test_e", ApiAppHandler(testEphemeralCommand)).Methods("GET")
} }
func listCommands(c *Context, w http.ResponseWriter, r *http.Request) { func listCommands(c *Context, w http.ResponseWriter, r *http.Request) {
@@ -70,7 +68,7 @@ func listCommands(c *Context, w http.ResponseWriter, r *http.Request) {
} }
if *utils.Cfg.ServiceSettings.EnableCommands { if *utils.Cfg.ServiceSettings.EnableCommands {
if result := <-Srv.Store.Command().GetByTeam(c.Session.TeamId); result.Err != nil { if result := <-Srv.Store.Command().GetByTeam(c.TeamId); result.Err != nil {
c.Err = result.Err c.Err = result.Err
return return
} else { } else {
@@ -99,7 +97,7 @@ func executeCommand(c *Context, w http.ResponseWriter, r *http.Request) {
} }
if len(channelId) > 0 { if len(channelId) > 0 {
cchan := Srv.Store.Channel().CheckPermissionsTo(c.Session.TeamId, channelId, c.Session.UserId) cchan := Srv.Store.Channel().CheckPermissionsTo(c.TeamId, channelId, c.Session.UserId)
if !c.HasPermissionsToChannel(cchan, "checkCommand") { if !c.HasPermissionsToChannel(cchan, "checkCommand") {
return return
@@ -124,10 +122,10 @@ func executeCommand(c *Context, w http.ResponseWriter, r *http.Request) {
} }
chanChan := Srv.Store.Channel().Get(channelId) chanChan := Srv.Store.Channel().Get(channelId)
teamChan := Srv.Store.Team().Get(c.Session.TeamId) teamChan := Srv.Store.Team().Get(c.TeamId)
userChan := Srv.Store.User().Get(c.Session.UserId) userChan := Srv.Store.User().Get(c.Session.UserId)
if result := <-Srv.Store.Command().GetByTeam(c.Session.TeamId); result.Err != nil { if result := <-Srv.Store.Command().GetByTeam(c.TeamId); result.Err != nil {
c.Err = result.Err c.Err = result.Err
return return
} else { } else {
@@ -254,7 +252,7 @@ func handleResponse(c *Context, w http.ResponseWriter, response *model.CommandRe
post.Message = response.Text post.Message = response.Text
post.CreateAt = model.GetMillis() post.CreateAt = model.GetMillis()
SendEphemeralPost( SendEphemeralPost(
c.Session.TeamId, c.TeamId,
c.Session.UserId, c.Session.UserId,
post, post,
) )
@@ -288,7 +286,7 @@ func createCommand(c *Context, w http.ResponseWriter, r *http.Request) {
} }
cmd.CreatorId = c.Session.UserId cmd.CreatorId = c.Session.UserId
cmd.TeamId = c.Session.TeamId cmd.TeamId = c.TeamId
if result := <-Srv.Store.Command().Save(cmd); result.Err != nil { if result := <-Srv.Store.Command().Save(cmd); result.Err != nil {
c.Err = result.Err c.Err = result.Err
@@ -315,7 +313,7 @@ func listTeamCommands(c *Context, w http.ResponseWriter, r *http.Request) {
} }
} }
if result := <-Srv.Store.Command().GetByTeam(c.Session.TeamId); result.Err != nil { if result := <-Srv.Store.Command().GetByTeam(c.TeamId); result.Err != nil {
c.Err = result.Err c.Err = result.Err
return return
} else { } else {
@@ -356,7 +354,7 @@ func regenCommandToken(c *Context, w http.ResponseWriter, r *http.Request) {
} else { } else {
cmd = result.Data.(*model.Command) cmd = result.Data.(*model.Command)
if c.Session.TeamId != cmd.TeamId || (c.Session.UserId != cmd.CreatorId && !c.IsTeamAdmin()) { if c.TeamId != cmd.TeamId || (c.Session.UserId != cmd.CreatorId && !c.IsTeamAdmin()) {
c.LogAudit("fail - inappropriate permissions") c.LogAudit("fail - inappropriate permissions")
c.Err = model.NewLocAppError("regenToken", "api.command.regen.app_error", nil, "user_id="+c.Session.UserId) c.Err = model.NewLocAppError("regenToken", "api.command.regen.app_error", nil, "user_id="+c.Session.UserId)
return return
@@ -402,7 +400,7 @@ func deleteCommand(c *Context, w http.ResponseWriter, r *http.Request) {
c.Err = result.Err c.Err = result.Err
return return
} else { } else {
if c.Session.TeamId != result.Data.(*model.Command).TeamId || (c.Session.UserId != result.Data.(*model.Command).CreatorId && !c.IsTeamAdmin()) { if c.TeamId != result.Data.(*model.Command).TeamId || (c.Session.UserId != result.Data.(*model.Command).CreatorId && !c.IsTeamAdmin()) {
c.LogAudit("fail - inappropriate permissions") c.LogAudit("fail - inappropriate permissions")
c.Err = model.NewLocAppError("deleteCommand", "api.command.delete.app_error", nil, "user_id="+c.Session.UserId) c.Err = model.NewLocAppError("deleteCommand", "api.command.delete.app_error", nil, "user_id="+c.Session.UserId)
return return

Просмотреть файл

@@ -8,23 +8,12 @@ import (
"time" "time"
"github.com/mattermost/platform/model" "github.com/mattermost/platform/model"
"github.com/mattermost/platform/store"
) )
func TestEchoCommand(t *testing.T) { func TestEchoCommand(t *testing.T) {
Setup() th := Setup().InitBasic()
Client := th.BasicClient
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} channel1 := th.BasicChannel
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey+test@test.com", Nickname: "Corey Hulen", Password: "pwd"}
user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user1.Id))
Client.LoginByEmail(team.Name, user1.Email, "pwd")
channel1 := &model.Channel{DisplayName: "AA", Name: "aa" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel)
echoTestString := "/echo test" echoTestString := "/echo test"
@@ -36,7 +25,7 @@ func TestEchoCommand(t *testing.T) {
time.Sleep(100 * time.Millisecond) time.Sleep(100 * time.Millisecond)
p1 := Client.Must(Client.GetPosts(channel1.Id, 0, 2, "")).Data.(*model.PostList) p1 := Client.Must(Client.GetPosts(channel1.Id, 0, 2, "")).Data.(*model.PostList)
if len(p1.Order) != 1 { if len(p1.Order) != 2 {
t.Fatal("Echo command failed to send") t.Fatal("Echo command failed to send")
} }
} }

Просмотреть файл

@@ -33,7 +33,7 @@ func (me *JoinProvider) GetCommand(c *Context) *model.Command {
} }
func (me *JoinProvider) DoCommand(c *Context, channelId string, message string) *model.CommandResponse { func (me *JoinProvider) DoCommand(c *Context, channelId string, message string) *model.CommandResponse {
if result := <-Srv.Store.Channel().GetMoreChannels(c.Session.TeamId, c.Session.UserId); result.Err != nil { if result := <-Srv.Store.Channel().GetMoreChannels(c.TeamId, c.Session.UserId); result.Err != nil {
return &model.CommandResponse{Text: c.T("api.command_join.list.app_error"), ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL} return &model.CommandResponse{Text: c.T("api.command_join.list.app_error"), ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}
} else { } else {
channels := result.Data.(*model.ChannelList) channels := result.Data.(*model.ChannelList)

Просмотреть файл

@@ -8,20 +8,13 @@ import (
"testing" "testing"
"github.com/mattermost/platform/model" "github.com/mattermost/platform/model"
"github.com/mattermost/platform/store"
) )
func TestJoinCommands(t *testing.T) { func TestJoinCommands(t *testing.T) {
Setup() th := Setup().InitBasic()
Client := th.BasicClient
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} team := th.BasicTeam
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team) user2 := th.BasicUser2
user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey+test@test.com", Nickname: "Corey Hulen", Password: "pwd"}
user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user1.Id))
Client.LoginByEmail(team.Name, user1.Email, "pwd")
channel0 := &model.Channel{DisplayName: "00", Name: "00" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} channel0 := &model.Channel{DisplayName: "00", Name: "00" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
channel0 = Client.Must(Client.CreateChannel(channel0)).Data.(*model.Channel) channel0 = Client.Must(Client.CreateChannel(channel0)).Data.(*model.Channel)
@@ -34,13 +27,7 @@ func TestJoinCommands(t *testing.T) {
channel2 = Client.Must(Client.CreateChannel(channel2)).Data.(*model.Channel) channel2 = Client.Must(Client.CreateChannel(channel2)).Data.(*model.Channel)
Client.Must(Client.LeaveChannel(channel2.Id)) Client.Must(Client.LeaveChannel(channel2.Id))
user2 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey+test@test.com", Nickname: "Corey Hulen", Password: "pwd"} channel3 := Client.Must(Client.CreateDirectChannel(user2.Id)).Data.(*model.Channel)
user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user1.Id))
data := make(map[string]string)
data["user_id"] = user2.Id
channel3 := Client.Must(Client.CreateDirectChannel(data)).Data.(*model.Channel)
rs5 := Client.Must(Client.Command(channel0.Id, "/join "+channel2.Name, false)).Data.(*model.CommandResponse) rs5 := Client.Must(Client.Command(channel0.Id, "/join "+channel2.Name, false)).Data.(*model.CommandResponse)
if !strings.HasSuffix(rs5.GotoLocation, "/"+team.Name+"/channels/"+channel2.Name) { if !strings.HasSuffix(rs5.GotoLocation, "/"+team.Name+"/channels/"+channel2.Name) {
@@ -54,7 +41,7 @@ func TestJoinCommands(t *testing.T) {
c1 := Client.Must(Client.GetChannels("")).Data.(*model.ChannelList) c1 := Client.Must(Client.GetChannels("")).Data.(*model.ChannelList)
if len(c1.Channels) != 5 { // 4 because of town-square, off-topic and direct if len(c1.Channels) != 6 { // 4 because of town-square, off-topic and direct
t.Fatal("didn't join channel") t.Fatal("didn't join channel")
} }

Просмотреть файл

@@ -182,10 +182,19 @@ func (me *LoadTestProvider) SetupCommand(c *Context, channelId string, message s
} }
} }
} else { } else {
var team *model.Team
if tr := <-Srv.Store.Team().Get(c.TeamId); tr.Err != nil {
return &model.CommandResponse{Text: "Failed to create testing environment", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}
} else {
team = tr.Data.(*model.Team)
}
client.MockSession(c.Session.Token) client.MockSession(c.Session.Token)
client.SetTeamId(c.TeamId)
CreateTestEnvironmentInTeam( CreateTestEnvironmentInTeam(
client, client,
c.Session.TeamId, team,
utils.Range{numChannels, numChannels}, utils.Range{numChannels, numChannels},
utils.Range{numUsers, numUsers}, utils.Range{numUsers, numUsers},
utils.Range{numPosts, numPosts}, utils.Range{numPosts, numPosts},
@@ -209,8 +218,16 @@ func (me *LoadTestProvider) UsersCommand(c *Context, channelId string, message s
usersr = utils.Range{2, 5} usersr = utils.Range{2, 5}
} }
var team *model.Team
if tr := <-Srv.Store.Team().Get(c.TeamId); tr.Err != nil {
return &model.CommandResponse{Text: "Failed to create testing environment", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}
} else {
team = tr.Data.(*model.Team)
}
client := model.NewClient(c.GetSiteURL()) client := model.NewClient(c.GetSiteURL())
userCreator := NewAutoUserCreator(client, c.Session.TeamId) client.SetTeamId(team.Id)
userCreator := NewAutoUserCreator(client, team)
userCreator.Fuzzy = doFuzz userCreator.Fuzzy = doFuzz
userCreator.CreateTestUsers(usersr) userCreator.CreateTestUsers(usersr)
@@ -230,9 +247,18 @@ func (me *LoadTestProvider) ChannelsCommand(c *Context, channelId string, messag
if err == false { if err == false {
channelsr = utils.Range{2, 5} channelsr = utils.Range{2, 5}
} }
var team *model.Team
if tr := <-Srv.Store.Team().Get(c.TeamId); tr.Err != nil {
return &model.CommandResponse{Text: "Failed to create testing environment", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}
} else {
team = tr.Data.(*model.Team)
}
client := model.NewClient(c.GetSiteURL()) client := model.NewClient(c.GetSiteURL())
client.SetTeamId(team.Id)
client.MockSession(c.Session.Token) client.MockSession(c.Session.Token)
channelCreator := NewAutoChannelCreator(client, c.Session.TeamId) channelCreator := NewAutoChannelCreator(client, team)
channelCreator.Fuzzy = doFuzz channelCreator.Fuzzy = doFuzz
channelCreator.CreateTestChannels(channelsr) channelCreator.CreateTestChannels(channelsr)
@@ -262,7 +288,7 @@ func (me *LoadTestProvider) PostsCommand(c *Context, channelId string, message s
} }
var usernames []string var usernames []string
if result := <-Srv.Store.User().GetProfiles(c.Session.TeamId); result.Err == nil { if result := <-Srv.Store.User().GetProfiles(c.TeamId); result.Err == nil {
profileUsers := result.Data.(map[string]*model.User) profileUsers := result.Data.(map[string]*model.User)
usernames = make([]string, len(profileUsers)) usernames = make([]string, len(profileUsers))
i := 0 i := 0
@@ -273,6 +299,7 @@ func (me *LoadTestProvider) PostsCommand(c *Context, channelId string, message s
} }
client := model.NewClient(c.GetSiteURL()) client := model.NewClient(c.GetSiteURL())
client.SetTeamId(c.TeamId)
client.MockSession(c.Session.Token) client.MockSession(c.Session.Token)
testPoster := NewAutoPostCreator(client, channelId) testPoster := NewAutoPostCreator(client, channelId)
testPoster.Fuzzy = doFuzz testPoster.Fuzzy = doFuzz

Просмотреть файл

@@ -9,12 +9,14 @@ import (
"time" "time"
"github.com/mattermost/platform/model" "github.com/mattermost/platform/model"
"github.com/mattermost/platform/store"
"github.com/mattermost/platform/utils" "github.com/mattermost/platform/utils"
) )
func TestLoadTestHelpCommands(t *testing.T) { func TestLoadTestHelpCommands(t *testing.T) {
Setup() th := Setup().InitBasic()
Client := th.BasicClient
channel := th.BasicChannel
// enable testing to use /loadtest but don't save it since we don't want to overwrite config.json // enable testing to use /loadtest but don't save it since we don't want to overwrite config.json
enableTesting := utils.Cfg.ServiceSettings.EnableTesting enableTesting := utils.Cfg.ServiceSettings.EnableTesting
defer func() { defer func() {
@@ -23,18 +25,6 @@ func TestLoadTestHelpCommands(t *testing.T) {
utils.Cfg.ServiceSettings.EnableTesting = true utils.Cfg.ServiceSettings.EnableTesting = true
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN}
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey+test@test.com", Nickname: "Corey Hulen", Password: "pwd"}
user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user1.Id))
Client.LoginByEmail(team.Name, user1.Email, "pwd")
channel := &model.Channel{DisplayName: "00", Name: "00" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
channel = Client.Must(Client.CreateChannel(channel)).Data.(*model.Channel)
rs := Client.Must(Client.Command(channel.Id, "/loadtest help", false)).Data.(*model.CommandResponse) rs := Client.Must(Client.Command(channel.Id, "/loadtest help", false)).Data.(*model.CommandResponse)
if !strings.Contains(rs.Text, "Mattermost load testing commands to help") { if !strings.Contains(rs.Text, "Mattermost load testing commands to help") {
t.Fatal(rs.Text) t.Fatal(rs.Text)
@@ -44,7 +34,10 @@ func TestLoadTestHelpCommands(t *testing.T) {
} }
func TestLoadTestSetupCommands(t *testing.T) { func TestLoadTestSetupCommands(t *testing.T) {
Setup() th := Setup().InitBasic()
Client := th.BasicClient
channel := th.BasicChannel
// enable testing to use /loadtest but don't save it since we don't want to overwrite config.json // enable testing to use /loadtest but don't save it since we don't want to overwrite config.json
enableTesting := utils.Cfg.ServiceSettings.EnableTesting enableTesting := utils.Cfg.ServiceSettings.EnableTesting
defer func() { defer func() {
@@ -53,18 +46,6 @@ func TestLoadTestSetupCommands(t *testing.T) {
utils.Cfg.ServiceSettings.EnableTesting = true utils.Cfg.ServiceSettings.EnableTesting = true
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN}
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey+test@test.com", Nickname: "Corey Hulen", Password: "pwd"}
user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user1.Id))
Client.LoginByEmail(team.Name, user1.Email, "pwd")
channel := &model.Channel{DisplayName: "00", Name: "00" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
channel = Client.Must(Client.CreateChannel(channel)).Data.(*model.Channel)
rs := Client.Must(Client.Command(channel.Id, "/loadtest setup fuzz 1 1 1", false)).Data.(*model.CommandResponse) rs := Client.Must(Client.Command(channel.Id, "/loadtest setup fuzz 1 1 1", false)).Data.(*model.CommandResponse)
if rs.Text != "Creating enviroment..." { if rs.Text != "Creating enviroment..." {
t.Fatal(rs.Text) t.Fatal(rs.Text)
@@ -74,7 +55,10 @@ func TestLoadTestSetupCommands(t *testing.T) {
} }
func TestLoadTestUsersCommands(t *testing.T) { func TestLoadTestUsersCommands(t *testing.T) {
Setup() th := Setup().InitBasic()
Client := th.BasicClient
channel := th.BasicChannel
// enable testing to use /loadtest but don't save it since we don't want to overwrite config.json // enable testing to use /loadtest but don't save it since we don't want to overwrite config.json
enableTesting := utils.Cfg.ServiceSettings.EnableTesting enableTesting := utils.Cfg.ServiceSettings.EnableTesting
defer func() { defer func() {
@@ -83,18 +67,6 @@ func TestLoadTestUsersCommands(t *testing.T) {
utils.Cfg.ServiceSettings.EnableTesting = true utils.Cfg.ServiceSettings.EnableTesting = true
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN}
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey+test@test.com", Nickname: "Corey Hulen", Password: "pwd"}
user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user1.Id))
Client.LoginByEmail(team.Name, user1.Email, "pwd")
channel := &model.Channel{DisplayName: "00", Name: "00" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
channel = Client.Must(Client.CreateChannel(channel)).Data.(*model.Channel)
rs := Client.Must(Client.Command(channel.Id, "/loadtest users fuzz 1 2", false)).Data.(*model.CommandResponse) rs := Client.Must(Client.Command(channel.Id, "/loadtest users fuzz 1 2", false)).Data.(*model.CommandResponse)
if rs.Text != "Adding users..." { if rs.Text != "Adding users..." {
t.Fatal(rs.Text) t.Fatal(rs.Text)
@@ -104,7 +76,10 @@ func TestLoadTestUsersCommands(t *testing.T) {
} }
func TestLoadTestChannelsCommands(t *testing.T) { func TestLoadTestChannelsCommands(t *testing.T) {
Setup() th := Setup().InitBasic()
Client := th.BasicClient
channel := th.BasicChannel
// enable testing to use /loadtest but don't save it since we don't want to overwrite config.json // enable testing to use /loadtest but don't save it since we don't want to overwrite config.json
enableTesting := utils.Cfg.ServiceSettings.EnableTesting enableTesting := utils.Cfg.ServiceSettings.EnableTesting
defer func() { defer func() {
@@ -113,18 +88,6 @@ func TestLoadTestChannelsCommands(t *testing.T) {
utils.Cfg.ServiceSettings.EnableTesting = true utils.Cfg.ServiceSettings.EnableTesting = true
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN}
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey+test@test.com", Nickname: "Corey Hulen", Password: "pwd"}
user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user1.Id))
Client.LoginByEmail(team.Name, user1.Email, "pwd")
channel := &model.Channel{DisplayName: "00", Name: "00" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
channel = Client.Must(Client.CreateChannel(channel)).Data.(*model.Channel)
rs := Client.Must(Client.Command(channel.Id, "/loadtest channels fuzz 1 2", false)).Data.(*model.CommandResponse) rs := Client.Must(Client.Command(channel.Id, "/loadtest channels fuzz 1 2", false)).Data.(*model.CommandResponse)
if rs.Text != "Adding channels..." { if rs.Text != "Adding channels..." {
t.Fatal(rs.Text) t.Fatal(rs.Text)
@@ -134,7 +97,10 @@ func TestLoadTestChannelsCommands(t *testing.T) {
} }
func TestLoadTestPostsCommands(t *testing.T) { func TestLoadTestPostsCommands(t *testing.T) {
Setup() th := Setup().InitBasic()
Client := th.BasicClient
channel := th.BasicChannel
// enable testing to use /loadtest but don't save it since we don't want to overwrite config.json // enable testing to use /loadtest but don't save it since we don't want to overwrite config.json
enableTesting := utils.Cfg.ServiceSettings.EnableTesting enableTesting := utils.Cfg.ServiceSettings.EnableTesting
defer func() { defer func() {
@@ -143,18 +109,6 @@ func TestLoadTestPostsCommands(t *testing.T) {
utils.Cfg.ServiceSettings.EnableTesting = true utils.Cfg.ServiceSettings.EnableTesting = true
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN}
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey+test@test.com", Nickname: "Corey Hulen", Password: "pwd"}
user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user1.Id))
Client.LoginByEmail(team.Name, user1.Email, "pwd")
channel := &model.Channel{DisplayName: "00", Name: "00" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
channel = Client.Must(Client.CreateChannel(channel)).Data.(*model.Channel)
rs := Client.Must(Client.Command(channel.Id, "/loadtest posts fuzz 2 3 2", false)).Data.(*model.CommandResponse) rs := Client.Must(Client.Command(channel.Id, "/loadtest posts fuzz 2 3 2", false)).Data.(*model.CommandResponse)
if rs.Text != "Adding posts..." { if rs.Text != "Adding posts..." {
t.Fatal(rs.Text) t.Fatal(rs.Text)
@@ -164,7 +118,10 @@ func TestLoadTestPostsCommands(t *testing.T) {
} }
func TestLoadTestUrlCommands(t *testing.T) { func TestLoadTestUrlCommands(t *testing.T) {
Setup() th := Setup().InitBasic()
Client := th.BasicClient
channel := th.BasicChannel
// enable testing to use /loadtest but don't save it since we don't want to overwrite config.json // enable testing to use /loadtest but don't save it since we don't want to overwrite config.json
enableTesting := utils.Cfg.ServiceSettings.EnableTesting enableTesting := utils.Cfg.ServiceSettings.EnableTesting
defer func() { defer func() {
@@ -173,18 +130,6 @@ func TestLoadTestUrlCommands(t *testing.T) {
utils.Cfg.ServiceSettings.EnableTesting = true utils.Cfg.ServiceSettings.EnableTesting = true
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN}
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey+test@test.com", Nickname: "Corey Hulen", Password: "pwd"}
user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user1.Id))
Client.LoginByEmail(team.Name, user1.Email, "pwd")
channel := &model.Channel{DisplayName: "00", Name: "00" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
channel = Client.Must(Client.CreateChannel(channel)).Data.(*model.Channel)
command := "/loadtest url " command := "/loadtest url "
if r := Client.Must(Client.Command(channel.Id, command, false)).Data.(*model.CommandResponse); r.Text != "Command must contain a url" { if r := Client.Must(Client.Command(channel.Id, command, false)).Data.(*model.CommandResponse); r.Text != "Command must contain a url" {
t.Fatal("/loadtest url with no url should've failed") t.Fatal("/loadtest url with no url should've failed")
@@ -223,7 +168,10 @@ func TestLoadTestUrlCommands(t *testing.T) {
} }
func TestLoadTestJsonCommands(t *testing.T) { func TestLoadTestJsonCommands(t *testing.T) {
Setup() th := Setup().InitBasic()
Client := th.BasicClient
channel := th.BasicChannel
// enable testing to use /loadtest but don't save it since we don't want to overwrite config.json // enable testing to use /loadtest but don't save it since we don't want to overwrite config.json
enableTesting := utils.Cfg.ServiceSettings.EnableTesting enableTesting := utils.Cfg.ServiceSettings.EnableTesting
defer func() { defer func() {
@@ -232,18 +180,6 @@ func TestLoadTestJsonCommands(t *testing.T) {
utils.Cfg.ServiceSettings.EnableTesting = true utils.Cfg.ServiceSettings.EnableTesting = true
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN}
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey+test@test.com", Nickname: "Corey Hulen", Password: "pwd"}
user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user1.Id))
Client.LoginByEmail(team.Name, user1.Email, "pwd")
channel := &model.Channel{DisplayName: "00", Name: "00" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
channel = Client.Must(Client.CreateChannel(channel)).Data.(*model.Channel)
command := "/loadtest json " command := "/loadtest json "
if r := Client.Must(Client.Command(channel.Id, command, false)).Data.(*model.CommandResponse); r.Text != "Command must contain a url" { if r := Client.Must(Client.Command(channel.Id, command, false)).Data.(*model.CommandResponse); r.Text != "Command must contain a url" {
t.Fatal("/loadtest url with no url should've failed") t.Fatal("/loadtest url with no url should've failed")
@@ -255,9 +191,9 @@ func TestLoadTestJsonCommands(t *testing.T) {
t.Fatal("/loadtest url with invalid url should've failed") t.Fatal("/loadtest url with invalid url should've failed")
} }
command = "/loadtest url https://secure.beldienst.nl/test.json" // Chicken-egg so will replace with mattermost/platform URL soon command = "/loadtest json test-slack-attachments"
if r := Client.Must(Client.Command(channel.Id, command, false)).Data.(*model.CommandResponse); r.Text != "Loading data..." { if r := Client.Must(Client.Command(channel.Id, command, false)).Data.(*model.CommandResponse); r.Text != "Loading data..." {
t.Fatal("/loadtest url for README.md should've executed") t.Fatal("/loadtest json should've executed")
} }
time.Sleep(2 * time.Second) time.Sleep(2 * time.Second)

Просмотреть файл

@@ -8,25 +8,12 @@ import (
"testing" "testing"
"github.com/mattermost/platform/model" "github.com/mattermost/platform/model"
"github.com/mattermost/platform/store"
) )
func TestLogoutTestCommand(t *testing.T) { func TestLogoutTestCommand(t *testing.T) {
Setup() th := Setup().InitBasic()
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} rs1 := th.BasicClient.Must(th.BasicClient.Command(th.BasicChannel.Id, "/logout", false)).Data.(*model.CommandResponse)
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey+test@test.com", Nickname: "Corey Hulen", Password: "pwd"}
user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user1.Id))
Client.LoginByEmail(team.Name, user1.Email, "pwd")
channel1 := &model.Channel{DisplayName: "AA", Name: "aa" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel)
rs1 := Client.Must(Client.Command(channel1.Id, "/logout", false)).Data.(*model.CommandResponse)
if !strings.HasSuffix(rs1.GotoLocation, "logout") { if !strings.HasSuffix(rs1.GotoLocation, "logout") {
t.Fatal("failed to logout") t.Fatal("failed to logout")
} }

Просмотреть файл

@@ -8,35 +8,24 @@ import (
"time" "time"
"github.com/mattermost/platform/model" "github.com/mattermost/platform/model"
"github.com/mattermost/platform/store"
) )
func TestMeCommand(t *testing.T) { func TestMeCommand(t *testing.T) {
Setup() th := Setup().InitBasic()
Client := th.BasicClient
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} channel := th.BasicChannel
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey+test@test.com", Nickname: "Corey Hulen", Password: "pwd"}
user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user1.Id))
Client.LoginByEmail(team.Name, user1.Email, "pwd")
channel1 := &model.Channel{DisplayName: "AA", Name: "aa" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel)
testString := "/me hello" testString := "/me hello"
r1 := Client.Must(Client.Command(channel1.Id, testString, false)).Data.(*model.CommandResponse) r1 := Client.Must(Client.Command(channel.Id, testString, false)).Data.(*model.CommandResponse)
if r1 == nil { if r1 == nil {
t.Fatal("Command failed to execute") t.Fatal("Command failed to execute")
} }
time.Sleep(100 * time.Millisecond) time.Sleep(100 * time.Millisecond)
p1 := Client.Must(Client.GetPosts(channel1.Id, 0, 2, "")).Data.(*model.PostList) p1 := Client.Must(Client.GetPosts(channel.Id, 0, 2, "")).Data.(*model.PostList)
if len(p1.Order) != 1 { if len(p1.Order) != 2 {
t.Fatal("Command failed to send") t.Fatal("Command failed to send")
} else { } else {
if p1.Posts[p1.Order[0]].Message != `*hello*` { if p1.Posts[p1.Order[0]].Message != `*hello*` {

Просмотреть файл

@@ -46,7 +46,7 @@ func (me *msgProvider) DoCommand(c *Context, channelId string, message string) *
targetUser = strings.SplitN(message, " ", 2)[0] targetUser = strings.SplitN(message, " ", 2)[0]
targetUser = strings.TrimPrefix(targetUser, "@") targetUser = strings.TrimPrefix(targetUser, "@")
if profileList := <-Srv.Store.User().GetProfiles(c.Session.TeamId); profileList.Err != nil { if profileList := <-Srv.Store.User().GetProfiles(c.TeamId); profileList.Err != nil {
c.Err = profileList.Err c.Err = profileList.Err
return &model.CommandResponse{Text: c.T("api.command_msg.list.app_error"), ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL} return &model.CommandResponse{Text: c.T("api.command_msg.list.app_error"), ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}
} else { } else {
@@ -62,7 +62,7 @@ func (me *msgProvider) DoCommand(c *Context, channelId string, message string) *
//Find the channel based on this user //Find the channel based on this user
channelName := model.GetDMNameFromIds(c.Session.UserId, userProfile.Id) channelName := model.GetDMNameFromIds(c.Session.UserId, userProfile.Id)
if channel := <-Srv.Store.Channel().GetByName(c.Session.TeamId, channelName); channel.Err != nil { if channel := <-Srv.Store.Channel().GetByName(c.TeamId, channelName); channel.Err != nil {
if channel.Err.Id == "store.sql_channel.get_by_name.missing.app_error" { if channel.Err.Id == "store.sql_channel.get_by_name.missing.app_error" {
if directChannel, err := CreateDirectChannel(c, userProfile.Id); err != nil { if directChannel, err := CreateDirectChannel(c, userProfile.Id); err != nil {
c.Err = err c.Err = err
@@ -78,7 +78,7 @@ func (me *msgProvider) DoCommand(c *Context, channelId string, message string) *
targetChannelId = channel.Data.(*model.Channel).Id targetChannelId = channel.Data.(*model.Channel).Id
} }
makeDirectChannelVisible(c.Session.TeamId, targetChannelId) makeDirectChannelVisible(c.TeamId, targetChannelId)
if len(parsedMessage) > 0 { if len(parsedMessage) > 0 {
post := &model.Post{} post := &model.Post{}
post.Message = parsedMessage post.Message = parsedMessage
@@ -87,9 +87,11 @@ func (me *msgProvider) DoCommand(c *Context, channelId string, message string) *
return &model.CommandResponse{Text: c.T("api.command_msg.fail.app_error"), ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL} return &model.CommandResponse{Text: c.T("api.command_msg.fail.app_error"), ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}
} }
} }
return &model.CommandResponse{GotoLocation: c.GetTeamURL() + "/channels/" + channelName, Text: c.T("api.command_msg.success"), ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL} return &model.CommandResponse{GotoLocation: c.GetTeamURL() + "/channels/" + channelName, Text: c.T("api.command_msg.success"), ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}
} }
} }
} }
return &model.CommandResponse{Text: c.T("api.command_msg.missing.app_error"), ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL} return &model.CommandResponse{Text: c.T("api.command_msg.missing.app_error"), ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}
} }

Просмотреть файл

@@ -4,39 +4,29 @@
package api package api
import ( import (
"github.com/mattermost/platform/model"
"strings" "strings"
"testing" "testing"
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/store"
) )
func TestMsgCommands(t *testing.T) { func TestMsgCommands(t *testing.T) {
Setup() th := Setup().InitBasic()
Client := th.BasicClient
team := th.BasicTeam
user1 := th.BasicUser
user2 := th.BasicUser2
user3 := th.CreateUser(th.BasicClient)
LinkUserToTeam(user3, team)
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "success+test@simulator.amazonses.com", Type: model.TEAM_OPEN} Client.Must(Client.CreateDirectChannel(user2.Id))
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team) Client.Must(Client.CreateDirectChannel(user3.Id))
user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Username: "user1", Password: "pwd"} rs1 := Client.Must(Client.Command("", "/msg "+user2.Username, false)).Data.(*model.CommandResponse)
user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user1.Id))
Client.LoginByEmail(team.Name, user1.Email, "pwd")
user2 := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test2@simulator.amazonses.com", Nickname: "Corey Hulen 2", Username: "user2", Password: "pwd"}
user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user2.Id))
user3 := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test3@simulator.amazonses.com", Nickname: "Corey Hulen 3", Username: "user3", Password: "pwd"}
user3 = Client.Must(Client.CreateUser(user3, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user3.Id))
rs1 := Client.Must(Client.Command("", "/msg user2", false)).Data.(*model.CommandResponse)
if !strings.HasSuffix(rs1.GotoLocation, "/"+team.Name+"/channels/"+user1.Id+"__"+user2.Id) && !strings.HasSuffix(rs1.GotoLocation, "/"+team.Name+"/channels/"+user2.Id+"__"+user1.Id) { if !strings.HasSuffix(rs1.GotoLocation, "/"+team.Name+"/channels/"+user1.Id+"__"+user2.Id) && !strings.HasSuffix(rs1.GotoLocation, "/"+team.Name+"/channels/"+user2.Id+"__"+user1.Id) {
t.Fatal("failed to create direct channel") t.Fatal("failed to create direct channel")
} }
rs2 := Client.Must(Client.Command("", "/msg user3 foobar", false)).Data.(*model.CommandResponse) rs2 := Client.Must(Client.Command("", "/msg "+user3.Username+" foobar", false)).Data.(*model.CommandResponse)
if !strings.HasSuffix(rs2.GotoLocation, "/"+team.Name+"/channels/"+user1.Id+"__"+user3.Id) && !strings.HasSuffix(rs2.GotoLocation, "/"+team.Name+"/channels/"+user3.Id+"__"+user1.Id) { if !strings.HasSuffix(rs2.GotoLocation, "/"+team.Name+"/channels/"+user1.Id+"__"+user3.Id) && !strings.HasSuffix(rs2.GotoLocation, "/"+team.Name+"/channels/"+user3.Id+"__"+user1.Id) {
t.Fatal("failed to create second direct channel") t.Fatal("failed to create second direct channel")
} }
@@ -44,7 +34,7 @@ func TestMsgCommands(t *testing.T) {
t.Fatalf("post did not get sent to direct message") t.Fatalf("post did not get sent to direct message")
} }
rs3 := Client.Must(Client.Command("", "/msg user2", false)).Data.(*model.CommandResponse) rs3 := Client.Must(Client.Command("", "/msg "+user2.Username, false)).Data.(*model.CommandResponse)
if !strings.HasSuffix(rs3.GotoLocation, "/"+team.Name+"/channels/"+user1.Id+"__"+user2.Id) && !strings.HasSuffix(rs3.GotoLocation, "/"+team.Name+"/channels/"+user2.Id+"__"+user1.Id) { if !strings.HasSuffix(rs3.GotoLocation, "/"+team.Name+"/channels/"+user1.Id+"__"+user2.Id) && !strings.HasSuffix(rs3.GotoLocation, "/"+team.Name+"/channels/"+user2.Id+"__"+user1.Id) {
t.Fatal("failed to go back to existing direct channel") t.Fatal("failed to go back to existing direct channel")
} }

Просмотреть файл

@@ -8,35 +8,24 @@ import (
"time" "time"
"github.com/mattermost/platform/model" "github.com/mattermost/platform/model"
"github.com/mattermost/platform/store"
) )
func TestShrugCommand(t *testing.T) { func TestShrugCommand(t *testing.T) {
Setup() th := Setup().InitBasic()
Client := th.BasicClient
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} channel := th.BasicChannel
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey+test@test.com", Nickname: "Corey Hulen", Password: "pwd"}
user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user1.Id))
Client.LoginByEmail(team.Name, user1.Email, "pwd")
channel1 := &model.Channel{DisplayName: "AA", Name: "aa" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel)
testString := "/shrug" testString := "/shrug"
r1 := Client.Must(Client.Command(channel1.Id, testString, false)).Data.(*model.CommandResponse) r1 := Client.Must(Client.Command(channel.Id, testString, false)).Data.(*model.CommandResponse)
if r1 == nil { if r1 == nil {
t.Fatal("Command failed to execute") t.Fatal("Command failed to execute")
} }
time.Sleep(100 * time.Millisecond) time.Sleep(100 * time.Millisecond)
p1 := Client.Must(Client.GetPosts(channel1.Id, 0, 2, "")).Data.(*model.PostList) p1 := Client.Must(Client.GetPosts(channel.Id, 0, 2, "")).Data.(*model.PostList)
if len(p1.Order) != 1 { if len(p1.Order) != 2 {
t.Fatal("Command failed to send") t.Fatal("Command failed to send")
} else { } else {
if p1.Posts[p1.Order[0]].Message != `¯\\\_(ツ)\_/¯` { if p1.Posts[p1.Order[0]].Message != `¯\\\_(ツ)\_/¯` {

Просмотреть файл

@@ -8,21 +8,12 @@ import (
"time" "time"
"github.com/mattermost/platform/model" "github.com/mattermost/platform/model"
"github.com/mattermost/platform/store"
"github.com/mattermost/platform/utils" "github.com/mattermost/platform/utils"
) )
func TestListCommands(t *testing.T) { func TestListCommands(t *testing.T) {
Setup() th := Setup().InitBasic()
Client := th.BasicClient
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN}
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user1.Id))
Client.LoginByEmail(team.Name, user1.Email, "pwd")
if results, err := Client.ListCommands(); err != nil { if results, err := Client.ListCommands(); err != nil {
t.Fatal(err) t.Fatal(err)
@@ -43,7 +34,10 @@ func TestListCommands(t *testing.T) {
} }
func TestCreateCommand(t *testing.T) { func TestCreateCommand(t *testing.T) {
Setup() th := Setup().InitBasic().InitSystemAdmin()
Client := th.BasicClient
user := th.SystemAdminUser
team := th.SystemAdminTeam
enableCommands := *utils.Cfg.ServiceSettings.EnableCommands enableCommands := *utils.Cfg.ServiceSettings.EnableCommands
defer func() { defer func() {
@@ -51,26 +45,13 @@ func TestCreateCommand(t *testing.T) {
}() }()
*utils.Cfg.ServiceSettings.EnableCommands = true *utils.Cfg.ServiceSettings.EnableCommands = true
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} cmd := &model.Command{URL: "http://nowhere.com", Method: model.COMMAND_METHOD_POST, Trigger: "trigger"}
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
user := &model.User{TeamId: team.Id, Email: model.NewId() + "corey+test@test.com", Nickname: "Corey Hulen", Password: "pwd"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user.Id))
Client.LoginByEmail(team.Name, user.Email, "pwd")
cmd := &model.Command{URL: "http://nowhere.com", Method: model.COMMAND_METHOD_POST}
if _, err := Client.CreateCommand(cmd); err == nil { if _, err := Client.CreateCommand(cmd); err == nil {
t.Fatal("should have failed because not admin") t.Fatal("should have failed because not admin")
} }
c := &Context{} Client = th.SystemAdminClient
c.RequestId = model.NewId()
c.IpAddress = "cmd_line"
UpdateRoles(c, user, model.ROLE_SYSTEM_ADMIN)
Client.LoginByEmail(team.Name, user.Email, "pwd")
var rcmd *model.Command var rcmd *model.Command
if result, err := Client.CreateCommand(cmd); err != nil { if result, err := Client.CreateCommand(cmd); err != nil {
@@ -87,7 +68,7 @@ func TestCreateCommand(t *testing.T) {
t.Fatal("team ids didn't match") t.Fatal("team ids didn't match")
} }
cmd = &model.Command{CreatorId: "123", TeamId: "456", URL: "http://nowhere.com", Method: model.COMMAND_METHOD_POST} cmd = &model.Command{CreatorId: "123", TeamId: "456", URL: "http://nowhere.com", Method: model.COMMAND_METHOD_POST, Trigger: "trigger"}
if result, err := Client.CreateCommand(cmd); err != nil { if result, err := Client.CreateCommand(cmd); err != nil {
t.Fatal(err) t.Fatal(err)
} else { } else {
@@ -101,27 +82,16 @@ func TestCreateCommand(t *testing.T) {
} }
func TestListTeamCommands(t *testing.T) { func TestListTeamCommands(t *testing.T) {
Setup() th := Setup().InitSystemAdmin()
Client := th.SystemAdminClient
enableCommands := *utils.Cfg.ServiceSettings.EnableCommands enableCommands := *utils.Cfg.ServiceSettings.EnableCommands
defer func() { defer func() {
utils.Cfg.ServiceSettings.EnableCommands = &enableCommands utils.Cfg.ServiceSettings.EnableCommands = &enableCommands
}() }()
*utils.Cfg.ServiceSettings.EnableCommands = true *utils.Cfg.ServiceSettings.EnableCommands = true
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} cmd1 := &model.Command{URL: "http://nowhere.com", Method: model.COMMAND_METHOD_POST, Trigger: "trigger"}
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
user := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user.Id))
c := &Context{}
c.RequestId = model.NewId()
c.IpAddress = "cmd_line"
UpdateRoles(c, user, model.ROLE_SYSTEM_ADMIN)
Client.LoginByEmail(team.Name, user.Email, "pwd")
cmd1 := &model.Command{URL: "http://nowhere.com", Method: model.COMMAND_METHOD_POST}
cmd1 = Client.Must(Client.CreateCommand(cmd1)).Data.(*model.Command) cmd1 = Client.Must(Client.CreateCommand(cmd1)).Data.(*model.Command)
if result, err := Client.ListTeamCommands(); err != nil { if result, err := Client.ListTeamCommands(); err != nil {
@@ -136,27 +106,16 @@ func TestListTeamCommands(t *testing.T) {
} }
func TestRegenToken(t *testing.T) { func TestRegenToken(t *testing.T) {
Setup() th := Setup().InitSystemAdmin()
Client := th.SystemAdminClient
enableCommands := *utils.Cfg.ServiceSettings.EnableCommands enableCommands := *utils.Cfg.ServiceSettings.EnableCommands
defer func() { defer func() {
utils.Cfg.ServiceSettings.EnableCommands = &enableCommands utils.Cfg.ServiceSettings.EnableCommands = &enableCommands
}() }()
*utils.Cfg.ServiceSettings.EnableCommands = true *utils.Cfg.ServiceSettings.EnableCommands = true
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} cmd := &model.Command{URL: "http://nowhere.com", Method: model.COMMAND_METHOD_POST, Trigger: "trigger"}
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
user := &model.User{TeamId: team.Id, Email: model.NewId() + "corey+test@test.com", Nickname: "Corey Hulen", Password: "pwd"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user.Id))
c := &Context{}
c.RequestId = model.NewId()
c.IpAddress = "cmd_line"
UpdateRoles(c, user, model.ROLE_SYSTEM_ADMIN)
Client.LoginByEmail(team.Name, user.Email, "pwd")
cmd := &model.Command{URL: "http://nowhere.com", Method: model.COMMAND_METHOD_POST}
cmd = Client.Must(Client.CreateCommand(cmd)).Data.(*model.Command) cmd = Client.Must(Client.CreateCommand(cmd)).Data.(*model.Command)
data := make(map[string]string) data := make(map[string]string)
@@ -172,27 +131,16 @@ func TestRegenToken(t *testing.T) {
} }
func TestDeleteCommand(t *testing.T) { func TestDeleteCommand(t *testing.T) {
Setup() th := Setup().InitSystemAdmin()
Client := th.SystemAdminClient
enableCommands := *utils.Cfg.ServiceSettings.EnableCommands enableCommands := *utils.Cfg.ServiceSettings.EnableCommands
defer func() { defer func() {
utils.Cfg.ServiceSettings.EnableCommands = &enableCommands utils.Cfg.ServiceSettings.EnableCommands = &enableCommands
}() }()
*utils.Cfg.ServiceSettings.EnableCommands = true *utils.Cfg.ServiceSettings.EnableCommands = true
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} cmd := &model.Command{URL: "http://nowhere.com", Method: model.COMMAND_METHOD_POST, Trigger: "trigger"}
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
user := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user.Id))
c := &Context{}
c.RequestId = model.NewId()
c.IpAddress = "cmd_line"
UpdateRoles(c, user, model.ROLE_SYSTEM_ADMIN)
Client.LoginByEmail(team.Name, user.Email, "pwd")
cmd := &model.Command{URL: "http://nowhere.com", Method: model.COMMAND_METHOD_POST}
cmd = Client.Must(Client.CreateCommand(cmd)).Data.(*model.Command) cmd = Client.Must(Client.CreateCommand(cmd)).Data.(*model.Command)
data := make(map[string]string) data := make(map[string]string)
@@ -209,31 +157,18 @@ func TestDeleteCommand(t *testing.T) {
} }
func TestTestCommand(t *testing.T) { func TestTestCommand(t *testing.T) {
Setup() th := Setup().InitSystemAdmin()
Client := th.SystemAdminClient
channel1 := th.SystemAdminChannel
enableCommands := *utils.Cfg.ServiceSettings.EnableCommands enableCommands := *utils.Cfg.ServiceSettings.EnableCommands
defer func() { defer func() {
utils.Cfg.ServiceSettings.EnableCommands = &enableCommands utils.Cfg.ServiceSettings.EnableCommands = &enableCommands
}() }()
*utils.Cfg.ServiceSettings.EnableCommands = true *utils.Cfg.ServiceSettings.EnableCommands = true
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN}
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
user := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user.Id))
c := &Context{}
c.RequestId = model.NewId()
c.IpAddress = "cmd_line"
UpdateRoles(c, user, model.ROLE_SYSTEM_ADMIN)
Client.LoginByEmail(team.Name, user.Email, "pwd")
channel1 := &model.Channel{DisplayName: "AA", Name: "aa" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel)
cmd1 := &model.Command{ cmd1 := &model.Command{
URL: "http://localhost" + utils.Cfg.ServiceSettings.ListenAddress + "/api/v1/commands/test", URL: "http://localhost" + utils.Cfg.ServiceSettings.ListenAddress + model.API_URL_SUFFIX + "/teams/command_test",
Method: model.COMMAND_METHOD_POST, Method: model.COMMAND_METHOD_POST,
Trigger: "test", Trigger: "test",
} }
@@ -253,7 +188,7 @@ func TestTestCommand(t *testing.T) {
} }
cmd2 := &model.Command{ cmd2 := &model.Command{
URL: "http://localhost" + utils.Cfg.ServiceSettings.ListenAddress + "/api/v1/commands/test", URL: "http://localhost" + utils.Cfg.ServiceSettings.ListenAddress + model.API_URL_SUFFIX + "/teams/command_test",
Method: model.COMMAND_METHOD_GET, Method: model.COMMAND_METHOD_GET,
Trigger: "test2", Trigger: "test2",
} }

Просмотреть файл

@@ -11,10 +11,12 @@ import (
"strings" "strings"
l4g "github.com/alecthomas/log4go" l4g "github.com/alecthomas/log4go"
"github.com/gorilla/mux"
goi18n "github.com/nicksnyder/go-i18n/i18n"
"github.com/mattermost/platform/model" "github.com/mattermost/platform/model"
"github.com/mattermost/platform/store" "github.com/mattermost/platform/store"
"github.com/mattermost/platform/utils" "github.com/mattermost/platform/utils"
goi18n "github.com/nicksnyder/go-i18n/i18n"
) )
var sessionCache *utils.Cache = utils.NewLru(model.SESSION_CACHE_SIZE) var sessionCache *utils.Cache = utils.NewLru(model.SESSION_CACHE_SIZE)
@@ -39,6 +41,7 @@ type Context struct {
siteURL string siteURL string
T goi18n.TranslateFunc T goi18n.TranslateFunc
Locale string Locale string
TeamId string
} }
func ApiAppHandler(h func(*Context, http.ResponseWriter, *http.Request)) http.Handler { func ApiAppHandler(h func(*Context, http.ResponseWriter, *http.Request)) http.Handler {
@@ -94,6 +97,8 @@ func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
c.T, c.Locale = utils.GetTranslationsAndLocale(w, r) c.T, c.Locale = utils.GetTranslationsAndLocale(w, r)
c.RequestId = model.NewId() c.RequestId = model.NewId()
c.IpAddress = GetIpAddress(r) c.IpAddress = GetIpAddress(r)
c.TeamId = mux.Vars(r)["team_id"]
h.isApi = IsApiCall(r)
token := "" token := ""
isTokenFromQueryString := false isTokenFromQueryString := false
@@ -116,7 +121,7 @@ func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if (h.requireSystemAdmin || h.requireUser) && !h.trustRequester { if (h.requireSystemAdmin || h.requireUser) && !h.trustRequester {
if r.Header.Get(model.HEADER_REQUESTED_WITH) != model.HEADER_REQUESTED_WITH_XML { if r.Header.Get(model.HEADER_REQUESTED_WITH) != model.HEADER_REQUESTED_WITH_XML {
c.Err = model.NewLocAppError("ServeHTTP", "api.context.session_expired.app_error", nil, "token="+token) c.Err = model.NewLocAppError("ServeHTTP", "api.context.session_expired.app_error", nil, "token="+token+" Appears to bea CSRF attempt")
token = "" token = ""
} }
} }
@@ -182,6 +187,10 @@ func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
c.SystemAdminRequired() c.SystemAdminRequired()
} }
if c.Err == nil && len(c.TeamId) > 0 {
c.HasPermissionsToTeam(c.TeamId, "TeamRoute")
}
if c.Err == nil && h.isUserActivity && token != "" && len(c.Session.UserId) > 0 { if c.Err == nil && h.isUserActivity && token != "" && len(c.Session.UserId) > 0 {
go func() { go func() {
if err := (<-Srv.Store.User().UpdateUserAndSessionActivity(c.Session.UserId, c.Session.Id, model.GetMillis())).Err; err != nil { if err := (<-Srv.Store.User().UpdateUserAndSessionActivity(c.Session.UserId, c.Session.Id, model.GetMillis())).Err; err != nil {
@@ -308,13 +317,14 @@ func (c *Context) HasPermissionsToUser(userId string, where string) bool {
} }
func (c *Context) HasPermissionsToTeam(teamId string, where string) bool { func (c *Context) HasPermissionsToTeam(teamId string, where string) bool {
if c.Session.TeamId == teamId { if c.IsSystemAdmin() {
return true return true
} }
// You're a mattermost system admin and you're on the VPN for _, teamMember := range c.Session.TeamMembers {
if c.IsSystemAdmin() { if teamId == teamMember.TeamId {
return true return true
}
} }
c.Err = model.NewLocAppError(where, "api.context.permissions.app_error", nil, "userId="+c.Session.UserId+", teamId="+teamId) c.Err = model.NewLocAppError(where, "api.context.permissions.app_error", nil, "userId="+c.Session.UserId+", teamId="+teamId)
@@ -353,10 +363,17 @@ func (c *Context) IsSystemAdmin() bool {
} }
func (c *Context) IsTeamAdmin() bool { func (c *Context) IsTeamAdmin() bool {
if model.IsInRole(c.Session.Roles, model.ROLE_TEAM_ADMIN) || c.IsSystemAdmin() {
if c.IsSystemAdmin() {
return true return true
} }
return false
team := c.Session.GetTeamByTeamId(c.TeamId)
if team == nil {
return false
}
return model.IsInRole(team.Roles, model.ROLE_TEAM_ADMIN)
} }
func (c *Context) RemoveSessionCookie(w http.ResponseWriter, r *http.Request) { func (c *Context) RemoveSessionCookie(w http.ResponseWriter, r *http.Request) {
@@ -386,7 +403,7 @@ func (c *Context) setTeamURL(url string, valid bool) {
} }
func (c *Context) SetTeamURLFromSession() { func (c *Context) SetTeamURLFromSession() {
if result := <-Srv.Store.Team().Get(c.Session.TeamId); result.Err == nil { if result := <-Srv.Store.Team().Get(c.TeamId); result.Err == nil {
c.setTeamURL(c.GetSiteURL()+"/"+result.Data.(*model.Team).Name, true) c.setTeamURL(c.GetSiteURL()+"/"+result.Data.(*model.Team).Name, true)
} }
} }
@@ -413,6 +430,10 @@ func (c *Context) GetSiteURL() string {
return c.siteURL return c.siteURL
} }
func IsApiCall(r *http.Request) bool {
return strings.Index(r.URL.Path, "/api/") == 0
}
func GetIpAddress(r *http.Request) string { func GetIpAddress(r *http.Request) string {
address := r.Header.Get(model.HEADER_FORWARDED) address := r.Header.Get(model.HEADER_FORWARDED)
@@ -427,69 +448,69 @@ func GetIpAddress(r *http.Request) string {
return address return address
} }
func IsTestDomain(r *http.Request) bool { // func IsTestDomain(r *http.Request) bool {
if strings.Index(r.Host, "localhost") == 0 { // if strings.Index(r.Host, "localhost") == 0 {
return true // return true
} // }
if strings.Index(r.Host, "dockerhost") == 0 { // if strings.Index(r.Host, "dockerhost") == 0 {
return true // return true
} // }
if strings.Index(r.Host, "test") == 0 { // if strings.Index(r.Host, "test") == 0 {
return true // return true
} // }
if strings.Index(r.Host, "127.0.") == 0 { // if strings.Index(r.Host, "127.0.") == 0 {
return true // return true
} // }
if strings.Index(r.Host, "192.168.") == 0 { // if strings.Index(r.Host, "192.168.") == 0 {
return true // return true
} // }
if strings.Index(r.Host, "10.") == 0 { // if strings.Index(r.Host, "10.") == 0 {
return true // return true
} // }
if strings.Index(r.Host, "176.") == 0 { // if strings.Index(r.Host, "176.") == 0 {
return true // return true
} // }
return false // return false
} // }
func IsBetaDomain(r *http.Request) bool { // func IsBetaDomain(r *http.Request) bool {
if strings.Index(r.Host, "beta") == 0 { // if strings.Index(r.Host, "beta") == 0 {
return true // return true
} // }
if strings.Index(r.Host, "ci") == 0 { // if strings.Index(r.Host, "ci") == 0 {
return true // return true
} // }
return false // return false
} // }
var privateIpAddress = []*net.IPNet{ // var privateIpAddress = []*net.IPNet{
{IP: net.IPv4(10, 0, 0, 1), Mask: net.IPv4Mask(255, 0, 0, 0)}, // {IP: net.IPv4(10, 0, 0, 1), Mask: net.IPv4Mask(255, 0, 0, 0)},
{IP: net.IPv4(176, 16, 0, 1), Mask: net.IPv4Mask(255, 255, 0, 0)}, // {IP: net.IPv4(176, 16, 0, 1), Mask: net.IPv4Mask(255, 255, 0, 0)},
{IP: net.IPv4(192, 168, 0, 1), Mask: net.IPv4Mask(255, 255, 255, 0)}, // {IP: net.IPv4(192, 168, 0, 1), Mask: net.IPv4Mask(255, 255, 255, 0)},
{IP: net.IPv4(127, 0, 0, 1), Mask: net.IPv4Mask(255, 255, 255, 252)}, // {IP: net.IPv4(127, 0, 0, 1), Mask: net.IPv4Mask(255, 255, 255, 252)},
} // }
func IsPrivateIpAddress(ipAddress string) bool { // func IsPrivateIpAddress(ipAddress string) bool {
for _, pips := range privateIpAddress { // for _, pips := range privateIpAddress {
if pips.Contains(net.ParseIP(ipAddress)) { // if pips.Contains(net.ParseIP(ipAddress)) {
return true // return true
} // }
} // }
return false // return false
} // }
func RenderWebError(err *model.AppError, w http.ResponseWriter, r *http.Request) { func RenderWebError(err *model.AppError, w http.ResponseWriter, r *http.Request) {
T, _ := utils.GetTranslationsAndLocale(w, r) T, _ := utils.GetTranslationsAndLocale(w, r)
@@ -513,9 +534,17 @@ func RenderWebError(err *model.AppError, w http.ResponseWriter, r *http.Request)
func Handle404(w http.ResponseWriter, r *http.Request) { func Handle404(w http.ResponseWriter, r *http.Request) {
err := model.NewLocAppError("Handle404", "api.context.404.app_error", nil, "") err := model.NewLocAppError("Handle404", "api.context.404.app_error", nil, "")
err.Translate(utils.T)
err.StatusCode = http.StatusNotFound err.StatusCode = http.StatusNotFound
l4g.Error("%v: code=404 ip=%v", r.URL.Path, GetIpAddress(r)) l4g.Error("%v: code=404 ip=%v", r.URL.Path, GetIpAddress(r))
RenderWebError(err, w, r)
if IsApiCall(r) {
w.WriteHeader(err.StatusCode)
err.DetailedError = "There doesn't appear to be an api call for the url='" + r.URL.Path + "'. Typo? are you missing a team_id or user_id as part of the url?"
w.Write([]byte(err.ToJson()))
} else {
RenderWebError(err, w, r)
}
} }
func GetSession(token string) *model.Session { func GetSession(token string) *model.Session {
@@ -542,6 +571,20 @@ func GetSession(token string) *model.Session {
return session return session
} }
func RemoveAllSessionsForUserId(userId string) {
keys := sessionCache.Keys()
for _, key := range keys {
if ts, ok := sessionCache.Get(key); ok {
session := ts.(*model.Session)
if session.UserId == userId {
sessionCache.Remove(key)
}
}
}
}
func AddSessionToCache(session *model.Session) { func AddSessionToCache(session *model.Session) {
sessionCache.AddWithExpiresInSecs(session.Token, session, int64(*utils.Cfg.ServiceSettings.SessionCacheInMinutes*60)) sessionCache.AddWithExpiresInSecs(session.Token, session, int64(*utils.Cfg.ServiceSettings.SessionCacheInMinutes*60))
} }

Просмотреть файл

@@ -8,32 +8,6 @@ import (
"testing" "testing"
) )
var ipAddressTests = []struct {
address string
expected bool
}{
{"126.255.255.255", false},
{"127.0.0.1", true},
{"127.0.0.4", false},
{"9.255.255.255", false},
{"10.0.0.1", true},
{"11.0.0.1", false},
{"176.15.155.255", false},
{"176.16.0.1", true},
{"176.31.0.1", false},
{"192.167.255.255", false},
{"192.168.0.1", true},
{"192.169.0.1", false},
}
func TestIpAddress(t *testing.T) {
for _, v := range ipAddressTests {
if IsPrivateIpAddress(v.address) != v.expected {
t.Errorf("expect %v as %v", v.address, v.expected)
}
}
}
func TestContext(t *testing.T) { func TestContext(t *testing.T) {
context := Context{} context := Context{}
@@ -52,9 +26,26 @@ func TestContext(t *testing.T) {
if !context.HasPermissionsToUser("6", "") { if !context.HasPermissionsToUser("6", "") {
t.Fatal("should have permissions") t.Fatal("should have permissions")
} }
}
// context.IpAddress = "125.0.0.1"
// if context.HasPermissionsToUser("6", "") { func TestCache(t *testing.T) {
// t.Fatal("shouldn't have permissions") session := &model.Session{
// } Id: model.NewId(),
Token: model.NewId(),
UserId: model.NewId(),
}
sessionCache.AddWithExpiresInSecs(session.Token, session, 5*60)
keys := sessionCache.Keys()
if len(keys) <= 0 {
t.Fatal("should have items")
}
RemoveAllSessionsForUserId(session.UserId)
rkeys := sessionCache.Keys()
if len(rkeys) != len(keys)-1 {
t.Fatal("should have one less")
}
} }

Просмотреть файл

@@ -60,7 +60,7 @@ func ExportToFile(options *ExportOptions) (link string, err *model.AppError) {
ExportToWriter(file, options) ExportToWriter(file, options)
} }
return "/api/v1/files/get_export", nil return model.API_URL_SUFFIX + "/files/get_export", nil
} }
func ExportToWriter(w io.Writer, options *ExportOptions) *model.AppError { func ExportToWriter(w io.Writer, options *ExportOptions) *model.AppError {

Просмотреть файл

@@ -57,15 +57,14 @@ const (
var fileInfoCache *utils.Cache = utils.NewLru(1000) var fileInfoCache *utils.Cache = utils.NewLru(1000)
func InitFile(r *mux.Router) { func InitFile() {
l4g.Debug(utils.T("api.file.init.debug")) l4g.Debug(utils.T("api.file.init.debug"))
sr := r.PathPrefix("/files").Subrouter() BaseRoutes.Files.Handle("/upload", ApiUserRequired(uploadFile)).Methods("POST")
sr.Handle("/upload", ApiUserRequired(uploadFile)).Methods("POST") BaseRoutes.Files.Handle("/get/{channel_id:[A-Za-z0-9]+}/{user_id:[A-Za-z0-9]+}/{filename:([A-Za-z0-9]+/)?.+(\\.[A-Za-z0-9]{3,})?}", ApiAppHandlerTrustRequester(getFile)).Methods("GET")
sr.Handle("/get/{channel_id:[A-Za-z0-9]+}/{user_id:[A-Za-z0-9]+}/{filename:([A-Za-z0-9]+/)?.+(\\.[A-Za-z0-9]{3,})?}", ApiAppHandlerTrustRequester(getFile)).Methods("GET") BaseRoutes.Files.Handle("/get_info/{channel_id:[A-Za-z0-9]+}/{user_id:[A-Za-z0-9]+}/{filename:([A-Za-z0-9]+/)?.+(\\.[A-Za-z0-9]{3,})?}", ApiAppHandler(getFileInfo)).Methods("GET")
sr.Handle("/get_info/{channel_id:[A-Za-z0-9]+}/{user_id:[A-Za-z0-9]+}/{filename:([A-Za-z0-9]+/)?.+(\\.[A-Za-z0-9]{3,})?}", ApiAppHandler(getFileInfo)).Methods("GET") BaseRoutes.Files.Handle("/get_public_link", ApiUserRequired(getPublicLink)).Methods("POST")
sr.Handle("/get_public_link", ApiUserRequired(getPublicLink)).Methods("POST") BaseRoutes.Files.Handle("/get_export", ApiUserRequired(getExport)).Methods("GET")
sr.Handle("/get_export", ApiUserRequired(getExport)).Methods("GET")
} }
func uploadFile(c *Context, w http.ResponseWriter, r *http.Request) { func uploadFile(c *Context, w http.ResponseWriter, r *http.Request) {
@@ -101,7 +100,7 @@ func uploadFile(c *Context, w http.ResponseWriter, r *http.Request) {
return return
} }
cchan := Srv.Store.Channel().CheckPermissionsTo(c.Session.TeamId, channelId, c.Session.UserId) cchan := Srv.Store.Channel().CheckPermissionsTo(c.TeamId, channelId, c.Session.UserId)
files := m.File["files"] files := m.File["files"]
@@ -147,7 +146,7 @@ func uploadFile(c *Context, w http.ResponseWriter, r *http.Request) {
} }
} }
path := "teams/" + c.Session.TeamId + "/channels/" + channelId + "/users/" + c.Session.UserId + "/" + uid + "/" + filename path := "teams/" + c.TeamId + "/channels/" + channelId + "/users/" + c.Session.UserId + "/" + uid + "/" + filename
if err := WriteFile(buf.Bytes(), path); err != nil { if err := WriteFile(buf.Bytes(), path); err != nil {
c.Err = err c.Err = err
@@ -164,7 +163,7 @@ func uploadFile(c *Context, w http.ResponseWriter, r *http.Request) {
resStruct.ClientIds = append(resStruct.ClientIds, clientId) resStruct.ClientIds = append(resStruct.ClientIds, clientId)
} }
handleImagesAndForget(imageNameList, imageDataList, c.Session.TeamId, channelId, c.Session.UserId) handleImagesAndForget(imageNameList, imageDataList, c.TeamId, channelId, c.Session.UserId)
w.Write([]byte(resStruct.ToJson())) w.Write([]byte(resStruct.ToJson()))
} }
@@ -319,9 +318,9 @@ func getFileInfo(c *Context, w http.ResponseWriter, r *http.Request) {
return return
} }
cchan := Srv.Store.Channel().CheckPermissionsTo(c.Session.TeamId, channelId, c.Session.UserId) cchan := Srv.Store.Channel().CheckPermissionsTo(c.TeamId, channelId, c.Session.UserId)
path := "teams/" + c.Session.TeamId + "/channels/" + channelId + "/users/" + userId + "/" + filename path := "teams/" + c.TeamId + "/channels/" + channelId + "/users/" + userId + "/" + filename
var info *model.FileInfo var info *model.FileInfo
if cached, ok := fileInfoCache.Get(path); ok { if cached, ok := fileInfoCache.Get(path); ok {
@@ -380,13 +379,13 @@ func getFile(c *Context, w http.ResponseWriter, r *http.Request) {
data := r.URL.Query().Get("d") data := r.URL.Query().Get("d")
teamId := r.URL.Query().Get("t") teamId := r.URL.Query().Get("t")
cchan := Srv.Store.Channel().CheckPermissionsTo(c.Session.TeamId, channelId, c.Session.UserId) cchan := Srv.Store.Channel().CheckPermissionsTo(c.TeamId, channelId, c.Session.UserId)
path := "" path := ""
if len(teamId) == 26 { if len(teamId) == 26 {
path = "teams/" + teamId + "/channels/" + channelId + "/users/" + userId + "/" + filename path = "teams/" + teamId + "/channels/" + channelId + "/users/" + userId + "/" + filename
} else { } else {
path = "teams/" + c.Session.TeamId + "/channels/" + channelId + "/users/" + userId + "/" + filename path = "teams/" + c.TeamId + "/channels/" + channelId + "/users/" + userId + "/" + filename
} }
fileData := make(chan []byte) fileData := make(chan []byte)
@@ -460,6 +459,7 @@ func getPublicLink(c *Context, w http.ResponseWriter, r *http.Request) {
if !utils.Cfg.FileSettings.EnablePublicLink { if !utils.Cfg.FileSettings.EnablePublicLink {
c.Err = model.NewLocAppError("getPublicLink", "api.file.get_public_link.disabled.app_error", nil, "") c.Err = model.NewLocAppError("getPublicLink", "api.file.get_public_link.disabled.app_error", nil, "")
c.Err.StatusCode = http.StatusForbidden c.Err.StatusCode = http.StatusForbidden
return
} }
props := model.MapFromJson(r.Body) props := model.MapFromJson(r.Body)
@@ -480,7 +480,7 @@ func getPublicLink(c *Context, w http.ResponseWriter, r *http.Request) {
userId := matches[0][2] userId := matches[0][2]
filename = matches[0][3] filename = matches[0][3]
cchan := Srv.Store.Channel().CheckPermissionsTo(c.Session.TeamId, channelId, c.Session.UserId) cchan := Srv.Store.Channel().CheckPermissionsTo(c.TeamId, channelId, c.Session.UserId)
newProps := make(map[string]string) newProps := make(map[string]string)
newProps["filename"] = filename newProps["filename"] = filename
@@ -488,7 +488,7 @@ func getPublicLink(c *Context, w http.ResponseWriter, r *http.Request) {
data := model.MapToJson(newProps) data := model.MapToJson(newProps)
hash := model.HashPassword(fmt.Sprintf("%v:%v", data, utils.Cfg.FileSettings.PublicLinkSalt)) hash := model.HashPassword(fmt.Sprintf("%v:%v", data, utils.Cfg.FileSettings.PublicLinkSalt))
url := fmt.Sprintf("%s/api/v1/files/get/%s/%s/%s?d=%s&h=%s&t=%s", c.GetSiteURL(), channelId, userId, filename, url.QueryEscape(data), url.QueryEscape(hash), c.Session.TeamId) url := fmt.Sprintf("%s/files/get/%s/%s/%s?d=%s&h=%s&t=%s", c.GetSiteURL()+model.API_URL_SUFFIX, channelId, userId, filename, url.QueryEscape(data), url.QueryEscape(hash), c.TeamId)
if !c.HasPermissionsToChannel(cchan, "getPublicLink") { if !c.HasPermissionsToChannel(cchan, "getPublicLink") {
return return
@@ -501,7 +501,7 @@ func getPublicLink(c *Context, w http.ResponseWriter, r *http.Request) {
} }
func getExport(c *Context, w http.ResponseWriter, r *http.Request) { func getExport(c *Context, w http.ResponseWriter, r *http.Request) {
if !c.HasPermissionsToTeam(c.Session.TeamId, "export") || !c.IsTeamAdmin() { if !c.HasPermissionsToTeam(c.TeamId, "export") || !c.IsTeamAdmin() {
c.Err = model.NewLocAppError("getExport", "api.file.get_export.team_admin.app_error", nil, "userId="+c.Session.UserId) c.Err = model.NewLocAppError("getExport", "api.file.get_export.team_admin.app_error", nil, "userId="+c.Session.UserId)
c.Err.StatusCode = http.StatusForbidden c.Err.StatusCode = http.StatusForbidden
return return

Просмотреть файл

@@ -13,7 +13,9 @@ import (
) )
func BenchmarkUploadFile(b *testing.B) { func BenchmarkUploadFile(b *testing.B) {
_, _, channel := SetupBenchmark() th := Setup().InitBasic()
Client := th.BasicClient
channel := th.BasicChannel
testPoster := NewAutoPostCreator(Client, channel.Id) testPoster := NewAutoPostCreator(Client, channel.Id)
@@ -25,7 +27,10 @@ func BenchmarkUploadFile(b *testing.B) {
} }
func BenchmarkGetFile(b *testing.B) { func BenchmarkGetFile(b *testing.B) {
team, _, channel := SetupBenchmark() th := Setup().InitBasic()
Client := th.BasicClient
team := th.BasicTeam
channel := th.BasicChannel
testPoster := NewAutoPostCreator(Client, channel.Id) testPoster := NewAutoPostCreator(Client, channel.Id)
filenames, err := testPoster.UploadTestFile() filenames, err := testPoster.UploadTestFile()
@@ -53,7 +58,9 @@ func BenchmarkGetFile(b *testing.B) {
} }
func BenchmarkGetPublicLink(b *testing.B) { func BenchmarkGetPublicLink(b *testing.B) {
_, _, channel := SetupBenchmark() th := Setup().InitBasic()
Client := th.BasicClient
channel := th.BasicChannel
testPoster := NewAutoPostCreator(Client, channel.Id) testPoster := NewAutoPostCreator(Client, channel.Id)
filenames, err := testPoster.UploadTestFile() filenames, err := testPoster.UploadTestFile()

Просмотреть файл

@@ -22,19 +22,11 @@ import (
) )
func TestUploadFile(t *testing.T) { func TestUploadFile(t *testing.T) {
Setup() th := Setup().InitBasic()
Client := th.BasicClient
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} team := th.BasicTeam
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team) user := th.BasicUser
channel := th.BasicChannel
user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user1.Id))
Client.LoginByEmail(team.Name, user1.Email, "pwd")
channel1 := &model.Channel{DisplayName: "Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel)
body := &bytes.Buffer{} body := &bytes.Buffer{}
writer := multipart.NewWriter(body) writer := multipart.NewWriter(body)
@@ -45,6 +37,9 @@ func TestUploadFile(t *testing.T) {
path := utils.FindDir("tests") path := utils.FindDir("tests")
file, err := os.Open(path + "/test.png") file, err := os.Open(path + "/test.png")
if err != nil {
t.Fatal(err)
}
defer file.Close() defer file.Close()
_, err = io.Copy(part, file) _, err = io.Copy(part, file)
@@ -57,7 +52,7 @@ func TestUploadFile(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
_, err = field.Write([]byte(channel1.Id)) _, err = field.Write([]byte(channel.Id))
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@@ -67,7 +62,7 @@ func TestUploadFile(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
resp, appErr := Client.UploadFile("/files/upload", body.Bytes(), writer.FormDataContentType()) resp, appErr := Client.UploadPostAttachment(body.Bytes(), writer.FormDataContentType())
if utils.Cfg.FileSettings.DriverName == model.IMAGE_DRIVER_S3 { if utils.Cfg.FileSettings.DriverName == model.IMAGE_DRIVER_S3 {
if appErr != nil { if appErr != nil {
t.Fatal(appErr) t.Fatal(appErr)
@@ -90,17 +85,17 @@ func TestUploadFile(t *testing.T) {
// wait a bit for files to ready // wait a bit for files to ready
time.Sleep(5 * time.Second) time.Sleep(5 * time.Second)
err = bucket.Del("teams/" + team.Id + "/channels/" + channel1.Id + "/users/" + user1.Id + "/" + filename) err = bucket.Del("teams/" + team.Id + "/channels/" + channel.Id + "/users/" + user.Id + "/" + filename)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
err = bucket.Del("teams/" + team.Id + "/channels/" + channel1.Id + "/users/" + user1.Id + "/" + fileId + "_thumb.jpg") err = bucket.Del("teams/" + team.Id + "/channels/" + channel.Id + "/users/" + user.Id + "/" + fileId + "_thumb.jpg")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
err = bucket.Del("teams/" + team.Id + "/channels/" + channel1.Id + "/users/" + user1.Id + "/" + fileId + "_preview.jpg") err = bucket.Del("teams/" + team.Id + "/channels/" + channel.Id + "/users/" + user.Id + "/" + fileId + "_preview.jpg")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@@ -115,17 +110,17 @@ func TestUploadFile(t *testing.T) {
// wait a bit for files to ready // wait a bit for files to ready
time.Sleep(5 * time.Second) time.Sleep(5 * time.Second)
path := utils.Cfg.FileSettings.Directory + "teams/" + team.Id + "/channels/" + channel1.Id + "/users/" + user1.Id + "/" + filename path := utils.Cfg.FileSettings.Directory + "teams/" + team.Id + "/channels/" + channel.Id + "/users/" + user.Id + "/" + filename
if err := os.Remove(path); err != nil { if err := os.Remove(path); err != nil {
t.Fatal("Couldn't remove file at " + path) t.Fatal("Couldn't remove file at " + path)
} }
path = utils.Cfg.FileSettings.Directory + "teams/" + team.Id + "/channels/" + channel1.Id + "/users/" + user1.Id + "/" + fileId + "_thumb.jpg" path = utils.Cfg.FileSettings.Directory + "teams/" + team.Id + "/channels/" + channel.Id + "/users/" + user.Id + "/" + fileId + "_thumb.jpg"
if err := os.Remove(path); err != nil { if err := os.Remove(path); err != nil {
t.Fatal("Couldn't remove file at " + path) t.Fatal("Couldn't remove file at " + path)
} }
path = utils.Cfg.FileSettings.Directory + "teams/" + team.Id + "/channels/" + channel1.Id + "/users/" + user1.Id + "/" + fileId + "_preview.jpg" path = utils.Cfg.FileSettings.Directory + "teams/" + team.Id + "/channels/" + channel.Id + "/users/" + user.Id + "/" + fileId + "_preview.jpg"
if err := os.Remove(path); err != nil { if err := os.Remove(path); err != nil {
t.Fatal("Couldn't remove file at " + path) t.Fatal("Couldn't remove file at " + path)
} }
@@ -137,25 +132,18 @@ func TestUploadFile(t *testing.T) {
} }
func TestGetFile(t *testing.T) { func TestGetFile(t *testing.T) {
Setup() th := Setup().InitBasic()
Client := th.BasicClient
team := th.BasicTeam
user := th.BasicUser
channel := th.BasicChannel
enablePublicLink := utils.Cfg.FileSettings.EnablePublicLink enablePublicLink := utils.Cfg.FileSettings.EnablePublicLink
defer func() { defer func() {
utils.Cfg.FileSettings.EnablePublicLink = enablePublicLink utils.Cfg.FileSettings.EnablePublicLink = enablePublicLink
}() }()
utils.Cfg.FileSettings.EnablePublicLink = true utils.Cfg.FileSettings.EnablePublicLink = true
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN}
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user1.Id))
Client.LoginByEmail(team.Name, user1.Email, "pwd")
channel1 := &model.Channel{DisplayName: "Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel)
if utils.Cfg.FileSettings.DriverName != "" { if utils.Cfg.FileSettings.DriverName != "" {
body := &bytes.Buffer{} body := &bytes.Buffer{}
writer := multipart.NewWriter(body) writer := multipart.NewWriter(body)
@@ -181,7 +169,7 @@ func TestGetFile(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
_, err = field.Write([]byte(channel1.Id)) _, err = field.Write([]byte(channel.Id))
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@@ -191,7 +179,7 @@ func TestGetFile(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
resp, upErr := Client.UploadFile("/files/upload", body.Bytes(), writer.FormDataContentType()) resp, upErr := Client.UploadPostAttachment(body.Bytes(), writer.FormDataContentType())
if upErr != nil { if upErr != nil {
t.Fatal(upErr) t.Fatal(upErr)
} }
@@ -217,8 +205,9 @@ func TestGetFile(t *testing.T) {
team2 := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} team2 := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN}
team2 = Client.Must(Client.CreateTeam(team2)).Data.(*model.Team) team2 = Client.Must(Client.CreateTeam(team2)).Data.(*model.Team)
user2 := &model.User{TeamId: team2.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"} user2 := &model.User{Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User) user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User)
LinkUserToTeam(user2, team2)
store.Must(Srv.Store.User().VerifyEmail(user2.Id)) store.Must(Srv.Store.User().VerifyEmail(user2.Id))
newProps := make(map[string]string) newProps := make(map[string]string)
@@ -229,6 +218,7 @@ func TestGetFile(t *testing.T) {
hash := model.HashPassword(fmt.Sprintf("%v:%v", data, utils.Cfg.FileSettings.PublicLinkSalt)) hash := model.HashPassword(fmt.Sprintf("%v:%v", data, utils.Cfg.FileSettings.PublicLinkSalt))
Client.LoginByEmail(team2.Name, user2.Email, "pwd") Client.LoginByEmail(team2.Name, user2.Email, "pwd")
Client.SetTeamId(team2.Id)
if _, downErr := Client.GetFile(filenames[0]+"?d="+url.QueryEscape(data)+"&h="+url.QueryEscape(hash)+"&t="+team.Id, false); downErr != nil { if _, downErr := Client.GetFile(filenames[0]+"?d="+url.QueryEscape(data)+"&h="+url.QueryEscape(hash)+"&t="+team.Id, false); downErr != nil {
t.Fatal(downErr) t.Fatal(downErr)
@@ -278,17 +268,17 @@ func TestGetFile(t *testing.T) {
filename := filenames[len(filenames)-2] + "/" + filenames[len(filenames)-1] filename := filenames[len(filenames)-2] + "/" + filenames[len(filenames)-1]
fileId := strings.Split(filename, ".")[0] fileId := strings.Split(filename, ".")[0]
err = bucket.Del("teams/" + team.Id + "/channels/" + channel1.Id + "/users/" + user1.Id + "/" + filename) err = bucket.Del("teams/" + team.Id + "/channels/" + channel.Id + "/users/" + user.Id + "/" + filename)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
err = bucket.Del("teams/" + team.Id + "/channels/" + channel1.Id + "/users/" + user1.Id + "/" + fileId + "_thumb.jpg") err = bucket.Del("teams/" + team.Id + "/channels/" + channel.Id + "/users/" + user.Id + "/" + fileId + "_thumb.jpg")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
err = bucket.Del("teams/" + team.Id + "/channels/" + channel1.Id + "/users/" + user1.Id + "/" + fileId + "_preview.jpg") err = bucket.Del("teams/" + team.Id + "/channels/" + channel.Id + "/users/" + user.Id + "/" + fileId + "_preview.jpg")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@@ -297,17 +287,17 @@ func TestGetFile(t *testing.T) {
filename := filenames[len(filenames)-2] + "/" + filenames[len(filenames)-1] filename := filenames[len(filenames)-2] + "/" + filenames[len(filenames)-1]
fileId := strings.Split(filename, ".")[0] fileId := strings.Split(filename, ".")[0]
path := utils.Cfg.FileSettings.Directory + "teams/" + team.Id + "/channels/" + channel1.Id + "/users/" + user1.Id + "/" + filename path := utils.Cfg.FileSettings.Directory + "teams/" + team.Id + "/channels/" + channel.Id + "/users/" + user.Id + "/" + filename
if err := os.Remove(path); err != nil { if err := os.Remove(path); err != nil {
t.Fatal("Couldn't remove file at " + path) t.Fatal("Couldn't remove file at " + path)
} }
path = utils.Cfg.FileSettings.Directory + "teams/" + team.Id + "/channels/" + channel1.Id + "/users/" + user1.Id + "/" + fileId + "_thumb.jpg" path = utils.Cfg.FileSettings.Directory + "teams/" + team.Id + "/channels/" + channel.Id + "/users/" + user.Id + "/" + fileId + "_thumb.jpg"
if err := os.Remove(path); err != nil { if err := os.Remove(path); err != nil {
t.Fatal("Couldn't remove file at " + path) t.Fatal("Couldn't remove file at " + path)
} }
path = utils.Cfg.FileSettings.Directory + "teams/" + team.Id + "/channels/" + channel1.Id + "/users/" + user1.Id + "/" + fileId + "_preview.jpg" path = utils.Cfg.FileSettings.Directory + "teams/" + team.Id + "/channels/" + channel.Id + "/users/" + user.Id + "/" + fileId + "_preview.jpg"
if err := os.Remove(path); err != nil { if err := os.Remove(path); err != nil {
t.Fatal("Couldn't remove file at " + path) t.Fatal("Couldn't remove file at " + path)
} }
@@ -320,25 +310,18 @@ func TestGetFile(t *testing.T) {
} }
func TestGetPublicLink(t *testing.T) { func TestGetPublicLink(t *testing.T) {
Setup() th := Setup().InitBasic()
Client := th.BasicClient
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} team := th.BasicTeam
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team) user := th.BasicUser
channel := th.BasicChannel
user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user1.Id))
user2 := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user2.Id))
Client.LoginByEmail(team.Name, user1.Email, "pwd")
channel1 := &model.Channel{DisplayName: "Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel)
if utils.Cfg.FileSettings.DriverName != "" { if utils.Cfg.FileSettings.DriverName != "" {
enablePublicLink := utils.Cfg.FileSettings.EnablePublicLink
defer func() {
utils.Cfg.FileSettings.EnablePublicLink = enablePublicLink
}()
utils.Cfg.FileSettings.EnablePublicLink = true
body := &bytes.Buffer{} body := &bytes.Buffer{}
writer := multipart.NewWriter(body) writer := multipart.NewWriter(body)
@@ -364,7 +347,7 @@ func TestGetPublicLink(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
_, err = field.Write([]byte(channel1.Id)) _, err = field.Write([]byte(channel.Id))
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@@ -374,14 +357,14 @@ func TestGetPublicLink(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
resp, upErr := Client.UploadFile("/files/upload", body.Bytes(), writer.FormDataContentType()) resp, upErr := Client.UploadPostAttachment(body.Bytes(), writer.FormDataContentType())
if upErr != nil { if upErr != nil {
t.Fatal(upErr) t.Fatal(upErr)
} }
filenames := resp.Data.(*model.FileUploadResponse).Filenames filenames := resp.Data.(*model.FileUploadResponse).Filenames
post1 := &model.Post{ChannelId: channel1.Id, Message: "a" + model.NewId() + "a", Filenames: filenames} post1 := &model.Post{ChannelId: channel.Id, Message: "a" + model.NewId() + "a", Filenames: filenames}
rpost1, postErr := Client.CreatePost(post1) rpost1, postErr := Client.CreatePost(post1)
if postErr != nil { if postErr != nil {
@@ -408,7 +391,8 @@ func TestGetPublicLink(t *testing.T) {
t.Fatal("Should have errored - bad file path") t.Fatal("Should have errored - bad file path")
} }
Client.LoginByEmail(team.Name, user2.Email, "pwd") th.LoginBasic2()
data["filename"] = filenames[0] data["filename"] = filenames[0]
if _, err := Client.GetPublicLink(data); err == nil { if _, err := Client.GetPublicLink(data); err == nil {
t.Fatal("should have errored, user not member of channel") t.Fatal("should have errored, user not member of channel")
@@ -427,17 +411,17 @@ func TestGetPublicLink(t *testing.T) {
filename := filenames[len(filenames)-2] + "/" + filenames[len(filenames)-1] filename := filenames[len(filenames)-2] + "/" + filenames[len(filenames)-1]
fileId := strings.Split(filename, ".")[0] fileId := strings.Split(filename, ".")[0]
err = bucket.Del("teams/" + team.Id + "/channels/" + channel1.Id + "/users/" + user1.Id + "/" + filename) err = bucket.Del("teams/" + team.Id + "/channels/" + channel.Id + "/users/" + user.Id + "/" + filename)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
err = bucket.Del("teams/" + team.Id + "/channels/" + channel1.Id + "/users/" + user1.Id + "/" + fileId + "_thumb.jpg") err = bucket.Del("teams/" + team.Id + "/channels/" + channel.Id + "/users/" + user.Id + "/" + fileId + "_thumb.jpg")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
err = bucket.Del("teams/" + team.Id + "/channels/" + channel1.Id + "/users/" + user1.Id + "/" + fileId + "_preview.jpg") err = bucket.Del("teams/" + team.Id + "/channels/" + channel.Id + "/users/" + user.Id + "/" + fileId + "_preview.jpg")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@@ -446,17 +430,17 @@ func TestGetPublicLink(t *testing.T) {
filename := filenames[len(filenames)-2] + "/" + filenames[len(filenames)-1] filename := filenames[len(filenames)-2] + "/" + filenames[len(filenames)-1]
fileId := strings.Split(filename, ".")[0] fileId := strings.Split(filename, ".")[0]
path := utils.Cfg.FileSettings.Directory + "teams/" + team.Id + "/channels/" + channel1.Id + "/users/" + user1.Id + "/" + filename path := utils.Cfg.FileSettings.Directory + "teams/" + team.Id + "/channels/" + channel.Id + "/users/" + user.Id + "/" + filename
if err := os.Remove(path); err != nil { if err := os.Remove(path); err != nil {
t.Fatal("Couldn't remove file at " + path) t.Fatal("Couldn't remove file at " + path)
} }
path = utils.Cfg.FileSettings.Directory + "teams/" + team.Id + "/channels/" + channel1.Id + "/users/" + user1.Id + "/" + fileId + "_thumb.jpg" path = utils.Cfg.FileSettings.Directory + "teams/" + team.Id + "/channels/" + channel.Id + "/users/" + user.Id + "/" + fileId + "_thumb.jpg"
if err := os.Remove(path); err != nil { if err := os.Remove(path); err != nil {
t.Fatal("Couldn't remove file at " + path) t.Fatal("Couldn't remove file at " + path)
} }
path = utils.Cfg.FileSettings.Directory + "teams/" + team.Id + "/channels/" + channel1.Id + "/users/" + user1.Id + "/" + fileId + "_preview.jpg" path = utils.Cfg.FileSettings.Directory + "teams/" + team.Id + "/channels/" + channel.Id + "/users/" + user.Id + "/" + fileId + "_preview.jpg"
if err := os.Remove(path); err != nil { if err := os.Remove(path); err != nil {
t.Fatal("Couldn't remove file at " + path) t.Fatal("Couldn't remove file at " + path)
} }

Просмотреть файл

@@ -22,7 +22,7 @@ func ImportPost(post *model.Post) {
} }
} }
func ImportUser(user *model.User) *model.User { func ImportUser(teamId string, user *model.User) *model.User {
user.MakeNonNil() user.MakeNonNil()
if result := <-Srv.Store.User().Save(user); result.Err != nil { if result := <-Srv.Store.User().Save(user); result.Err != nil {
@@ -31,8 +31,8 @@ func ImportUser(user *model.User) *model.User {
} else { } else {
ruser := result.Data.(*model.User) ruser := result.Data.(*model.User)
if err := JoinDefaultChannels(ruser, ""); err != nil { if err := JoinDefaultChannels(teamId, ruser, ""); err != nil {
l4g.Error(utils.T("api.import.import_user.joining_default.error"), ruser.Id, ruser.TeamId, err) l4g.Error(utils.T("api.import.import_user.joining_default.error"), ruser.Id, teamId, err)
} }
if cresult := <-Srv.Store.User().VerifyEmail(ruser.Id); cresult.Err != nil { if cresult := <-Srv.Store.User().VerifyEmail(ruser.Id); cresult.Err != nil {

Просмотреть файл

@@ -6,7 +6,6 @@ package api
import ( import (
"bytes" "bytes"
l4g "github.com/alecthomas/log4go" l4g "github.com/alecthomas/log4go"
"github.com/gorilla/mux"
"github.com/mattermost/platform/model" "github.com/mattermost/platform/model"
"github.com/mattermost/platform/utils" "github.com/mattermost/platform/utils"
"io" "io"
@@ -19,13 +18,12 @@ const (
INVALID_LICENSE_ERROR = "api.license.add_license.invalid.app_error" INVALID_LICENSE_ERROR = "api.license.add_license.invalid.app_error"
) )
func InitLicense(r *mux.Router) { func InitLicense() {
l4g.Debug(utils.T("api.license.init.debug")) l4g.Debug(utils.T("api.license.init.debug"))
sr := r.PathPrefix("/license").Subrouter() BaseRoutes.License.Handle("/add", ApiAdminSystemRequired(addLicense)).Methods("POST")
sr.Handle("/add", ApiAdminSystemRequired(addLicense)).Methods("POST") BaseRoutes.License.Handle("/remove", ApiAdminSystemRequired(removeLicense)).Methods("POST")
sr.Handle("/remove", ApiAdminSystemRequired(removeLicense)).Methods("POST") BaseRoutes.License.Handle("/client_config", ApiAppHandler(getClientLicenceConfig)).Methods("GET")
sr.Handle("/client_config", ApiAppHandler(getClientLicenceConfig)).Methods("GET")
} }
func LoadLicense() { func LoadLicense() {

Просмотреть файл

@@ -9,7 +9,8 @@ import (
) )
func TestGetLicenceConfig(t *testing.T) { func TestGetLicenceConfig(t *testing.T) {
Setup() th := Setup().InitBasic()
Client := th.BasicClient
if result, err := Client.GetClientLicenceConfig(""); err != nil { if result, err := Client.GetClientLicenceConfig(""); err != nil {
t.Fatal(err) t.Fatal(err)

Просмотреть файл

@@ -4,7 +4,10 @@
package api package api
import ( import (
"crypto/tls"
b64 "encoding/base64"
"fmt" "fmt"
"io"
"net/http" "net/http"
"net/url" "net/url"
"strconv" "strconv"
@@ -12,31 +15,29 @@ import (
l4g "github.com/alecthomas/log4go" l4g "github.com/alecthomas/log4go"
"github.com/gorilla/mux" "github.com/gorilla/mux"
"github.com/mattermost/platform/einterfaces"
"github.com/mattermost/platform/model" "github.com/mattermost/platform/model"
"github.com/mattermost/platform/utils" "github.com/mattermost/platform/utils"
) )
func InitOAuth(r *mux.Router) { func InitOAuth() {
l4g.Debug(utils.T("api.oauth.init.debug")) l4g.Debug(utils.T("api.oauth.init.debug"))
sr := r.PathPrefix("/oauth").Subrouter() BaseRoutes.OAuth.Handle("/register", ApiUserRequired(registerOAuthApp)).Methods("POST")
BaseRoutes.OAuth.Handle("/allow", ApiUserRequired(allowOAuth)).Methods("GET")
BaseRoutes.OAuth.Handle("/{service:[A-Za-z]+}/complete", AppHandlerIndependent(completeOAuth)).Methods("GET")
BaseRoutes.OAuth.Handle("/{service:[A-Za-z]+}/login", AppHandlerIndependent(loginWithOAuth)).Methods("GET")
BaseRoutes.OAuth.Handle("/{service:[A-Za-z]+}/signup", AppHandlerIndependent(signupWithOAuth)).Methods("GET")
BaseRoutes.OAuth.Handle("/authorize", ApiUserRequired(authorizeOAuth)).Methods("GET")
BaseRoutes.OAuth.Handle("/access_token", ApiAppHandler(getAccessToken)).Methods("POST")
sr.Handle("/register", ApiUserRequired(registerOAuthApp)).Methods("POST") BaseRoutes.Root.Handle("/authorize", ApiUserRequired(authorizeOAuth)).Methods("GET")
sr.Handle("/allow", ApiUserRequired(allowOAuth)).Methods("GET") BaseRoutes.Root.Handle("/access_token", ApiAppHandler(getAccessToken)).Methods("POST")
sr.Handle("/{service:[A-Za-z]+}/complete", AppHandlerIndependent(completeOAuth)).Methods("GET")
sr.Handle("/{service:[A-Za-z]+}/login", AppHandlerIndependent(loginWithOAuth)).Methods("GET")
sr.Handle("/{service:[A-Za-z]+}/signup", AppHandlerIndependent(signupWithOAuth)).Methods("GET")
sr.Handle("/authorize", ApiUserRequired(authorizeOAuth)).Methods("GET")
sr.Handle("/access_token", ApiAppHandler(getAccessToken)).Methods("POST")
mr := Srv.Router
mr.Handle("/authorize", ApiUserRequired(authorizeOAuth)).Methods("GET")
mr.Handle("/access_token", ApiAppHandler(getAccessToken)).Methods("POST")
// Handle all the old routes, to be later removed // Handle all the old routes, to be later removed
mr.Handle("/{service:[A-Za-z]+}/complete", AppHandlerIndependent(completeOAuth)).Methods("GET") BaseRoutes.Root.Handle("/{service:[A-Za-z]+}/complete", AppHandlerIndependent(completeOAuth)).Methods("GET")
mr.Handle("/signup/{service:[A-Za-z]+}/complete", AppHandlerIndependent(completeOAuth)).Methods("GET") BaseRoutes.Root.Handle("/signup/{service:[A-Za-z]+}/complete", AppHandlerIndependent(completeOAuth)).Methods("GET")
mr.Handle("/login/{service:[A-Za-z]+}/complete", AppHandlerIndependent(completeOAuth)).Methods("GET") BaseRoutes.Root.Handle("/login/{service:[A-Za-z]+}/complete", AppHandlerIndependent(completeOAuth)).Methods("GET")
} }
func registerOAuthApp(c *Context, w http.ResponseWriter, r *http.Request) { func registerOAuthApp(c *Context, w http.ResponseWriter, r *http.Request) {
@@ -190,40 +191,40 @@ func completeOAuth(c *Context, w http.ResponseWriter, r *http.Request) {
uri := c.GetSiteURL() + "/signup/" + service + "/complete" uri := c.GetSiteURL() + "/signup/" + service + "/complete"
if body, team, props, err := AuthorizeOAuthUser(service, code, state, uri); err != nil { if body, teamId, props, err := AuthorizeOAuthUser(service, code, state, uri); err != nil {
c.Err = err c.Err = err
return return
} else { } else {
action := props["action"] action := props["action"]
switch action { switch action {
case model.OAUTH_ACTION_SIGNUP: case model.OAUTH_ACTION_SIGNUP:
CreateOAuthUser(c, w, r, service, body, team) CreateOAuthUser(c, w, r, service, body, teamId)
if c.Err == nil { if c.Err == nil {
http.Redirect(w, r, GetProtocol(r)+"://"+r.Host+"/"+team.Name, http.StatusTemporaryRedirect) http.Redirect(w, r, GetProtocol(r)+"://"+r.Host, http.StatusTemporaryRedirect)
} }
break break
case model.OAUTH_ACTION_LOGIN: case model.OAUTH_ACTION_LOGIN:
LoginByOAuth(c, w, r, service, body, team) LoginByOAuth(c, w, r, service, body)
if c.Err == nil { if c.Err == nil {
http.Redirect(w, r, GetProtocol(r)+"://"+r.Host+"/"+team.Name, http.StatusTemporaryRedirect) http.Redirect(w, r, GetProtocol(r)+"://"+r.Host, http.StatusTemporaryRedirect)
} }
break break
case model.OAUTH_ACTION_EMAIL_TO_SSO: case model.OAUTH_ACTION_EMAIL_TO_SSO:
CompleteSwitchWithOAuth(c, w, r, service, body, team, props["email"]) CompleteSwitchWithOAuth(c, w, r, service, body, props["email"])
if c.Err == nil { if c.Err == nil {
http.Redirect(w, r, GetProtocol(r)+"://"+r.Host+"/"+team.Name+"/login?extra=signin_change", http.StatusTemporaryRedirect) http.Redirect(w, r, GetProtocol(r)+"://"+r.Host+"/login?extra=signin_change", http.StatusTemporaryRedirect)
} }
break break
case model.OAUTH_ACTION_SSO_TO_EMAIL: case model.OAUTH_ACTION_SSO_TO_EMAIL:
LoginByOAuth(c, w, r, service, body, team) LoginByOAuth(c, w, r, service, body)
if c.Err == nil { if c.Err == nil {
http.Redirect(w, r, GetProtocol(r)+"://"+r.Host+"/"+team.Name+"/"+"/claim?email="+url.QueryEscape(props["email"]), http.StatusTemporaryRedirect) http.Redirect(w, r, GetProtocol(r)+"://"+r.Host+"/claim?email="+url.QueryEscape(props["email"]), http.StatusTemporaryRedirect)
} }
break break
default: default:
LoginByOAuth(c, w, r, service, body, team) LoginByOAuth(c, w, r, service, body)
if c.Err == nil { if c.Err == nil {
http.Redirect(w, r, GetProtocol(r)+"://"+r.Host+"/"+team.Name, http.StatusTemporaryRedirect) http.Redirect(w, r, GetProtocol(r)+"://"+r.Host, http.StatusTemporaryRedirect)
} }
break break
} }
@@ -257,7 +258,7 @@ func authorizeOAuth(c *Context, w http.ResponseWriter, r *http.Request) {
} }
var team *model.Team var team *model.Team
if result := <-Srv.Store.Team().Get(c.Session.TeamId); result.Err != nil { if result := <-Srv.Store.Team().Get(c.TeamId); result.Err != nil {
c.Err = result.Err c.Err = result.Err
return return
} else { } else {
@@ -389,7 +390,7 @@ func getAccessToken(c *Context, w http.ResponseWriter, r *http.Request) {
user = result.Data.(*model.User) user = result.Data.(*model.User)
} }
session := &model.Session{UserId: user.Id, TeamId: user.TeamId, Roles: user.Roles, IsOAuth: true} session := &model.Session{UserId: user.Id, Roles: user.Roles, IsOAuth: true}
if result := <-Srv.Store.Session().Save(session); result.Err != nil { if result := <-Srv.Store.Session().Save(session); result.Err != nil {
c.Err = model.NewLocAppError("getAccessToken", "web.get_access_token.internal_session.app_error", nil, "") c.Err = model.NewLocAppError("getAccessToken", "web.get_access_token.internal_session.app_error", nil, "")
@@ -422,24 +423,11 @@ func loginWithOAuth(c *Context, w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r) params := mux.Vars(r)
service := params["service"] service := params["service"]
loginHint := r.URL.Query().Get("login_hint") loginHint := r.URL.Query().Get("login_hint")
teamName := r.URL.Query().Get("team")
if len(teamName) == 0 {
c.Err = model.NewLocAppError("loginWithOAuth", "web.login_with_oauth.invalid_team.app_error", nil, "team_name="+teamName)
c.Err.StatusCode = http.StatusBadRequest
return
}
// Make sure team exists
if result := <-Srv.Store.Team().GetByName(teamName); result.Err != nil {
c.Err = result.Err
return
}
stateProps := map[string]string{} stateProps := map[string]string{}
stateProps["action"] = model.OAUTH_ACTION_LOGIN stateProps["action"] = model.OAUTH_ACTION_LOGIN
if authUrl, err := GetAuthorizationCode(c, service, teamName, stateProps, loginHint); err != nil { if authUrl, err := GetAuthorizationCode(c, service, stateProps, loginHint); err != nil {
c.Err = err c.Err = err
return return
} else { } else {
@@ -450,31 +438,19 @@ func loginWithOAuth(c *Context, w http.ResponseWriter, r *http.Request) {
func signupWithOAuth(c *Context, w http.ResponseWriter, r *http.Request) { func signupWithOAuth(c *Context, w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r) params := mux.Vars(r)
service := params["service"] service := params["service"]
teamName := r.URL.Query().Get("team")
if !utils.Cfg.TeamSettings.EnableUserCreation { if !utils.Cfg.TeamSettings.EnableUserCreation {
c.Err = model.NewLocAppError("signupTeam", "web.singup_with_oauth.disabled.app_error", nil, "") c.Err = model.NewLocAppError("signupWithOAuth", "web.singup_with_oauth.disabled.app_error", nil, "")
c.Err.StatusCode = http.StatusNotImplemented c.Err.StatusCode = http.StatusNotImplemented
return return
} }
if len(teamName) == 0 {
c.Err = model.NewLocAppError("signupWithOAuth", "web.singup_with_oauth.invalid_team.app_error", nil, "team_name="+teamName)
c.Err.StatusCode = http.StatusBadRequest
return
}
hash := r.URL.Query().Get("h") hash := r.URL.Query().Get("h")
var team *model.Team teamId := ""
if result := <-Srv.Store.Team().GetByName(teamName); result.Err != nil { inviteId := r.URL.Query().Get("id")
c.Err = result.Err
return
} else {
team = result.Data.(*model.Team)
}
if IsVerifyHashRequired(nil, team, hash) { if len(hash) > 0 {
data := r.URL.Query().Get("d") data := r.URL.Query().Get("d")
props := model.MapFromJson(strings.NewReader(data)) props := model.MapFromJson(strings.NewReader(data))
@@ -489,19 +465,173 @@ func signupWithOAuth(c *Context, w http.ResponseWriter, r *http.Request) {
return return
} }
if team.Id != props["id"] { teamId = props["id"]
c.Err = model.NewLocAppError("signupWithOAuth", "web.singup_with_oauth.invalid_team.app_error", nil, data) } else if len(inviteId) != 0 {
return if result := <-Srv.Store.Team().GetByInviteId(inviteId); result.Err != nil {
// soft fail, so we still create user but don't auto-join team
l4g.Error("%v", result.Err)
} else {
teamId = result.Data.(*model.Team).Id
} }
} }
stateProps := map[string]string{} stateProps := map[string]string{}
stateProps["action"] = model.OAUTH_ACTION_SIGNUP stateProps["action"] = model.OAUTH_ACTION_SIGNUP
if len(teamId) != 0 {
stateProps["team_id"] = teamId
}
if authUrl, err := GetAuthorizationCode(c, service, teamName, stateProps, ""); err != nil { if authUrl, err := GetAuthorizationCode(c, service, stateProps, ""); err != nil {
c.Err = err c.Err = err
return return
} else { } else {
http.Redirect(w, r, authUrl, http.StatusFound) http.Redirect(w, r, authUrl, http.StatusFound)
} }
} }
func GetAuthorizationCode(c *Context, service string, props map[string]string, loginHint string) (string, *model.AppError) {
sso := utils.Cfg.GetSSOService(service)
if sso != nil && !sso.Enable {
return "", model.NewLocAppError("GetAuthorizationCode", "api.user.get_authorization_code.unsupported.app_error", nil, "service="+service)
}
clientId := sso.Id
endpoint := sso.AuthEndpoint
scope := sso.Scope
props["hash"] = model.HashPassword(clientId)
state := b64.StdEncoding.EncodeToString([]byte(model.MapToJson(props)))
redirectUri := c.GetSiteURL() + "/signup/" + service + "/complete"
authUrl := endpoint + "?response_type=code&client_id=" + clientId + "&redirect_uri=" + url.QueryEscape(redirectUri) + "&state=" + url.QueryEscape(state)
if len(scope) > 0 {
authUrl += "&scope=" + utils.UrlEncode(scope)
}
if len(loginHint) > 0 {
authUrl += "&login_hint=" + utils.UrlEncode(loginHint)
}
return authUrl, nil
}
func AuthorizeOAuthUser(service, code, state, redirectUri string) (io.ReadCloser, string, map[string]string, *model.AppError) {
sso := utils.Cfg.GetSSOService(service)
if sso == nil || !sso.Enable {
return nil, "", nil, model.NewLocAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.unsupported.app_error", nil, "service="+service)
}
stateStr := ""
if b, err := b64.StdEncoding.DecodeString(state); err != nil {
return nil, "", nil, model.NewLocAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.invalid_state.app_error", nil, err.Error())
} else {
stateStr = string(b)
}
stateProps := model.MapFromJson(strings.NewReader(stateStr))
if !model.ComparePassword(stateProps["hash"], sso.Id) {
return nil, "", nil, model.NewLocAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.invalid_state.app_error", nil, "")
}
teamId := stateProps["team_id"]
p := url.Values{}
p.Set("client_id", sso.Id)
p.Set("client_secret", sso.Secret)
p.Set("code", code)
p.Set("grant_type", model.ACCESS_TOKEN_GRANT_TYPE)
p.Set("redirect_uri", redirectUri)
tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: *utils.Cfg.ServiceSettings.EnableInsecureOutgoingConnections},
}
client := &http.Client{Transport: tr}
req, _ := http.NewRequest("POST", sso.TokenEndpoint, strings.NewReader(p.Encode()))
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.Header.Set("Accept", "application/json")
var ar *model.AccessResponse
if resp, err := client.Do(req); err != nil {
return nil, "", nil, model.NewLocAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.token_failed.app_error", nil, err.Error())
} else {
ar = model.AccessResponseFromJson(resp.Body)
if ar == nil {
return nil, "", nil, model.NewLocAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.bad_response.app_error", nil, "")
}
}
if strings.ToLower(ar.TokenType) != model.ACCESS_TOKEN_TYPE {
return nil, "", nil, model.NewLocAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.bad_token.app_error", nil, "token_type="+ar.TokenType)
}
if len(ar.AccessToken) == 0 {
return nil, "", nil, model.NewLocAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.missing.app_error", nil, "")
}
p = url.Values{}
p.Set("access_token", ar.AccessToken)
req, _ = http.NewRequest("GET", sso.UserApiEndpoint, strings.NewReader(""))
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.Header.Set("Accept", "application/json")
req.Header.Set("Authorization", "Bearer "+ar.AccessToken)
if resp, err := client.Do(req); err != nil {
return nil, "", nil, model.NewLocAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.service.app_error",
map[string]interface{}{"Service": service}, err.Error())
} else {
return resp.Body, teamId, stateProps, nil
}
}
func CompleteSwitchWithOAuth(c *Context, w http.ResponseWriter, r *http.Request, service string, userData io.ReadCloser, email string) {
authData := ""
ssoEmail := ""
provider := einterfaces.GetOauthProvider(service)
if provider == nil {
c.Err = model.NewLocAppError("CompleteClaimWithOAuth", "api.user.complete_switch_with_oauth.unavailable.app_error",
map[string]interface{}{"Service": service}, "")
return
} else {
ssoUser := provider.GetUserFromJson(userData)
authData = ssoUser.AuthData
ssoEmail = ssoUser.Email
}
if len(authData) == 0 {
c.Err = model.NewLocAppError("CompleteClaimWithOAuth", "api.user.complete_switch_with_oauth.parse.app_error",
map[string]interface{}{"Service": service}, "")
return
}
if len(email) == 0 {
c.Err = model.NewLocAppError("CompleteClaimWithOAuth", "api.user.complete_switch_with_oauth.blank_email.app_error", nil, "")
return
}
var user *model.User
if result := <-Srv.Store.User().GetByEmail(email); result.Err != nil {
c.Err = result.Err
return
} else {
user = result.Data.(*model.User)
}
RevokeAllSession(c, user.Id)
if c.Err != nil {
return
}
if result := <-Srv.Store.User().UpdateAuthData(user.Id, service, authData, ssoEmail); result.Err != nil {
c.Err = result.Err
return
}
sendSignInChangeEmailAndForget(c, user.Email, c.GetSiteURL(), strings.Title(service)+" SSO")
}

Просмотреть файл

@@ -5,22 +5,14 @@ package api
import ( import (
"github.com/mattermost/platform/model" "github.com/mattermost/platform/model"
"github.com/mattermost/platform/store"
"github.com/mattermost/platform/utils" "github.com/mattermost/platform/utils"
"net/url" "net/url"
"strings"
"testing" "testing"
) )
func TestRegisterApp(t *testing.T) { func TestRegisterApp(t *testing.T) {
Setup() th := Setup().InitBasic()
Client := th.BasicClient
team := model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN}
rteam, _ := Client.CreateTeam(&team)
user := model.User{TeamId: rteam.Data.(*model.Team).Id, Email: strings.ToLower(model.NewId()) + "success+test@simulator.amazonses.com", Password: "pwd"}
ruser := Client.Must(Client.CreateUser(&user, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(ruser.Id))
app := &model.OAuthApp{Name: "TestApp" + model.NewId(), Homepage: "https://nowhere.com", Description: "test", CallbackUrls: []string{"https://nowhere.com"}} app := &model.OAuthApp{Name: "TestApp" + model.NewId(), Homepage: "https://nowhere.com", Description: "test", CallbackUrls: []string{"https://nowhere.com"}}
@@ -38,7 +30,7 @@ func TestRegisterApp(t *testing.T) {
t.Fatal("not logged in - should have failed") t.Fatal("not logged in - should have failed")
} }
Client.Must(Client.LoginById(ruser.Id, "pwd")) th.LoginBasic()
if result, err := Client.RegisterApp(app); err != nil { if result, err := Client.RegisterApp(app); err != nil {
t.Fatal(err) t.Fatal(err)
@@ -70,19 +62,11 @@ func TestRegisterApp(t *testing.T) {
} }
func TestAllowOAuth(t *testing.T) { func TestAllowOAuth(t *testing.T) {
Setup() th := Setup().InitBasic()
Client := th.BasicClient
team := model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN}
rteam, _ := Client.CreateTeam(&team)
user := model.User{TeamId: rteam.Data.(*model.Team).Id, Email: strings.ToLower(model.NewId()) + "success+test@simulator.amazonses.com", Password: "pwd"}
ruser := Client.Must(Client.CreateUser(&user, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(ruser.Id))
app := &model.OAuthApp{Name: "TestApp" + model.NewId(), Homepage: "https://nowhere.com", Description: "test", CallbackUrls: []string{"https://nowhere.com"}} app := &model.OAuthApp{Name: "TestApp" + model.NewId(), Homepage: "https://nowhere.com", Description: "test", CallbackUrls: []string{"https://nowhere.com"}}
Client.Must(Client.LoginById(ruser.Id, "pwd"))
state := "123" state := "123"
if !utils.Cfg.ServiceSettings.EnableOAuthServiceProvider { if !utils.Cfg.ServiceSettings.EnableOAuthServiceProvider {

Просмотреть файл

@@ -22,21 +22,21 @@ import (
"time" "time"
) )
func InitPost(r *mux.Router) { func InitPost() {
l4g.Debug(utils.T("api.post.init.debug")) l4g.Debug(utils.T("api.post.init.debug"))
r.Handle("/posts/search", ApiUserRequired(searchPosts)).Methods("GET") BaseRoutes.NeedTeam.Handle("/posts/search", ApiUserRequired(searchPosts)).Methods("GET")
r.Handle("/posts/{post_id}", ApiUserRequired(getPostById)).Methods("GET") BaseRoutes.NeedTeam.Handle("/posts/{post_id}", ApiUserRequired(getPostById)).Methods("GET")
sr := r.PathPrefix("/channels/{id:[A-Za-z0-9]+}").Subrouter() BaseRoutes.Posts.Handle("/create", ApiUserRequired(createPost)).Methods("POST")
sr.Handle("/create", ApiUserRequired(createPost)).Methods("POST") BaseRoutes.Posts.Handle("/update", ApiUserRequired(updatePost)).Methods("POST")
sr.Handle("/update", ApiUserRequired(updatePost)).Methods("POST") BaseRoutes.Posts.Handle("/page/{offset:[0-9]+}/{limit:[0-9]+}", ApiUserRequiredActivity(getPosts, false)).Methods("GET")
sr.Handle("/posts/{offset:[0-9]+}/{limit:[0-9]+}", ApiUserRequiredActivity(getPosts, false)).Methods("GET") BaseRoutes.Posts.Handle("/since/{time:[0-9]+}", ApiUserRequiredActivity(getPostsSince, false)).Methods("GET")
sr.Handle("/posts/{time:[0-9]+}", ApiUserRequiredActivity(getPostsSince, false)).Methods("GET")
sr.Handle("/post/{post_id:[A-Za-z0-9]+}", ApiUserRequired(getPost)).Methods("GET") BaseRoutes.NeedPost.Handle("/get", ApiUserRequired(getPost)).Methods("GET")
sr.Handle("/post/{post_id:[A-Za-z0-9]+}/delete", ApiUserRequired(deletePost)).Methods("POST") BaseRoutes.NeedPost.Handle("/delete", ApiUserRequired(deletePost)).Methods("POST")
sr.Handle("/post/{post_id:[A-Za-z0-9]+}/before/{offset:[0-9]+}/{num_posts:[0-9]+}", ApiUserRequired(getPostsBefore)).Methods("GET") BaseRoutes.NeedPost.Handle("/before/{offset:[0-9]+}/{num_posts:[0-9]+}", ApiUserRequired(getPostsBefore)).Methods("GET")
sr.Handle("/post/{post_id:[A-Za-z0-9]+}/after/{offset:[0-9]+}/{num_posts:[0-9]+}", ApiUserRequired(getPostsAfter)).Methods("GET") BaseRoutes.NeedPost.Handle("/after/{offset:[0-9]+}/{num_posts:[0-9]+}", ApiUserRequired(getPostsAfter)).Methods("GET")
} }
func createPost(c *Context, w http.ResponseWriter, r *http.Request) { func createPost(c *Context, w http.ResponseWriter, r *http.Request) {
@@ -47,7 +47,7 @@ func createPost(c *Context, w http.ResponseWriter, r *http.Request) {
} }
// Create and save post object to channel // Create and save post object to channel
cchan := Srv.Store.Channel().CheckPermissionsTo(c.Session.TeamId, post.ChannelId, c.Session.UserId) cchan := Srv.Store.Channel().CheckPermissionsTo(c.TeamId, post.ChannelId, c.Session.UserId)
if !c.HasPermissionsToChannel(cchan, "createPost") { if !c.HasPermissionsToChannel(cchan, "createPost") {
return return
@@ -228,15 +228,16 @@ func CreateWebhookPost(c *Context, channelId, text, overrideUsername, overrideIc
func handlePostEventsAndForget(c *Context, post *model.Post, triggerWebhooks bool) { func handlePostEventsAndForget(c *Context, post *model.Post, triggerWebhooks bool) {
go func() { go func() {
tchan := Srv.Store.Team().Get(c.Session.TeamId) tchan := Srv.Store.Team().Get(c.TeamId)
cchan := Srv.Store.Channel().Get(post.ChannelId) cchan := Srv.Store.Channel().Get(post.ChannelId)
uchan := Srv.Store.User().Get(post.UserId) uchan := Srv.Store.User().Get(post.UserId)
pchan := Srv.Store.User().GetProfiles(c.Session.TeamId) pchan := Srv.Store.User().GetProfiles(c.TeamId)
dpchan := Srv.Store.User().GetDirectProfiles(c.Session.UserId)
mchan := Srv.Store.Channel().GetMembers(post.ChannelId) mchan := Srv.Store.Channel().GetMembers(post.ChannelId)
var team *model.Team var team *model.Team
if result := <-tchan; result.Err != nil { if result := <-tchan; result.Err != nil {
l4g.Error(utils.T("api.post.handle_post_events_and_forget.team.error"), c.Session.TeamId, result.Err) l4g.Error(utils.T("api.post.handle_post_events_and_forget.team.error"), c.TeamId, result.Err)
return return
} else { } else {
team = result.Data.(*model.Team) team = result.Data.(*model.Team)
@@ -252,12 +253,22 @@ func handlePostEventsAndForget(c *Context, post *model.Post, triggerWebhooks boo
var profiles map[string]*model.User var profiles map[string]*model.User
if result := <-pchan; result.Err != nil { if result := <-pchan; result.Err != nil {
l4g.Error(utils.T("api.post.handle_post_events_and_forget.profiles.error"), c.Session.TeamId, result.Err) l4g.Error(utils.T("api.post.handle_post_events_and_forget.profiles.error"), c.TeamId, result.Err)
return return
} else { } else {
profiles = result.Data.(map[string]*model.User) profiles = result.Data.(map[string]*model.User)
} }
if result := <-dpchan; result.Err != nil {
l4g.Error(utils.T("api.post.handle_post_events_and_forget.profiles.error"), c.TeamId, result.Err)
return
} else {
dps := result.Data.(map[string]*model.User)
for k, v := range dps {
profiles[k] = v
}
}
var members []model.ChannelMember var members []model.ChannelMember
if result := <-mchan; result.Err != nil { if result := <-mchan; result.Err != nil {
l4g.Error(utils.T("api.post.handle_post_events_and_forget.members.error"), post.ChannelId, result.Err) l4g.Error(utils.T("api.post.handle_post_events_and_forget.members.error"), post.ChannelId, result.Err)
@@ -282,7 +293,7 @@ func handlePostEventsAndForget(c *Context, post *model.Post, triggerWebhooks boo
} }
if channel.Type == model.CHANNEL_DIRECT { if channel.Type == model.CHANNEL_DIRECT {
go makeDirectChannelVisible(c.Session.TeamId, post.ChannelId) go makeDirectChannelVisible(c.TeamId, post.ChannelId)
} }
}() }()
} }
@@ -352,7 +363,7 @@ func handleWebhookEventsAndForget(c *Context, post *model.Post, team *model.Team
return return
} }
hchan := Srv.Store.Webhook().GetOutgoingByTeam(c.Session.TeamId) hchan := Srv.Store.Webhook().GetOutgoingByTeam(c.TeamId)
hooks := []*model.OutgoingWebhook{} hooks := []*model.OutgoingWebhook{}
@@ -416,8 +427,25 @@ func handleWebhookEventsAndForget(c *Context, post *model.Post, team *model.Team
respProps := model.MapFromJson(resp.Body) respProps := model.MapFromJson(resp.Body)
// copy the context and create a mock session for posting the message // copy the context and create a mock session for posting the message
mockSession := model.Session{UserId: hook.CreatorId, TeamId: hook.TeamId, IsOAuth: false} mockSession := model.Session{
newContext := &Context{mockSession, model.NewId(), "", c.Path, nil, c.teamURLValid, c.teamURL, c.siteURL, c.T, c.Locale} UserId: hook.CreatorId,
TeamMembers: []*model.TeamMember{{TeamId: hook.TeamId, UserId: hook.CreatorId}},
IsOAuth: false,
}
newContext := &Context{
Session: mockSession,
RequestId: model.NewId(),
IpAddress: "",
Path: c.Path,
Err: nil,
teamURLValid: c.teamURLValid,
teamURL: c.teamURL,
siteURL: c.siteURL,
T: c.T,
Locale: c.Locale,
TeamId: hook.TeamId,
}
if text, ok := respProps["text"]; ok { if text, ok := respProps["text"]; ok {
if _, err := CreateWebhookPost(newContext, post.ChannelId, text, respProps["username"], respProps["icon_url"], post.Props, post.Type); err != nil { if _, err := CreateWebhookPost(newContext, post.ChannelId, text, respProps["username"], respProps["icon_url"], post.Props, post.Type); err != nil {
@@ -706,7 +734,7 @@ func sendNotifications(c *Context, post *model.Post, team *model.Team, channel *
TLSClientConfig: &tls.Config{InsecureSkipVerify: *utils.Cfg.ServiceSettings.EnableInsecureOutgoingConnections}, TLSClientConfig: &tls.Config{InsecureSkipVerify: *utils.Cfg.ServiceSettings.EnableInsecureOutgoingConnections},
} }
httpClient := &http.Client{Transport: tr} httpClient := &http.Client{Transport: tr}
request, _ := http.NewRequest("POST", *utils.Cfg.EmailSettings.PushNotificationServer+"/api/v1/send_push", strings.NewReader(msg.ToJson())) request, _ := http.NewRequest("POST", *utils.Cfg.EmailSettings.PushNotificationServer+model.API_URL_SUFFIX_V1+"/send_push", strings.NewReader(msg.ToJson()))
l4g.Debug(utils.T("api.post.send_notifications_and_forget.push_notification.debug"), msg.DeviceId, msg.Message) l4g.Debug(utils.T("api.post.send_notifications_and_forget.push_notification.debug"), msg.DeviceId, msg.Message)
if _, err := httpClient.Do(request); err != nil { if _, err := httpClient.Do(request); err != nil {
@@ -719,7 +747,7 @@ func sendNotifications(c *Context, post *model.Post, team *model.Team, channel *
} }
} }
message := model.NewMessage(c.Session.TeamId, post.ChannelId, post.UserId, model.ACTION_POSTED) message := model.NewMessage(c.TeamId, post.ChannelId, post.UserId, model.ACTION_POSTED)
message.Add("post", post.ToJson()) message.Add("post", post.ToJson())
message.Add("channel_type", channel.Type) message.Add("channel_type", channel.Type)
@@ -780,7 +808,7 @@ func checkForOutOfChannelMentions(c *Context, post *model.Post, channel *model.C
} }
SendEphemeralPost( SendEphemeralPost(
c.Session.TeamId, c.TeamId,
post.UserId, post.UserId,
&model.Post{ &model.Post{
ChannelId: post.ChannelId, ChannelId: post.ChannelId,
@@ -847,7 +875,7 @@ func updatePost(c *Context, w http.ResponseWriter, r *http.Request) {
return return
} }
cchan := Srv.Store.Channel().CheckPermissionsTo(c.Session.TeamId, post.ChannelId, c.Session.UserId) cchan := Srv.Store.Channel().CheckPermissionsTo(c.TeamId, post.ChannelId, c.Session.UserId)
pchan := Srv.Store.Post().Get(post.Id) pchan := Srv.Store.Post().Get(post.Id)
if !c.HasPermissionsToChannel(cchan, "updatePost") { if !c.HasPermissionsToChannel(cchan, "updatePost") {
@@ -889,7 +917,7 @@ func updatePost(c *Context, w http.ResponseWriter, r *http.Request) {
} else { } else {
rpost := result.Data.(*model.Post) rpost := result.Data.(*model.Post)
message := model.NewMessage(c.Session.TeamId, rpost.ChannelId, c.Session.UserId, model.ACTION_POST_EDITED) message := model.NewMessage(c.TeamId, rpost.ChannelId, c.Session.UserId, model.ACTION_POST_EDITED)
message.Add("post", rpost.ToJson()) message.Add("post", rpost.ToJson())
PublishAndForget(message) PublishAndForget(message)
@@ -901,7 +929,7 @@ func updatePost(c *Context, w http.ResponseWriter, r *http.Request) {
func getPosts(c *Context, w http.ResponseWriter, r *http.Request) { func getPosts(c *Context, w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r) params := mux.Vars(r)
id := params["id"] id := params["channel_id"]
if len(id) != 26 { if len(id) != 26 {
c.SetInvalidParam("getPosts", "channelId") c.SetInvalidParam("getPosts", "channelId")
return return
@@ -919,7 +947,7 @@ func getPosts(c *Context, w http.ResponseWriter, r *http.Request) {
return return
} }
cchan := Srv.Store.Channel().CheckPermissionsTo(c.Session.TeamId, id, c.Session.UserId) cchan := Srv.Store.Channel().CheckPermissionsTo(c.TeamId, id, c.Session.UserId)
etagChan := Srv.Store.Post().GetEtag(id) etagChan := Srv.Store.Post().GetEtag(id)
if !c.HasPermissionsToChannel(cchan, "getPosts") { if !c.HasPermissionsToChannel(cchan, "getPosts") {
@@ -949,7 +977,7 @@ func getPosts(c *Context, w http.ResponseWriter, r *http.Request) {
func getPostsSince(c *Context, w http.ResponseWriter, r *http.Request) { func getPostsSince(c *Context, w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r) params := mux.Vars(r)
id := params["id"] id := params["channel_id"]
if len(id) != 26 { if len(id) != 26 {
c.SetInvalidParam("getPostsSince", "channelId") c.SetInvalidParam("getPostsSince", "channelId")
return return
@@ -961,7 +989,7 @@ func getPostsSince(c *Context, w http.ResponseWriter, r *http.Request) {
return return
} }
cchan := Srv.Store.Channel().CheckPermissionsTo(c.Session.TeamId, id, c.Session.UserId) cchan := Srv.Store.Channel().CheckPermissionsTo(c.TeamId, id, c.Session.UserId)
pchan := Srv.Store.Post().GetPostsSince(id, time) pchan := Srv.Store.Post().GetPostsSince(id, time)
if !c.HasPermissionsToChannel(cchan, "getPostsSince") { if !c.HasPermissionsToChannel(cchan, "getPostsSince") {
@@ -982,7 +1010,7 @@ func getPostsSince(c *Context, w http.ResponseWriter, r *http.Request) {
func getPost(c *Context, w http.ResponseWriter, r *http.Request) { func getPost(c *Context, w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r) params := mux.Vars(r)
channelId := params["id"] channelId := params["channel_id"]
if len(channelId) != 26 { if len(channelId) != 26 {
c.SetInvalidParam("getPost", "channelId") c.SetInvalidParam("getPost", "channelId")
return return
@@ -994,7 +1022,7 @@ func getPost(c *Context, w http.ResponseWriter, r *http.Request) {
return return
} }
cchan := Srv.Store.Channel().CheckPermissionsTo(c.Session.TeamId, channelId, c.Session.UserId) cchan := Srv.Store.Channel().CheckPermissionsTo(c.TeamId, channelId, c.Session.UserId)
pchan := Srv.Store.Post().Get(postId) pchan := Srv.Store.Post().Get(postId)
if !c.HasPermissionsToChannel(cchan, "getPost") { if !c.HasPermissionsToChannel(cchan, "getPost") {
@@ -1041,7 +1069,7 @@ func getPostById(c *Context, w http.ResponseWriter, r *http.Request) {
} }
post := list.Posts[list.Order[0]] post := list.Posts[list.Order[0]]
cchan := Srv.Store.Channel().CheckPermissionsTo(c.Session.TeamId, post.ChannelId, c.Session.UserId) cchan := Srv.Store.Channel().CheckPermissionsTo(c.TeamId, post.ChannelId, c.Session.UserId)
if !c.HasPermissionsToChannel(cchan, "getPostById") { if !c.HasPermissionsToChannel(cchan, "getPostById") {
return return
} }
@@ -1058,7 +1086,7 @@ func getPostById(c *Context, w http.ResponseWriter, r *http.Request) {
func deletePost(c *Context, w http.ResponseWriter, r *http.Request) { func deletePost(c *Context, w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r) params := mux.Vars(r)
channelId := params["id"] channelId := params["channel_id"]
if len(channelId) != 26 { if len(channelId) != 26 {
c.SetInvalidParam("deletePost", "channelId") c.SetInvalidParam("deletePost", "channelId")
return return
@@ -1070,7 +1098,7 @@ func deletePost(c *Context, w http.ResponseWriter, r *http.Request) {
return return
} }
cchan := Srv.Store.Channel().CheckPermissionsTo(c.Session.TeamId, channelId, c.Session.UserId) cchan := Srv.Store.Channel().CheckPermissionsTo(c.TeamId, channelId, c.Session.UserId)
pchan := Srv.Store.Post().Get(postId) pchan := Srv.Store.Post().Get(postId)
if result := <-pchan; result.Err != nil { if result := <-pchan; result.Err != nil {
@@ -1106,11 +1134,11 @@ func deletePost(c *Context, w http.ResponseWriter, r *http.Request) {
return return
} }
message := model.NewMessage(c.Session.TeamId, post.ChannelId, c.Session.UserId, model.ACTION_POST_DELETED) message := model.NewMessage(c.TeamId, post.ChannelId, c.Session.UserId, model.ACTION_POST_DELETED)
message.Add("post", post.ToJson()) message.Add("post", post.ToJson())
PublishAndForget(message) PublishAndForget(message)
DeletePostFilesAndForget(c.Session.TeamId, post) DeletePostFilesAndForget(c.TeamId, post)
result := make(map[string]string) result := make(map[string]string)
result["id"] = postId result["id"] = postId
@@ -1146,7 +1174,7 @@ func getPostsAfter(c *Context, w http.ResponseWriter, r *http.Request) {
func getPostsBeforeOrAfter(c *Context, w http.ResponseWriter, r *http.Request, before bool) { func getPostsBeforeOrAfter(c *Context, w http.ResponseWriter, r *http.Request, before bool) {
params := mux.Vars(r) params := mux.Vars(r)
id := params["id"] id := params["channel_id"]
if len(id) != 26 { if len(id) != 26 {
c.SetInvalidParam("getPostsBeforeOrAfter", "channelId") c.SetInvalidParam("getPostsBeforeOrAfter", "channelId")
return return
@@ -1170,7 +1198,7 @@ func getPostsBeforeOrAfter(c *Context, w http.ResponseWriter, r *http.Request, b
return return
} }
cchan := Srv.Store.Channel().CheckPermissionsTo(c.Session.TeamId, id, c.Session.UserId) cchan := Srv.Store.Channel().CheckPermissionsTo(c.TeamId, id, c.Session.UserId)
// We can do better than this etag in this situation // We can do better than this etag in this situation
etagChan := Srv.Store.Post().GetEtag(id) etagChan := Srv.Store.Post().GetEtag(id)
@@ -1215,7 +1243,7 @@ func searchPosts(c *Context, w http.ResponseWriter, r *http.Request) {
for _, params := range paramsList { for _, params := range paramsList {
// don't allow users to search for everything // don't allow users to search for everything
if params.Terms != "*" { if params.Terms != "*" {
channels = append(channels, Srv.Store.Post().Search(c.Session.TeamId, c.Session.UserId, params)) channels = append(channels, Srv.Store.Post().Search(c.TeamId, c.Session.UserId, params))
} }
} }

Просмотреть файл

@@ -16,7 +16,10 @@ func BenchmarkCreatePost(b *testing.B) {
var ( var (
NUM_POSTS_RANGE = utils.Range{NUM_POSTS, NUM_POSTS} NUM_POSTS_RANGE = utils.Range{NUM_POSTS, NUM_POSTS}
) )
_, _, channel := SetupBenchmark()
th := Setup().InitBasic()
Client := th.BasicClient
channel := th.BasicChannel
testPoster := NewAutoPostCreator(Client, channel.Id) testPoster := NewAutoPostCreator(Client, channel.Id)
@@ -32,7 +35,10 @@ func BenchmarkUpdatePost(b *testing.B) {
NUM_POSTS_RANGE = utils.Range{NUM_POSTS, NUM_POSTS} NUM_POSTS_RANGE = utils.Range{NUM_POSTS, NUM_POSTS}
UPDATE_POST_LEN = 100 UPDATE_POST_LEN = 100
) )
_, _, channel := SetupBenchmark()
th := Setup().InitBasic()
Client := th.BasicClient
channel := th.BasicChannel
testPoster := NewAutoPostCreator(Client, channel.Id) testPoster := NewAutoPostCreator(Client, channel.Id)
posts, valid := testPoster.CreateTestPosts(NUM_POSTS_RANGE) posts, valid := testPoster.CreateTestPosts(NUM_POSTS_RANGE)
@@ -59,7 +65,10 @@ func BenchmarkGetPosts(b *testing.B) {
var ( var (
NUM_POSTS_RANGE = utils.Range{NUM_POSTS, NUM_POSTS} NUM_POSTS_RANGE = utils.Range{NUM_POSTS, NUM_POSTS}
) )
_, _, channel := SetupBenchmark()
th := Setup().InitBasic()
Client := th.BasicClient
channel := th.BasicChannel
testPoster := NewAutoPostCreator(Client, channel.Id) testPoster := NewAutoPostCreator(Client, channel.Id)
testPoster.CreateTestPosts(NUM_POSTS_RANGE) testPoster.CreateTestPosts(NUM_POSTS_RANGE)
@@ -75,7 +84,10 @@ func BenchmarkSearchPosts(b *testing.B) {
var ( var (
NUM_POSTS_RANGE = utils.Range{NUM_POSTS, NUM_POSTS} NUM_POSTS_RANGE = utils.Range{NUM_POSTS, NUM_POSTS}
) )
_, _, channel := SetupBenchmark()
th := Setup().InitBasic()
Client := th.BasicClient
channel := th.BasicChannel
testPoster := NewAutoPostCreator(Client, channel.Id) testPoster := NewAutoPostCreator(Client, channel.Id)
testPoster.CreateTestPosts(NUM_POSTS_RANGE) testPoster.CreateTestPosts(NUM_POSTS_RANGE)
@@ -93,7 +105,10 @@ func BenchmarkEtagCache(b *testing.B) {
var ( var (
NUM_POSTS_RANGE = utils.Range{NUM_POSTS, NUM_POSTS} NUM_POSTS_RANGE = utils.Range{NUM_POSTS, NUM_POSTS}
) )
_, _, channel := SetupBenchmark()
th := Setup().InitBasic()
Client := th.BasicClient
channel := th.BasicChannel
testPoster := NewAutoPostCreator(Client, channel.Id) testPoster := NewAutoPostCreator(Client, channel.Id)
testPoster.CreateTestPosts(NUM_POSTS_RANGE) testPoster.CreateTestPosts(NUM_POSTS_RANGE)
@@ -111,7 +126,10 @@ func BenchmarkDeletePosts(b *testing.B) {
var ( var (
NUM_POSTS_RANGE = utils.Range{NUM_POSTS, NUM_POSTS} NUM_POSTS_RANGE = utils.Range{NUM_POSTS, NUM_POSTS}
) )
_, _, channel := SetupBenchmark()
th := Setup().InitBasic()
Client := th.BasicClient
channel := th.BasicChannel
testPoster := NewAutoPostCreator(Client, channel.Id) testPoster := NewAutoPostCreator(Client, channel.Id)
posts, valid := testPoster.CreateTestPosts(NUM_POSTS_RANGE) posts, valid := testPoster.CreateTestPosts(NUM_POSTS_RANGE)

Просмотреть файл

@@ -5,38 +5,24 @@ package api
import ( import (
"github.com/mattermost/platform/model" "github.com/mattermost/platform/model"
"github.com/mattermost/platform/store"
"github.com/mattermost/platform/utils" "github.com/mattermost/platform/utils"
"net/http" "net/http"
"strings" //"strings"
"fmt"
"testing" "testing"
"time" "time"
) )
func TestCreatePost(t *testing.T) { func TestCreatePost(t *testing.T) {
Setup() th := Setup().InitBasic()
Client := th.BasicClient
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} team := th.BasicTeam
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team) team2 := th.CreateTeam(th.BasicClient)
user1 := th.BasicUser
team2 := &model.Team{DisplayName: "Name Team 2", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} user3 := th.CreateUser(th.BasicClient)
team2 = Client.Must(Client.CreateTeam(team2)).Data.(*model.Team) LinkUserToTeam(user3, team2)
channel1 := th.BasicChannel
user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"} channel2 := th.CreateChannel(Client, team)
user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user1.Id))
user2 := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user2.Id))
Client.LoginByEmail(team.Name, user1.Email, "pwd")
channel1 := &model.Channel{DisplayName: "Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel)
channel2 := &model.Channel{DisplayName: "Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
channel2 = Client.Must(Client.CreateChannel(channel2)).Data.(*model.Channel)
filenames := []string{"/12345678901234567890123456/12345678901234567890123456/12345678901234567890123456/test.png", "/" + channel1.Id + "/" + user1.Id + "/test.png", "www.mattermost.com/fake/url", "junk"} filenames := []string{"/12345678901234567890123456/12345678901234567890123456/12345678901234567890123456/test.png", "/" + channel1.Id + "/" + user1.Id + "/test.png", "www.mattermost.com/fake/url", "junk"}
@@ -97,21 +83,17 @@ func TestCreatePost(t *testing.T) {
t.Fatal("Should have been forbidden") t.Fatal("Should have been forbidden")
} }
Client.LoginByEmail(team.Name, user2.Email, "pwd") th.LoginBasic2()
post7 := &model.Post{ChannelId: channel1.Id, Message: "a" + model.NewId() + "a"} post7 := &model.Post{ChannelId: channel1.Id, Message: "a" + model.NewId() + "a"}
_, err = Client.CreatePost(post7) _, err = Client.CreatePost(post7)
if err.StatusCode != http.StatusForbidden { if err.StatusCode != http.StatusForbidden {
t.Fatal("Should have been forbidden") t.Fatal("Should have been forbidden")
} }
user3 := &model.User{TeamId: team2.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"} Client.LoginByEmail(team2.Name, user3.Email, user3.Password)
user3 = Client.Must(Client.CreateUser(user3, "")).Data.(*model.User) Client.SetTeamId(team2.Id)
store.Must(Srv.Store.User().VerifyEmail(user3.Id)) channel3 := th.CreateChannel(Client, team2)
Client.LoginByEmail(team2.Name, user3.Email, "pwd")
channel3 := &model.Channel{DisplayName: "Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team2.Id}
channel3 = Client.Must(Client.CreateChannel(channel3)).Data.(*model.Channel)
post8 := &model.Post{ChannelId: channel1.Id, Message: "a" + model.NewId() + "a"} post8 := &model.Post{ChannelId: channel1.Id, Message: "a" + model.NewId() + "a"}
_, err = Client.CreatePost(post8) _, err = Client.CreatePost(post8)
@@ -125,29 +107,9 @@ func TestCreatePost(t *testing.T) {
} }
func TestUpdatePost(t *testing.T) { func TestUpdatePost(t *testing.T) {
Setup() th := Setup().InitBasic()
Client := th.BasicClient
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} channel1 := th.BasicChannel
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
team2 := &model.Team{DisplayName: "Name Team 2", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN}
team2 = Client.Must(Client.CreateTeam(team2)).Data.(*model.Team)
user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user1.Id))
user2 := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user2.Id))
Client.LoginByEmail(team.Name, user1.Email, "pwd")
channel1 := &model.Channel{DisplayName: "Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel)
channel2 := &model.Channel{DisplayName: "Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
channel2 = Client.Must(Client.CreateChannel(channel2)).Data.(*model.Channel)
post1 := &model.Post{ChannelId: channel1.Id, Message: "a" + model.NewId() + "a"} post1 := &model.Post{ChannelId: channel1.Id, Message: "a" + model.NewId() + "a"}
rpost1, err := Client.CreatePost(post1) rpost1, err := Client.CreatePost(post1)
@@ -196,19 +158,9 @@ func TestUpdatePost(t *testing.T) {
} }
func TestGetPosts(t *testing.T) { func TestGetPosts(t *testing.T) {
Setup() th := Setup().InitBasic()
Client := th.BasicClient
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} channel1 := th.BasicChannel
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user1.Id))
Client.LoginByEmail(team.Name, user1.Email, "pwd")
channel1 := &model.Channel{DisplayName: "TestGetPosts", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel)
time.Sleep(10 * time.Millisecond) time.Sleep(10 * time.Millisecond)
post1 := &model.Post{ChannelId: channel1.Id, Message: "a" + model.NewId() + "a"} post1 := &model.Post{ChannelId: channel1.Id, Message: "a" + model.NewId() + "a"}
@@ -261,19 +213,9 @@ func TestGetPosts(t *testing.T) {
} }
func TestGetPostsSince(t *testing.T) { func TestGetPostsSince(t *testing.T) {
Setup() th := Setup().InitBasic()
Client := th.BasicClient
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} channel1 := th.BasicChannel
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user1.Id))
Client.LoginByEmail(team.Name, user1.Email, "pwd")
channel1 := &model.Channel{DisplayName: "TestGetPosts", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel)
time.Sleep(10 * time.Millisecond) time.Sleep(10 * time.Millisecond)
post0 := &model.Post{ChannelId: channel1.Id, Message: "a" + model.NewId() + "a"} post0 := &model.Post{ChannelId: channel1.Id, Message: "a" + model.NewId() + "a"}
@@ -331,19 +273,9 @@ func TestGetPostsSince(t *testing.T) {
} }
func TestGetPostsBeforeAfter(t *testing.T) { func TestGetPostsBeforeAfter(t *testing.T) {
Setup() th := Setup().InitBasic()
Client := th.BasicClient
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} channel1 := th.BasicChannel
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user1.Id))
Client.LoginByEmail(team.Name, user1.Email, "pwd")
channel1 := &model.Channel{DisplayName: "TestGetPosts", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel)
time.Sleep(10 * time.Millisecond) time.Sleep(10 * time.Millisecond)
post0 := &model.Post{ChannelId: channel1.Id, Message: "a" + model.NewId() + "a"} post0 := &model.Post{ChannelId: channel1.Id, Message: "a" + model.NewId() + "a"}
@@ -379,7 +311,8 @@ func TestGetPostsBeforeAfter(t *testing.T) {
t.Fatal("wrong order") t.Fatal("wrong order")
} }
if len(r1.Posts) != 2 { if len(r1.Posts) != 3 {
t.Log(r1.Posts)
t.Fatal("wrong size") t.Fatal("wrong size")
} }
@@ -408,19 +341,9 @@ func TestGetPostsBeforeAfter(t *testing.T) {
} }
func TestSearchPosts(t *testing.T) { func TestSearchPosts(t *testing.T) {
Setup() th := Setup().InitBasic()
Client := th.BasicClient
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} channel1 := th.BasicChannel
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user1.Id))
Client.LoginByEmail(team.Name, user1.Email, "pwd")
channel1 := &model.Channel{DisplayName: "TestGetPosts", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel)
post1 := &model.Post{ChannelId: channel1.Id, Message: "search for post1"} post1 := &model.Post{ChannelId: channel1.Id, Message: "search for post1"}
post1 = Client.Must(Client.CreatePost(post1)).Data.(*model.Post) post1 = Client.Must(Client.CreatePost(post1)).Data.(*model.Post)
@@ -458,19 +381,9 @@ func TestSearchPosts(t *testing.T) {
} }
func TestSearchHashtagPosts(t *testing.T) { func TestSearchHashtagPosts(t *testing.T) {
Setup() th := Setup().InitBasic()
Client := th.BasicClient
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} channel1 := th.BasicChannel
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user1.Id))
Client.LoginByEmail(team.Name, user1.Email, "pwd")
channel1 := &model.Channel{DisplayName: "TestGetPosts", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel)
post1 := &model.Post{ChannelId: channel1.Id, Message: "#sgtitlereview with space"} post1 := &model.Post{ChannelId: channel1.Id, Message: "#sgtitlereview with space"}
post1 = Client.Must(Client.CreatePost(post1)).Data.(*model.Post) post1 = Client.Must(Client.CreatePost(post1)).Data.(*model.Post)
@@ -489,19 +402,10 @@ func TestSearchHashtagPosts(t *testing.T) {
} }
func TestSearchPostsInChannel(t *testing.T) { func TestSearchPostsInChannel(t *testing.T) {
Setup() th := Setup().InitBasic()
Client := th.BasicClient
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} channel1 := th.BasicChannel
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team) team := th.BasicTeam
user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user1.Id))
Client.LoginByEmail(team.Name, user1.Email, "pwd")
channel1 := &model.Channel{DisplayName: "TestGetPosts", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel)
post1 := &model.Post{ChannelId: channel1.Id, Message: "sgtitlereview with space"} post1 := &model.Post{ChannelId: channel1.Id, Message: "sgtitlereview with space"}
post1 = Client.Must(Client.CreatePost(post1)).Data.(*model.Post) post1 = Client.Must(Client.CreatePost(post1)).Data.(*model.Post)
@@ -529,7 +433,7 @@ func TestSearchPostsInChannel(t *testing.T) {
t.Fatalf("wrong number of posts returned %v", len(result.Order)) t.Fatalf("wrong number of posts returned %v", len(result.Order))
} }
if result := Client.Must(Client.SearchPosts("channel:" + channel1.Name)).Data.(*model.PostList); len(result.Order) != 1 { if result := Client.Must(Client.SearchPosts("channel:" + channel1.Name)).Data.(*model.PostList); len(result.Order) != 2 {
t.Fatalf("wrong number of posts returned %v", len(result.Order)) t.Fatalf("wrong number of posts returned %v", len(result.Order))
} }
@@ -567,38 +471,29 @@ func TestSearchPostsInChannel(t *testing.T) {
} }
func TestSearchPostsFromUser(t *testing.T) { func TestSearchPostsFromUser(t *testing.T) {
Setup() th := Setup().InitBasic()
Client := th.BasicClient
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} channel1 := th.BasicChannel
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team) team := th.BasicTeam
user1 := th.BasicUser
user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"} user2 := th.BasicUser2
user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User) channel2 := th.CreateChannel(Client, team)
store.Must(Srv.Store.User().VerifyEmail(user1.Id)) Client.Must(Client.AddChannelMember(channel1.Id, th.BasicUser2.Id))
Client.Must(Client.AddChannelMember(channel2.Id, th.BasicUser2.Id))
Client.LoginByEmail(team.Name, user1.Email, "pwd") user3 := th.CreateUser(Client)
LinkUserToTeam(user3, team)
channel1 := &model.Channel{DisplayName: "TestGetPosts", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} Client.Must(Client.AddChannelMember(channel1.Id, user3.Id))
channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel) Client.Must(Client.AddChannelMember(channel2.Id, user3.Id))
channel2 := &model.Channel{DisplayName: "TestGetPosts", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
channel2 = Client.Must(Client.CreateChannel(channel2)).Data.(*model.Channel)
post1 := &model.Post{ChannelId: channel1.Id, Message: "sgtitlereview with space"} post1 := &model.Post{ChannelId: channel1.Id, Message: "sgtitlereview with space"}
post1 = Client.Must(Client.CreatePost(post1)).Data.(*model.Post) post1 = Client.Must(Client.CreatePost(post1)).Data.(*model.Post)
user2 := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"} th.LoginBasic2()
user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user2.Id))
Client.LoginByEmail(team.Name, user2.Email, "pwd")
Client.Must(Client.JoinChannel(channel1.Id))
Client.Must(Client.JoinChannel(channel2.Id))
post2 := &model.Post{ChannelId: channel2.Id, Message: "sgtitlereview\n with return"} post2 := &model.Post{ChannelId: channel2.Id, Message: "sgtitlereview\n with return"}
post2 = Client.Must(Client.CreatePost(post2)).Data.(*model.Post) post2 = Client.Must(Client.CreatePost(post2)).Data.(*model.Post)
if result := Client.Must(Client.SearchPosts("from: " + user1.Username)).Data.(*model.PostList); len(result.Order) != 1 { if result := Client.Must(Client.SearchPosts("from: " + user1.Username)).Data.(*model.PostList); len(result.Order) != 2 {
t.Fatalf("wrong number of posts returned %v", len(result.Order)) t.Fatalf("wrong number of posts returned %v", len(result.Order))
} }
@@ -617,13 +512,7 @@ func TestSearchPostsFromUser(t *testing.T) {
t.Fatalf("wrong number of posts returned %v", len(result.Order)) t.Fatalf("wrong number of posts returned %v", len(result.Order))
} }
user3 := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"} Client.LoginByEmail(team.Name, user3.Email, user3.Password)
user3 = Client.Must(Client.CreateUser(user3, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user3.Id))
Client.LoginByEmail(team.Name, user3.Email, "pwd")
Client.Must(Client.JoinChannel(channel1.Id))
Client.Must(Client.JoinChannel(channel2.Id))
// wait for the join/leave messages to be created for user3 since they're done asynchronously // wait for the join/leave messages to be created for user3 since they're done asynchronously
time.Sleep(100 * time.Millisecond) time.Sleep(100 * time.Millisecond)
@@ -649,19 +538,9 @@ func TestSearchPostsFromUser(t *testing.T) {
} }
func TestGetPostsCache(t *testing.T) { func TestGetPostsCache(t *testing.T) {
Setup() th := Setup().InitBasic()
Client := th.BasicClient
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} channel1 := th.BasicChannel
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user1.Id))
Client.LoginByEmail(team.Name, user1.Email, "pwd")
channel1 := &model.Channel{DisplayName: "TestGetPosts", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel)
time.Sleep(10 * time.Millisecond) time.Sleep(10 * time.Millisecond)
post1 := &model.Post{ChannelId: channel1.Id, Message: "a" + model.NewId() + "a"} post1 := &model.Post{ChannelId: channel1.Id, Message: "a" + model.NewId() + "a"}
@@ -698,23 +577,10 @@ func TestGetPostsCache(t *testing.T) {
} }
func TestDeletePosts(t *testing.T) { func TestDeletePosts(t *testing.T) {
Setup() th := Setup().InitBasic()
Client := th.BasicClient
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} channel1 := th.BasicChannel
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team) UpdateUserToTeamAdmin(th.BasicUser2, th.BasicTeam)
userAdmin := &model.User{TeamId: team.Id, Email: team.Email, Nickname: "Corey Hulen", Password: "pwd"}
userAdmin = Client.Must(Client.CreateUser(userAdmin, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(userAdmin.Id))
user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user1.Id))
Client.LoginByEmail(team.Name, user1.Email, "pwd")
channel1 := &model.Channel{DisplayName: "TestGetPosts", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel)
time.Sleep(10 * time.Millisecond) time.Sleep(10 * time.Millisecond)
post1 := &model.Post{ChannelId: channel1.Id, Message: "a" + model.NewId() + "a"} post1 := &model.Post{ChannelId: channel1.Id, Message: "a" + model.NewId() + "a"}
@@ -745,7 +611,7 @@ func TestDeletePosts(t *testing.T) {
r2 := Client.Must(Client.GetPosts(channel1.Id, 0, 10, "")).Data.(*model.PostList) r2 := Client.Must(Client.GetPosts(channel1.Id, 0, 10, "")).Data.(*model.PostList)
if len(r2.Posts) != 4 { if len(r2.Posts) != 5 {
t.Fatal("should have returned 4 items") t.Fatal("should have returned 4 items")
} }
@@ -753,27 +619,17 @@ func TestDeletePosts(t *testing.T) {
post4 := &model.Post{ChannelId: channel1.Id, Message: "a" + model.NewId() + "a"} post4 := &model.Post{ChannelId: channel1.Id, Message: "a" + model.NewId() + "a"}
post4 = Client.Must(Client.CreatePost(post4)).Data.(*model.Post) post4 = Client.Must(Client.CreatePost(post4)).Data.(*model.Post)
Client.LoginByEmail(team.Name, userAdmin.Email, "pwd") th.LoginBasic2()
Client.Must(Client.DeletePost(channel1.Id, post4.Id)) Client.Must(Client.DeletePost(channel1.Id, post4.Id))
} }
func TestEmailMention(t *testing.T) { func TestEmailMention(t *testing.T) {
Setup() th := Setup().InitBasic()
Client := th.BasicClient
channel1 := th.BasicChannel
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} post1 := &model.Post{ChannelId: channel1.Id, Message: th.BasicUser.Username}
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
user1 := &model.User{TeamId: team.Id, Email: "success+test@simulator.amazonses.com", Nickname: "Bob Bobby", Password: "pwd"}
user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user1.Id))
Client.LoginByEmail(team.Name, user1.Email, "pwd")
channel1 := &model.Channel{DisplayName: "TestGetPosts", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel)
post1 := &model.Post{ChannelId: channel1.Id, Message: "bob"}
post1 = Client.Must(Client.CreatePost(post1)).Data.(*model.Post) post1 = Client.Must(Client.CreatePost(post1)).Data.(*model.Post)
// No easy way to verify the email was sent, but this will at least cause the server to throw errors if the code is broken // No easy way to verify the email was sent, but this will at least cause the server to throw errors if the code is broken
@@ -781,19 +637,9 @@ func TestEmailMention(t *testing.T) {
} }
func TestFuzzyPosts(t *testing.T) { func TestFuzzyPosts(t *testing.T) {
Setup() th := Setup().InitBasic()
Client := th.BasicClient
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} channel1 := th.BasicChannel
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
user := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user.Id))
Client.LoginByEmail(team.Name, user.Email, "pwd")
channel1 := &model.Channel{DisplayName: "Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel)
filenames := []string{"junk"} filenames := []string{"junk"}
@@ -808,21 +654,13 @@ func TestFuzzyPosts(t *testing.T) {
} }
func TestMakeDirectChannelVisible(t *testing.T) { func TestMakeDirectChannelVisible(t *testing.T) {
Setup() th := Setup().InitBasic()
Client := th.BasicClient
team := th.BasicTeam
user1 := th.BasicUser
user2 := th.BasicUser2
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} th.LoginBasic2()
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user1.Id))
user2 := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user2.Id))
// user2 will be created with prefs created to show user1 in the sidebar so set that to false to get rid of it
Client.LoginByEmail(team.Name, user2.Email, "pwd")
preferences := &model.Preferences{ preferences := &model.Preferences{
{ {
@@ -834,9 +672,11 @@ func TestMakeDirectChannelVisible(t *testing.T) {
} }
Client.Must(Client.SetPreferences(preferences)) Client.Must(Client.SetPreferences(preferences))
Client.LoginByEmail(team.Name, user1.Email, "pwd") Client.Must(Client.Logout())
th.LoginBasic()
th.BasicClient.SetTeamId(team.Id)
channel := Client.Must(Client.CreateDirectChannel(map[string]string{"user_id": user2.Id})).Data.(*model.Channel) channel := Client.Must(Client.CreateDirectChannel(user2.Id)).Data.(*model.Channel)
makeDirectChannelVisible(team.Id, channel.Id) makeDirectChannelVisible(team.Id, channel.Id)
@@ -845,38 +685,17 @@ func TestMakeDirectChannelVisible(t *testing.T) {
} else if pref := result.Data.(*model.Preference); pref.Value != "true" { } else if pref := result.Data.(*model.Preference); pref.Value != "true" {
t.Fatal("Failed to set direct channel to be visible for user1") t.Fatal("Failed to set direct channel to be visible for user1")
} }
Client.LoginByEmail(team.Name, user2.Email, "pwd")
if result, err := Client.GetPreference(model.PREFERENCE_CATEGORY_DIRECT_CHANNEL_SHOW, user1.Id); err != nil {
t.Fatal("Errored trying to set direct channel to be visible for user2")
} else if pref := result.Data.(*model.Preference); pref.Value != "true" {
t.Fatal("Failed to set direct channel to be visible for user2")
}
} }
func TestGetOutOfChannelMentions(t *testing.T) { func TestGetOutOfChannelMentions(t *testing.T) {
Setup() th := Setup().InitBasic()
Client := th.BasicClient
team1 := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: strings.ToLower(model.NewId()) + "success+test@simulator.amazonses.com", Type: model.TEAM_OPEN} channel1 := th.BasicChannel
team1 = Client.Must(Client.CreateTeam(team1)).Data.(*model.Team) team1 := th.BasicTeam
user1 := th.BasicUser
user1 := &model.User{TeamId: team1.Id, Email: strings.ToLower(model.NewId()) + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd", Username: "user1"} user2 := th.BasicUser2
user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User) user3 := th.CreateUser(Client)
store.Must(Srv.Store.User().VerifyEmail(user1.Id)) LinkUserToTeam(user3, team1)
user2 := &model.User{TeamId: team1.Id, Email: strings.ToLower(model.NewId()) + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd", Username: "user2"}
user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user2.Id))
user3 := &model.User{TeamId: team1.Id, Email: strings.ToLower(model.NewId()) + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd", Username: "user3"}
user3 = Client.Must(Client.CreateUser(user3, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user3.Id))
Client.Must(Client.LoginByEmail(team1.Name, user1.Email, "pwd"))
channel1 := &model.Channel{DisplayName: "Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team1.Id}
channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel)
var allProfiles map[string]*model.User var allProfiles map[string]*model.User
if result := <-Srv.Store.User().GetProfiles(team1.Id); result.Err != nil { if result := <-Srv.Store.User().GetProfiles(team1.Id); result.Err != nil {
@@ -893,39 +712,37 @@ func TestGetOutOfChannelMentions(t *testing.T) {
} }
// test a post that doesn't @mention anybody // test a post that doesn't @mention anybody
post1 := &model.Post{ChannelId: channel1.Id, Message: "user1 user2 user3"} post1 := &model.Post{ChannelId: channel1.Id, Message: fmt.Sprintf("%v %v %v", user1.Username, user2.Username, user3.Username)}
if mentioned := getOutOfChannelMentions(post1, allProfiles, members); len(mentioned) != 0 { if mentioned := getOutOfChannelMentions(post1, allProfiles, members); len(mentioned) != 0 {
t.Fatalf("getOutOfChannelMentions returned %v when no users were mentioned", mentioned) t.Fatalf("getOutOfChannelMentions returned %v when no users were mentioned", mentioned)
} }
// test a post that @mentions someone in the channel // test a post that @mentions someone in the channel
post2 := &model.Post{ChannelId: channel1.Id, Message: "@user1 is user1"} post2 := &model.Post{ChannelId: channel1.Id, Message: fmt.Sprintf("@%v is %v", user1.Username, user1.Username)}
if mentioned := getOutOfChannelMentions(post2, allProfiles, members); len(mentioned) != 0 { if mentioned := getOutOfChannelMentions(post2, allProfiles, members); len(mentioned) != 0 {
t.Fatalf("getOutOfChannelMentions returned %v when only users in the channel were mentioned", mentioned) t.Fatalf("getOutOfChannelMentions returned %v when only users in the channel were mentioned", mentioned)
} }
// test a post that @mentions someone not in the channel // test a post that @mentions someone not in the channel
post3 := &model.Post{ChannelId: channel1.Id, Message: "@user2 and @user3 aren't in the channel"} post3 := &model.Post{ChannelId: channel1.Id, Message: fmt.Sprintf("@%v and @%v aren't in the channel", user2.Username, user3.Username)}
if mentioned := getOutOfChannelMentions(post3, allProfiles, members); len(mentioned) != 2 || (mentioned[0].Id != user2.Id && mentioned[0].Id != user3.Id) || (mentioned[1].Id != user2.Id && mentioned[1].Id != user3.Id) { if mentioned := getOutOfChannelMentions(post3, allProfiles, members); len(mentioned) != 2 || (mentioned[0].Id != user2.Id && mentioned[0].Id != user3.Id) || (mentioned[1].Id != user2.Id && mentioned[1].Id != user3.Id) {
t.Fatalf("getOutOfChannelMentions returned %v when two users outside the channel were mentioned", mentioned) t.Fatalf("getOutOfChannelMentions returned %v when two users outside the channel were mentioned", mentioned)
} }
// test a post that @mentions someone not in the channel as well as someone in the channel // test a post that @mentions someone not in the channel as well as someone in the channel
post4 := &model.Post{ChannelId: channel1.Id, Message: "@user2 and @user1 might be in the channel"} post4 := &model.Post{ChannelId: channel1.Id, Message: fmt.Sprintf("@%v and @%v might be in the channel", user2.Username, user1.Username)}
if mentioned := getOutOfChannelMentions(post4, allProfiles, members); len(mentioned) != 1 || mentioned[0].Id != user2.Id { if mentioned := getOutOfChannelMentions(post4, allProfiles, members); len(mentioned) != 1 || mentioned[0].Id != user2.Id {
t.Fatalf("getOutOfChannelMentions returned %v when someone in the channel and someone outside the channel were mentioned", mentioned) t.Fatalf("getOutOfChannelMentions returned %v when someone in the channel and someone outside the channel were mentioned", mentioned)
} }
Client.Must(Client.Logout()) Client.Must(Client.Logout())
team2 := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: strings.ToLower(model.NewId()) + "success+test@simulator.amazonses.com", Type: model.TEAM_OPEN} team2 := th.CreateTeam(Client)
team2 = Client.Must(Client.CreateTeam(team2)).Data.(*model.Team) user4 := th.CreateUser(Client)
LinkUserToTeam(user4, team2)
user4 := &model.User{TeamId: team2.Id, Email: strings.ToLower(model.NewId()) + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd", Username: "user4"} Client.Must(Client.LoginByEmail(team2.Name, user4.Email, user4.Password))
user4 = Client.Must(Client.CreateUser(user4, "")).Data.(*model.User) Client.SetTeamId(team2.Id)
store.Must(Srv.Store.User().VerifyEmail(user4.Id))
Client.Must(Client.LoginByEmail(team2.Name, user4.Email, "pwd"))
channel2 := &model.Channel{DisplayName: "Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team2.Id} channel2 := &model.Channel{DisplayName: "Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team2.Id}
channel2 = Client.Must(Client.CreateChannel(channel2)).Data.(*model.Channel) channel2 = Client.Must(Client.CreateChannel(channel2)).Data.(*model.Channel)
@@ -943,7 +760,7 @@ func TestGetOutOfChannelMentions(t *testing.T) {
} }
// test a post that @mentions someone on a different team // test a post that @mentions someone on a different team
post5 := &model.Post{ChannelId: channel2.Id, Message: "@user2 and @user3 might be in the channel"} post5 := &model.Post{ChannelId: channel2.Id, Message: fmt.Sprintf("@%v and @%v might be in the channel", user2.Username, user3.Username)}
if mentioned := getOutOfChannelMentions(post5, allProfiles, members); len(mentioned) != 0 { if mentioned := getOutOfChannelMentions(post5, allProfiles, members); len(mentioned) != 0 {
t.Fatalf("getOutOfChannelMentions returned %v when two users on a different team were mentioned", mentioned) t.Fatalf("getOutOfChannelMentions returned %v when two users on a different team were mentioned", mentioned)
} }

Просмотреть файл

@@ -11,14 +11,13 @@ import (
"net/http" "net/http"
) )
func InitPreference(r *mux.Router) { func InitPreference() {
l4g.Debug(utils.T("api.preference.init.debug")) l4g.Debug(utils.T("api.preference.init.debug"))
sr := r.PathPrefix("/preferences").Subrouter() BaseRoutes.Preferences.Handle("/", ApiUserRequired(getAllPreferences)).Methods("GET")
sr.Handle("/", ApiUserRequired(getAllPreferences)).Methods("GET") BaseRoutes.Preferences.Handle("/save", ApiUserRequired(savePreferences)).Methods("POST")
sr.Handle("/save", ApiUserRequired(savePreferences)).Methods("POST") BaseRoutes.Preferences.Handle("/{category:[A-Za-z0-9_]+}", ApiUserRequired(getPreferenceCategory)).Methods("GET")
sr.Handle("/{category:[A-Za-z0-9_]+}", ApiUserRequired(getPreferenceCategory)).Methods("GET") BaseRoutes.Preferences.Handle("/{category:[A-Za-z0-9_]+}/{name:[A-Za-z0-9_]+}", ApiUserRequired(getPreference)).Methods("GET")
sr.Handle("/{category:[A-Za-z0-9_]+}/{name:[A-Za-z0-9_]+}", ApiUserRequired(getPreference)).Methods("GET")
} }
func getAllPreferences(c *Context, w http.ResponseWriter, r *http.Request) { func getAllPreferences(c *Context, w http.ResponseWriter, r *http.Request) {
@@ -44,7 +43,7 @@ func savePreferences(c *Context, w http.ResponseWriter, r *http.Request) {
c.Err = model.NewLocAppError("savePreferences", "api.preference.save_preferences.set.app_error", nil, c.Err = model.NewLocAppError("savePreferences", "api.preference.save_preferences.set.app_error", nil,
c.T("api.preference.save_preferences.set_details.app_error", c.T("api.preference.save_preferences.set_details.app_error",
map[string]interface{}{"SessionUserId": c.Session.UserId, "PreferenceUserId": preference.UserId})) map[string]interface{}{"SessionUserId": c.Session.UserId, "PreferenceUserId": preference.UserId}))
c.Err.StatusCode = http.StatusUnauthorized c.Err.StatusCode = http.StatusForbidden
return return
} }
} }

Просмотреть файл

@@ -5,23 +5,13 @@ package api
import ( import (
"github.com/mattermost/platform/model" "github.com/mattermost/platform/model"
"github.com/mattermost/platform/store"
"testing" "testing"
) )
func TestGetAllPreferences(t *testing.T) { func TestGetAllPreferences(t *testing.T) {
Setup() th := Setup().InitBasic()
Client := th.BasicClient
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} user1 := th.BasicUser
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user1.Id))
user2 := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user2.Id))
category := model.NewId() category := model.NewId()
@@ -43,7 +33,6 @@ func TestGetAllPreferences(t *testing.T) {
}, },
} }
Client.LoginByEmail(team.Name, user1.Email, "pwd")
Client.Must(Client.SetPreferences(&preferences1)) Client.Must(Client.SetPreferences(&preferences1))
if result, err := Client.GetAllPreferences(); err != nil { if result, err := Client.GetAllPreferences(); err != nil {
@@ -52,27 +41,19 @@ func TestGetAllPreferences(t *testing.T) {
t.Fatal("received the wrong number of preferences") t.Fatal("received the wrong number of preferences")
} }
Client.LoginByEmail(team.Name, user2.Email, "pwd") th.LoginBasic2()
// note that user2 will automatically have a preference set for them to show user1 for direct messages
if result, err := Client.GetAllPreferences(); err != nil { if result, err := Client.GetAllPreferences(); err != nil {
t.Fatal(err) t.Fatal(err)
} else if data := result.Data.(model.Preferences); len(data) != 2 { } else if data := result.Data.(model.Preferences); len(data) == 0 {
t.Fatal("received the wrong number of preferences") t.Fatal("received the wrong number of preferences")
} }
} }
func TestSetPreferences(t *testing.T) { func TestSetPreferences(t *testing.T) {
Setup() th := Setup().InitBasic()
Client := th.BasicClient
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} user1 := th.BasicUser
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user1.Id))
Client.LoginByEmail(team.Name, user1.Email, "pwd")
// save 10 preferences // save 10 preferences
var preferences model.Preferences var preferences model.Preferences
@@ -98,12 +79,7 @@ func TestSetPreferences(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
// not able to update as a different user th.LoginBasic2()
user2 := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user2.Id))
Client.LoginByEmail(team.Name, user2.Email, "pwd")
if _, err := Client.SetPreferences(&preferences); err == nil { if _, err := Client.SetPreferences(&preferences); err == nil {
t.Fatal("shouldn't have been able to update another user's preferences") t.Fatal("shouldn't have been able to update another user's preferences")
@@ -111,18 +87,9 @@ func TestSetPreferences(t *testing.T) {
} }
func TestGetPreferenceCategory(t *testing.T) { func TestGetPreferenceCategory(t *testing.T) {
Setup() th := Setup().InitBasic()
Client := th.BasicClient
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} user1 := th.BasicUser
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user1.Id))
user2 := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user2.Id))
category := model.NewId() category := model.NewId()
@@ -144,11 +111,8 @@ func TestGetPreferenceCategory(t *testing.T) {
}, },
} }
Client.LoginByEmail(team.Name, user1.Email, "pwd")
Client.Must(Client.SetPreferences(&preferences1)) Client.Must(Client.SetPreferences(&preferences1))
Client.LoginByEmail(team.Name, user1.Email, "pwd")
if result, err := Client.GetPreferenceCategory(category); err != nil { if result, err := Client.GetPreferenceCategory(category); err != nil {
t.Fatal(err) t.Fatal(err)
} else if data := result.Data.(model.Preferences); len(data) != 2 { } else if data := result.Data.(model.Preferences); len(data) != 2 {
@@ -157,7 +121,7 @@ func TestGetPreferenceCategory(t *testing.T) {
t.Fatal("received incorrect preferences") t.Fatal("received incorrect preferences")
} }
Client.LoginByEmail(team.Name, user2.Email, "pwd") th.LoginBasic2()
if result, err := Client.GetPreferenceCategory(category); err != nil { if result, err := Client.GetPreferenceCategory(category); err != nil {
t.Fatal(err) t.Fatal(err)
@@ -167,16 +131,9 @@ func TestGetPreferenceCategory(t *testing.T) {
} }
func TestGetPreference(t *testing.T) { func TestGetPreference(t *testing.T) {
Setup() th := Setup().InitBasic()
Client := th.BasicClient
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} user := th.BasicUser
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
user := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user.Id))
Client.LoginByEmail(team.Name, user.Email, "pwd")
preferences := model.Preferences{ preferences := model.Preferences{
{ {

Просмотреть файл

@@ -6,6 +6,7 @@ package api
import ( import (
l4g "github.com/alecthomas/log4go" l4g "github.com/alecthomas/log4go"
"github.com/braintree/manners" "github.com/braintree/manners"
"github.com/gorilla/handlers"
"github.com/gorilla/mux" "github.com/gorilla/mux"
"github.com/mattermost/platform/store" "github.com/mattermost/platform/store"
"github.com/mattermost/platform/utils" "github.com/mattermost/platform/utils"
@@ -73,11 +74,10 @@ func StartServer() {
} }
go func() { go func() {
err := manners.ListenAndServe(utils.Cfg.ServiceSettings.ListenAddress, handler) err := manners.ListenAndServe(utils.Cfg.ServiceSettings.ListenAddress, handlers.RecoveryHandler(handlers.PrintRecoveryStack(true))(handler))
if err != nil { if err != nil {
l4g.Critical(utils.T("api.server.start_server.starting.critical"), err) l4g.Critical(utils.T("api.server.start_server.starting.critical"), err)
time.Sleep(time.Second) time.Sleep(time.Second)
panic(utils.T("api.server.start_server.starting.panic") + err.Error())
} }
}() }()
} }

Просмотреть файл

@@ -1,79 +0,0 @@
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api
/*
func createSubDomain(subDomain string, target string) {
if utils.Cfg.AWSSettings.Route53AccessKeyId == "" {
return
}
creds := aws.Creds(utils.Cfg.AWSSettings.Route53AccessKeyId, utils.Cfg.AWSSettings.Route53SecretAccessKey, "")
r53 := route53.New(aws.DefaultConfig.Merge(&aws.Config{Credentials: creds, Region: utils.Cfg.AWSSettings.Route53Region}))
rr := route53.ResourceRecord{
Value: aws.String(target),
}
rrs := make([]*route53.ResourceRecord, 1)
rrs[0] = &rr
change := route53.Change{
Action: aws.String("CREATE"),
ResourceRecordSet: &route53.ResourceRecordSet{
Name: aws.String(fmt.Sprintf("%v.%v", subDomain, utils.Cfg.ServiceSettings.Domain)),
TTL: aws.Long(300),
Type: aws.String("CNAME"),
ResourceRecords: rrs,
},
}
changes := make([]*route53.Change, 1)
changes[0] = &change
r53req := &route53.ChangeResourceRecordSetsInput{
HostedZoneID: aws.String(utils.Cfg.AWSSettings.Route53ZoneId),
ChangeBatch: &route53.ChangeBatch{
Changes: changes,
},
}
if _, err := r53.ChangeResourceRecordSets(r53req); err != nil {
l4g.Error("erro in createSubDomain domain=%v err=%v", subDomain, err)
return
}
}
func doesSubDomainExist(subDomain string) bool {
// if it's configured for testing then skip this step
if utils.Cfg.AWSSettings.Route53AccessKeyId == "" {
return false
}
creds := aws.Creds(utils.Cfg.AWSSettings.Route53AccessKeyId, utils.Cfg.AWSSettings.Route53SecretAccessKey, "")
r53 := route53.New(aws.DefaultConfig.Merge(&aws.Config{Credentials: creds, Region: utils.Cfg.AWSSettings.Route53Region}))
r53req := &route53.ListResourceRecordSetsInput{
HostedZoneID: aws.String(utils.Cfg.AWSSettings.Route53ZoneId),
MaxItems: aws.String("1"),
StartRecordName: aws.String(fmt.Sprintf("%v.%v.", subDomain, utils.Cfg.ServiceSettings.Domain)),
}
if result, err := r53.ListResourceRecordSets(r53req); err != nil {
l4g.Error("error in doesSubDomainExist domain=%v err=%v", subDomain, err)
return true
} else {
for _, v := range result.ResourceRecordSets {
if v.Name != nil && *v.Name == fmt.Sprintf("%v.%v.", subDomain, utils.Cfg.ServiceSettings.Domain) {
return true
}
}
}
return false
}
*/

Просмотреть файл

@@ -112,7 +112,6 @@ func SlackAddUsers(teamId string, slackusers []SlackUser, log *bytes.Buffer) map
password := model.NewId() password := model.NewId()
newUser := model.User{ newUser := model.User{
TeamId: teamId,
Username: sUser.Username, Username: sUser.Username,
FirstName: firstName, FirstName: firstName,
LastName: lastName, LastName: lastName,
@@ -120,7 +119,7 @@ func SlackAddUsers(teamId string, slackusers []SlackUser, log *bytes.Buffer) map
Password: password, Password: password,
} }
if mUser := ImportUser(&newUser); mUser != nil { if mUser := ImportUser(teamId, &newUser); mUser != nil {
addedUsers[sUser.Id] = mUser addedUsers[sUser.Id] = mUser
log.WriteString(utils.T("api.slackimport.slack_add_users.email_pwd", map[string]interface{}{"Email": newUser.Email, "Password": password})) log.WriteString(utils.T("api.slackimport.slack_add_users.email_pwd", map[string]interface{}{"Email": newUser.Email, "Password": password}))
} else { } else {

Просмотреть файл

@@ -6,38 +6,43 @@ package api
import ( import (
"bytes" "bytes"
"fmt" "fmt"
l4g "github.com/alecthomas/log4go"
"github.com/gorilla/mux"
"github.com/mattermost/platform/einterfaces"
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/store"
"github.com/mattermost/platform/utils"
"html/template" "html/template"
"net/http" "net/http"
"net/url" "net/url"
"strconv" "strconv"
"strings" "strings"
"time" "time"
l4g "github.com/alecthomas/log4go"
"github.com/gorilla/mux"
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/utils"
) )
func InitTeam(r *mux.Router) { func InitTeam() {
l4g.Debug(utils.T("api.team.init.debug")) l4g.Debug(utils.T("api.team.init.debug"))
sr := r.PathPrefix("/teams").Subrouter() BaseRoutes.Teams.Handle("/create", ApiAppHandler(createTeam)).Methods("POST")
sr.Handle("/create", ApiAppHandler(createTeam)).Methods("POST") BaseRoutes.Teams.Handle("/create_from_signup", ApiAppHandler(createTeamFromSignup)).Methods("POST")
sr.Handle("/create_from_signup", ApiAppHandler(createTeamFromSignup)).Methods("POST") BaseRoutes.Teams.Handle("/signup", ApiAppHandler(signupTeam)).Methods("POST")
sr.Handle("/create_with_ldap", ApiAppHandler(createTeamWithLdap)).Methods("POST") BaseRoutes.Teams.Handle("/all", ApiAppHandler(getAll)).Methods("GET")
sr.Handle("/create_with_sso/{service:[A-Za-z]+}", ApiAppHandler(createTeamFromSSO)).Methods("POST") BaseRoutes.Teams.Handle("/all_team_listings", ApiUserRequired(GetAllTeamListings)).Methods("GET")
sr.Handle("/signup", ApiAppHandler(signupTeam)).Methods("POST") BaseRoutes.Teams.Handle("/get_invite_info", ApiAppHandler(getInviteInfo)).Methods("POST")
sr.Handle("/all", ApiAppHandler(getAll)).Methods("GET") BaseRoutes.Teams.Handle("/find_team_by_name", ApiAppHandler(findTeamByName)).Methods("POST")
sr.Handle("/find_team_by_name", ApiAppHandler(findTeamByName)).Methods("POST") BaseRoutes.Teams.Handle("/members/{id:[A-Za-z0-9]+}", ApiUserRequired(getMembers)).Methods("GET")
sr.Handle("/invite_members", ApiUserRequired(inviteMembers)).Methods("POST")
sr.Handle("/update", ApiUserRequired(updateTeam)).Methods("POST") BaseRoutes.NeedTeam.Handle("/me", ApiUserRequired(getMyTeam)).Methods("GET")
sr.Handle("/me", ApiUserRequired(getMyTeam)).Methods("GET") BaseRoutes.NeedTeam.Handle("/update", ApiUserRequired(updateTeam)).Methods("POST")
sr.Handle("/get_invite_info", ApiAppHandler(getInviteInfo)).Methods("POST")
BaseRoutes.NeedTeam.Handle("/invite_members", ApiUserRequired(inviteMembers)).Methods("POST")
BaseRoutes.NeedTeam.Handle("/add_user_to_team", ApiUserRequired(addUserToTeam)).Methods("POST")
// These should be moved to the global admain console // These should be moved to the global admain console
sr.Handle("/import_team", ApiUserRequired(importTeam)).Methods("POST") BaseRoutes.Teams.Handle("/import_team", ApiUserRequired(importTeam)).Methods("POST")
sr.Handle("/export_team", ApiUserRequired(exportTeam)).Methods("GET") BaseRoutes.Teams.Handle("/export_team", ApiUserRequired(exportTeam)).Methods("GET")
BaseRoutes.Teams.Handle("/add_user_to_team_from_invite", ApiUserRequired(addUserToTeamFromInvite)).Methods("POST")
} }
func signupTeam(c *Context, w http.ResponseWriter, r *http.Request) { func signupTeam(c *Context, w http.ResponseWriter, r *http.Request) {
@@ -92,67 +97,6 @@ func signupTeam(c *Context, w http.ResponseWriter, r *http.Request) {
w.Write([]byte(model.MapToJson(m))) w.Write([]byte(model.MapToJson(m)))
} }
func createTeamFromSSO(c *Context, w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r)
service := params["service"]
sso := utils.Cfg.GetSSOService(service)
if sso != nil && !sso.Enable {
c.SetInvalidParam("createTeamFromSSO", "service")
return
}
team := model.TeamFromJson(r.Body)
if team == nil {
c.SetInvalidParam("createTeamFromSSO", "team")
return
}
if !isTeamCreationAllowed(c, team.Email) {
return
}
team.PreSave()
team.Name = model.CleanTeamName(team.Name)
if err := team.IsValid(*utils.Cfg.TeamSettings.RestrictTeamNames); err != nil {
c.Err = err
return
}
team.Id = ""
found := true
count := 0
for found {
if found = FindTeamByName(c, team.Name, "true"); c.Err != nil {
return
} else if found {
team.Name = team.Name + strconv.Itoa(count)
count += 1
}
}
if result := <-Srv.Store.Team().Save(team); result.Err != nil {
c.Err = result.Err
return
} else {
rteam := result.Data.(*model.Team)
if _, err := CreateDefaultChannels(c, rteam.Id); err != nil {
c.Err = nil
return
}
data := map[string]string{"follow_link": c.GetSiteURL() + "/api/v1/oauth/" + service + "/signup?team=" + rteam.Name}
w.Write([]byte(model.MapToJson(data)))
}
}
func createTeamFromSignup(c *Context, w http.ResponseWriter, r *http.Request) { func createTeamFromSignup(c *Context, w http.ResponseWriter, r *http.Request) {
if !utils.Cfg.EmailSettings.EnableSignUpWithEmail { if !utils.Cfg.EmailSettings.EnableSignUpWithEmail {
c.Err = model.NewLocAppError("createTeamFromSignup", "api.team.create_team_from_signup.email_disabled.app_error", nil, "") c.Err = model.NewLocAppError("createTeamFromSignup", "api.team.create_team_from_signup.email_disabled.app_error", nil, "")
@@ -186,13 +130,11 @@ func createTeamFromSignup(c *Context, w http.ResponseWriter, r *http.Request) {
password := teamSignup.User.Password password := teamSignup.User.Password
teamSignup.User.PreSave() teamSignup.User.PreSave()
teamSignup.User.TeamId = model.NewId()
if err := teamSignup.User.IsValid(); err != nil { if err := teamSignup.User.IsValid(); err != nil {
c.Err = err c.Err = err
return return
} }
teamSignup.User.Id = "" teamSignup.User.Id = ""
teamSignup.User.TeamId = ""
teamSignup.User.Password = password teamSignup.User.Password = password
if !model.ComparePassword(teamSignup.Hash, fmt.Sprintf("%v:%v", teamSignup.Data, utils.Cfg.EmailSettings.InviteSalt)) { if !model.ComparePassword(teamSignup.Hash, fmt.Sprintf("%v:%v", teamSignup.Data, utils.Cfg.EmailSettings.InviteSalt)) {
@@ -206,10 +148,7 @@ func createTeamFromSignup(c *Context, w http.ResponseWriter, r *http.Request) {
return return
} }
found := FindTeamByName(c, teamSignup.Team.Name, "true") found := FindTeamByName(teamSignup.Team.Name)
if c.Err != nil {
return
}
if found { if found {
c.Err = model.NewLocAppError("createTeamFromSignup", "api.team.create_team_from_signup.unavailable.app_error", nil, "d="+teamSignup.Team.Name) c.Err = model.NewLocAppError("createTeamFromSignup", "api.team.create_team_from_signup.unavailable.app_error", nil, "d="+teamSignup.Team.Name)
@@ -227,15 +166,16 @@ func createTeamFromSignup(c *Context, w http.ResponseWriter, r *http.Request) {
return return
} }
teamSignup.User.TeamId = rteam.Id
teamSignup.User.EmailVerified = true teamSignup.User.EmailVerified = true
ruser, err := CreateUser(rteam, &teamSignup.User) ruser, err := CreateUser(&teamSignup.User)
if err != nil { if err != nil {
c.Err = err c.Err = err
return return
} }
JoinUserToTeam(rteam, ruser)
InviteMembers(c, rteam, ruser, teamSignup.Invites) InviteMembers(c, rteam, ruser, teamSignup.Invites)
teamSignup.Team = *rteam teamSignup.Team = *rteam
@@ -245,85 +185,38 @@ func createTeamFromSignup(c *Context, w http.ResponseWriter, r *http.Request) {
} }
} }
func createTeamWithLdap(c *Context, w http.ResponseWriter, r *http.Request) { func createTeam(c *Context, w http.ResponseWriter, r *http.Request) {
ldap := einterfaces.GetLdapInterface() team := model.TeamFromJson(r.Body)
if ldap == nil {
c.Err = model.NewLocAppError("createTeamWithLdap", "ent.ldap.do_login.licence_disable.app_error", nil, "") if team == nil {
c.SetInvalidParam("createTeam", "team")
return return
} }
teamSignup := model.TeamSignupFromJson(r.Body) var user *model.User
if len(c.Session.UserId) > 0 {
uchan := Srv.Store.User().Get(c.Session.UserId)
if teamSignup == nil { if result := <-uchan; result.Err != nil {
c.SetInvalidParam("createTeam", "teamSignup") c.Err = result.Err
return return
} else {
user = result.Data.(*model.User)
team.Email = user.Email
}
} }
teamSignup.Team.PreSave() rteam := CreateTeam(c, team)
if err := teamSignup.Team.IsValid(*utils.Cfg.TeamSettings.RestrictTeamNames); err != nil {
c.Err = err
return
}
if !isTeamCreationAllowed(c, teamSignup.Team.Email) {
return
}
teamSignup.Team.Id = ""
found := FindTeamByName(c, teamSignup.Team.Name, "true")
if c.Err != nil { if c.Err != nil {
return return
} }
if found { if user != nil {
c.Err = model.NewLocAppError("createTeamFromSignup", "api.team.create_team_from_signup.unavailable.app_error", nil, "d="+teamSignup.Team.Name) err := JoinUserToTeam(team, user)
return
}
user, err := ldap.GetUser(teamSignup.User.Username)
if err != nil {
c.Err = err
return
}
err = ldap.CheckPassword(teamSignup.User.Username, teamSignup.User.Password)
if err != nil {
c.Err = err
return
}
if result := <-Srv.Store.Team().Save(&teamSignup.Team); result.Err != nil {
c.Err = result.Err
return
} else {
rteam := result.Data.(*model.Team)
if _, err := CreateDefaultChannels(c, rteam.Id); err != nil {
c.Err = nil
return
}
user.TeamId = rteam.Id
ruser, err := CreateUser(rteam, user)
if err != nil { if err != nil {
c.Err = err c.Err = err
return return
} }
teamSignup.Team = *rteam
teamSignup.User = *ruser
w.Write([]byte(teamSignup.ToJson()))
}
}
func createTeam(c *Context, w http.ResponseWriter, r *http.Request) {
team := model.TeamFromJson(r.Body)
rteam := CreateTeam(c, team)
if c.Err != nil {
return
} }
w.Write([]byte(rteam.ToJson())) w.Write([]byte(rteam.ToJson()))
@@ -360,6 +253,31 @@ func CreateTeam(c *Context, team *model.Team) *model.Team {
} }
} }
func JoinUserToTeam(team *model.Team, user *model.User) *model.AppError {
tm := &model.TeamMember{TeamId: team.Id, UserId: user.Id}
channelRole := ""
if team.Email == user.Email {
tm.Roles = model.ROLE_TEAM_ADMIN
channelRole = model.CHANNEL_ROLE_ADMIN
}
if tmr := <-Srv.Store.Team().SaveMember(tm); tmr.Err != nil {
return tmr.Err
}
// Soft error if there is an issue joining the default channels
if err := JoinDefaultChannels(team.Id, user, channelRole); err != nil {
l4g.Error(utils.T("api.user.create_user.joining.error"), user.Id, team.Id, err)
}
RemoveAllSessionsForUserId(user.Id)
InvalidateCacheForUser(user.Id)
return nil
}
func isTeamCreationAllowed(c *Context, email string) bool { func isTeamCreationAllowed(c *Context, email string) bool {
email = strings.ToLower(email) email = strings.ToLower(email)
@@ -389,6 +307,24 @@ func isTeamCreationAllowed(c *Context, email string) bool {
return true return true
} }
func GetAllTeamListings(c *Context, w http.ResponseWriter, r *http.Request) {
if result := <-Srv.Store.Team().GetAllTeamListing(); result.Err != nil {
c.Err = result.Err
return
} else {
teams := result.Data.([]*model.Team)
m := make(map[string]*model.Team)
for _, v := range teams {
m[v.Id] = v
if !c.IsSystemAdmin() {
m[v.Id].Sanitize()
}
}
w.Write([]byte(model.TeamMapToJson(m)))
}
}
func getAll(c *Context, w http.ResponseWriter, r *http.Request) { func getAll(c *Context, w http.ResponseWriter, r *http.Request) {
if result := <-Srv.Store.Team().GetAll(); result.Err != nil { if result := <-Srv.Store.Team().GetAll(); result.Err != nil {
c.Err = result.Err c.Err = result.Err
@@ -435,42 +371,6 @@ func revokeAllSessions(c *Context, w http.ResponseWriter, r *http.Request) {
} }
} }
func findTeamByName(c *Context, w http.ResponseWriter, r *http.Request) {
m := model.MapFromJson(r.Body)
name := strings.ToLower(strings.TrimSpace(m["name"]))
all := strings.ToLower(strings.TrimSpace(m["all"]))
found := FindTeamByName(c, name, all)
if c.Err != nil {
return
}
if found {
w.Write([]byte("true"))
} else {
w.Write([]byte("false"))
}
}
func FindTeamByName(c *Context, name string, all string) bool {
if name == "" || len(name) > 64 {
c.SetInvalidParam("findTeamByName", "domain")
return false
}
if result := <-Srv.Store.Team().GetByName(name); result.Err != nil {
return false
} else {
return true
}
return false
}
func inviteMembers(c *Context, w http.ResponseWriter, r *http.Request) { func inviteMembers(c *Context, w http.ResponseWriter, r *http.Request) {
invites := model.InvitesFromJson(r.Body) invites := model.InvitesFromJson(r.Body)
if len(invites.Invites) == 0 { if len(invites.Invites) == 0 {
@@ -479,7 +379,7 @@ func inviteMembers(c *Context, w http.ResponseWriter, r *http.Request) {
return return
} }
tchan := Srv.Store.Team().Get(c.Session.TeamId) tchan := Srv.Store.Team().Get(c.TeamId)
uchan := Srv.Store.User().Get(c.Session.UserId) uchan := Srv.Store.User().Get(c.Session.UserId)
var team *model.Team var team *model.Team
@@ -498,15 +398,6 @@ func inviteMembers(c *Context, w http.ResponseWriter, r *http.Request) {
user = result.Data.(*model.User) user = result.Data.(*model.User)
} }
var invNum int64 = 0
for i, invite := range invites.Invites {
if result := <-Srv.Store.User().GetByEmail(c.Session.TeamId, invite["email"]); result.Err == nil || result.Err.Id != store.MISSING_ACCOUNT_ERROR {
invNum = int64(i)
c.Err = model.NewLocAppError("invite_members", "api.team.invite_members.already.app_error", nil, strconv.FormatInt(invNum, 10))
return
}
}
ia := make([]string, len(invites.Invites)) ia := make([]string, len(invites.Invites))
for _, invite := range invites.Invites { for _, invite := range invites.Invites {
ia = append(ia, invite["email"]) ia = append(ia, invite["email"])
@@ -517,6 +408,146 @@ func inviteMembers(c *Context, w http.ResponseWriter, r *http.Request) {
w.Write([]byte(invites.ToJson())) w.Write([]byte(invites.ToJson()))
} }
func addUserToTeam(c *Context, w http.ResponseWriter, r *http.Request) {
params := model.MapFromJson(r.Body)
userId := params["user_id"]
if len(userId) != 26 {
c.SetInvalidParam("addUserToTeam", "user_id")
return
}
tchan := Srv.Store.Team().Get(c.TeamId)
uchan := Srv.Store.User().Get(userId)
var team *model.Team
if result := <-tchan; result.Err != nil {
c.Err = result.Err
return
} else {
team = result.Data.(*model.Team)
}
var user *model.User
if result := <-uchan; result.Err != nil {
c.Err = result.Err
return
} else {
user = result.Data.(*model.User)
}
if !c.IsTeamAdmin() {
c.Err = model.NewLocAppError("addUserToTeam", "api.team.update_team.permissions.app_error", nil, "userId="+c.Session.UserId)
c.Err.StatusCode = http.StatusForbidden
return
}
err := JoinUserToTeam(team, user)
if err != nil {
c.Err = err
return
}
w.Write([]byte(model.MapToJson(params)))
}
func addUserToTeamFromInvite(c *Context, w http.ResponseWriter, r *http.Request) {
params := model.MapFromJson(r.Body)
hash := params["hash"]
data := params["data"]
inviteId := params["invite_id"]
teamId := ""
var team *model.Team
if len(hash) > 0 {
props := model.MapFromJson(strings.NewReader(data))
if !model.ComparePassword(hash, fmt.Sprintf("%v:%v", data, utils.Cfg.EmailSettings.InviteSalt)) {
c.Err = model.NewLocAppError("addUserToTeamFromInvite", "api.user.create_user.signup_link_invalid.app_error", nil, "")
return
}
t, err := strconv.ParseInt(props["time"], 10, 64)
if err != nil || model.GetMillis()-t > 1000*60*60*48 { // 48 hours
c.Err = model.NewLocAppError("addUserToTeamFromInvite", "api.user.create_user.signup_link_expired.app_error", nil, "")
return
}
teamId = props["id"]
// try to load the team to make sure it exists
if result := <-Srv.Store.Team().Get(teamId); result.Err != nil {
c.Err = result.Err
return
} else {
team = result.Data.(*model.Team)
}
}
if len(inviteId) > 0 {
if result := <-Srv.Store.Team().GetByInviteId(inviteId); result.Err != nil {
c.Err = result.Err
return
} else {
team = result.Data.(*model.Team)
teamId = team.Id
}
}
if len(teamId) == 0 {
c.Err = model.NewLocAppError("addUserToTeamFromInvite", "api.user.create_user.signup_link_invalid.app_error", nil, "")
return
}
uchan := Srv.Store.User().Get(c.Session.UserId)
var user *model.User
if result := <-uchan; result.Err != nil {
c.Err = result.Err
return
} else {
user = result.Data.(*model.User)
}
tm := c.Session.GetTeamByTeamId(teamId)
if tm == nil {
err := JoinUserToTeam(team, user)
if err != nil {
c.Err = err
return
}
}
team.Sanitize()
w.Write([]byte(team.ToJson()))
}
func FindTeamByName(name string) bool {
if result := <-Srv.Store.Team().GetByName(name); result.Err != nil {
return false
} else {
return true
}
}
func findTeamByName(c *Context, w http.ResponseWriter, r *http.Request) {
m := model.MapFromJson(r.Body)
name := strings.ToLower(strings.TrimSpace(m["name"]))
found := FindTeamByName(name)
if found {
w.Write([]byte("true"))
} else {
w.Write([]byte("false"))
}
}
func InviteMembers(c *Context, team *model.Team, user *model.User, invites []string) { func InviteMembers(c *Context, team *model.Team, user *model.User, invites []string) {
for _, invite := range invites { for _, invite := range invites {
if len(invite) > 0 { if len(invite) > 0 {
@@ -573,7 +604,7 @@ func updateTeam(c *Context, w http.ResponseWriter, r *http.Request) {
return return
} }
team.Id = c.Session.TeamId team.Id = c.TeamId
if !c.IsTeamAdmin() { if !c.IsTeamAdmin() {
c.Err = model.NewLocAppError("updateTeam", "api.team.update_team.permissions.app_error", nil, "userId="+c.Session.UserId) c.Err = model.NewLocAppError("updateTeam", "api.team.update_team.permissions.app_error", nil, "userId="+c.Session.UserId)
@@ -592,7 +623,6 @@ func updateTeam(c *Context, w http.ResponseWriter, r *http.Request) {
oldTeam.DisplayName = team.DisplayName oldTeam.DisplayName = team.DisplayName
oldTeam.InviteId = team.InviteId oldTeam.InviteId = team.InviteId
oldTeam.AllowOpenInvite = team.AllowOpenInvite oldTeam.AllowOpenInvite = team.AllowOpenInvite
oldTeam.AllowTeamListing = team.AllowTeamListing
oldTeam.CompanyName = team.CompanyName oldTeam.CompanyName = team.CompanyName
oldTeam.AllowedDomains = team.AllowedDomains oldTeam.AllowedDomains = team.AllowedDomains
//oldTeam.Type = team.Type //oldTeam.Type = team.Type
@@ -617,16 +647,11 @@ func PermanentDeleteTeam(c *Context, team *model.Team) *model.AppError {
return result.Err return result.Err
} }
if result := <-Srv.Store.User().GetForExport(team.Id); result.Err != nil { if result := <-Srv.Store.Channel().PermanentDeleteByTeam(team.Id); result.Err != nil {
return result.Err return result.Err
} else {
users := result.Data.([]*model.User)
for _, user := range users {
PermanentDeleteUser(c, user)
}
} }
if result := <-Srv.Store.Channel().PermanentDeleteByTeam(team.Id); result.Err != nil { if result := <-Srv.Store.Team().RemoveAllMembersByTeam(team.Id); result.Err != nil {
return result.Err return result.Err
} }
@@ -642,11 +667,11 @@ func PermanentDeleteTeam(c *Context, team *model.Team) *model.AppError {
func getMyTeam(c *Context, w http.ResponseWriter, r *http.Request) { func getMyTeam(c *Context, w http.ResponseWriter, r *http.Request) {
if len(c.Session.TeamId) == 0 { if len(c.TeamId) == 0 {
return return
} }
if result := <-Srv.Store.Team().Get(c.Session.TeamId); result.Err != nil { if result := <-Srv.Store.Team().Get(c.TeamId); result.Err != nil {
c.Err = result.Err c.Err = result.Err
return return
} else if HandleEtag(result.Data.(*model.Team).Etag(), w, r) { } else if HandleEtag(result.Data.(*model.Team).Etag(), w, r) {
@@ -659,7 +684,7 @@ func getMyTeam(c *Context, w http.ResponseWriter, r *http.Request) {
} }
func importTeam(c *Context, w http.ResponseWriter, r *http.Request) { func importTeam(c *Context, w http.ResponseWriter, r *http.Request) {
if !c.HasPermissionsToTeam(c.Session.TeamId, "import") || !c.IsTeamAdmin() { if !c.HasPermissionsToTeam(c.TeamId, "import") || !c.IsTeamAdmin() {
c.Err = model.NewLocAppError("importTeam", "api.team.import_team.admin.app_error", nil, "userId="+c.Session.UserId) c.Err = model.NewLocAppError("importTeam", "api.team.import_team.admin.app_error", nil, "userId="+c.Session.UserId)
c.Err.StatusCode = http.StatusForbidden c.Err.StatusCode = http.StatusForbidden
return return
@@ -714,7 +739,7 @@ func importTeam(c *Context, w http.ResponseWriter, r *http.Request) {
switch importFrom { switch importFrom {
case "slack": case "slack":
var err *model.AppError var err *model.AppError
if err, log = SlackImport(fileData, fileSize, c.Session.TeamId); err != nil { if err, log = SlackImport(fileData, fileSize, c.TeamId); err != nil {
c.Err = err c.Err = err
c.Err.StatusCode = http.StatusBadRequest c.Err.StatusCode = http.StatusBadRequest
} }
@@ -726,7 +751,7 @@ func importTeam(c *Context, w http.ResponseWriter, r *http.Request) {
} }
func exportTeam(c *Context, w http.ResponseWriter, r *http.Request) { func exportTeam(c *Context, w http.ResponseWriter, r *http.Request) {
if !c.HasPermissionsToTeam(c.Session.TeamId, "export") || !c.IsTeamAdmin() { if !c.HasPermissionsToTeam(c.TeamId, "export") || !c.IsTeamAdmin() {
c.Err = model.NewLocAppError("exportTeam", "api.team.export_team.admin.app_error", nil, "userId="+c.Session.UserId) c.Err = model.NewLocAppError("exportTeam", "api.team.export_team.admin.app_error", nil, "userId="+c.Session.UserId)
c.Err.StatusCode = http.StatusForbidden c.Err.StatusCode = http.StatusForbidden
return return
@@ -765,3 +790,23 @@ func getInviteInfo(c *Context, w http.ResponseWriter, r *http.Request) {
w.Write([]byte(model.MapToJson(result))) w.Write([]byte(model.MapToJson(result)))
} }
} }
func getMembers(c *Context, w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r)
id := params["id"]
if c.Session.GetTeamByTeamId(id) == nil {
if !c.HasSystemAdminPermissions("getMembers") {
return
}
}
if result := <-Srv.Store.Team().GetMembers(id); result.Err != nil {
c.Err = result.Err
return
} else {
members := result.Data.([]*model.TeamMember)
w.Write([]byte(model.TeamMembersToJson(members)))
return
}
}

Просмотреть файл

@@ -13,7 +13,9 @@ import (
) )
func TestSignupTeam(t *testing.T) { func TestSignupTeam(t *testing.T) {
Setup() th := Setup().InitBasic()
th.BasicClient.Logout()
Client := th.BasicClient
_, err := Client.SignupTeam("test@nowhere.com", "name") _, err := Client.SignupTeam("test@nowhere.com", "name")
if err != nil { if err != nil {
@@ -22,7 +24,9 @@ func TestSignupTeam(t *testing.T) {
} }
func TestCreateFromSignupTeam(t *testing.T) { func TestCreateFromSignupTeam(t *testing.T) {
Setup() th := Setup().InitBasic()
th.BasicClient.Logout()
Client := th.BasicClient
props := make(map[string]string) props := make(map[string]string)
props["email"] = strings.ToLower(model.NewId()) + "success+test@simulator.amazonses.com" props["email"] = strings.ToLower(model.NewId()) + "success+test@simulator.amazonses.com"
@@ -47,6 +51,8 @@ func TestCreateFromSignupTeam(t *testing.T) {
} }
ruser := rts.Data.(*model.TeamSignup).User ruser := rts.Data.(*model.TeamSignup).User
rteam := rts.Data.(*model.TeamSignup).Team
Client.SetTeamId(rteam.Id)
if result, err := Client.LoginById(ruser.Id, user.Password); err != nil { if result, err := Client.LoginById(ruser.Id, user.Password); err != nil {
t.Fatal(err) t.Fatal(err)
@@ -69,7 +75,9 @@ func TestCreateFromSignupTeam(t *testing.T) {
} }
func TestCreateTeam(t *testing.T) { func TestCreateTeam(t *testing.T) {
Setup() th := Setup().InitBasic()
th.BasicClient.Logout()
Client := th.BasicClient
team := model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} team := model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN}
rteam, err := Client.CreateTeam(&team) rteam, err := Client.CreateTeam(&team)
@@ -77,11 +85,13 @@ func TestCreateTeam(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
user := &model.User{TeamId: rteam.Data.(*model.Team).Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"} user := &model.User{Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User) user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
LinkUserToTeam(user, rteam.Data.(*model.Team))
store.Must(Srv.Store.User().VerifyEmail(user.Id)) store.Must(Srv.Store.User().VerifyEmail(user.Id))
Client.LoginByEmail(team.Name, user.Email, "pwd") Client.LoginByEmail(team.Name, user.Email, "pwd")
Client.SetTeamId(rteam.Data.(*model.Team).Id)
c1 := Client.Must(Client.GetChannels("")).Data.(*model.ChannelList) c1 := Client.Must(Client.GetChannels("")).Data.(*model.ChannelList)
if len(c1.Channels) != 2 { if len(c1.Channels) != 2 {
@@ -108,23 +118,124 @@ func TestCreateTeam(t *testing.T) {
} }
} }
func TestGetAllTeams(t *testing.T) { func TestAddUserToTeam(t *testing.T) {
Setup() th := Setup().InitBasic()
th.BasicClient.Logout()
Client := th.BasicClient
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN, AllowTeamListing: true} props := make(map[string]string)
props["email"] = strings.ToLower(model.NewId()) + "success+test@simulator.amazonses.com"
props["name"] = "Test Company name"
props["time"] = fmt.Sprintf("%v", model.GetMillis())
data := model.MapToJson(props)
hash := model.HashPassword(fmt.Sprintf("%v:%v", data, utils.Cfg.EmailSettings.InviteSalt))
team := model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: props["email"], Type: model.TEAM_OPEN}
user := model.User{Email: props["email"], Nickname: "Corey Hulen", Password: "hello"}
ts := model.TeamSignup{Team: team, User: user, Invites: []string{"success+test@simulator.amazonses.com"}, Data: data, Hash: hash}
rts, err := Client.CreateTeamFromSignup(&ts)
if err != nil {
t.Fatal(err)
}
if rts.Data.(*model.TeamSignup).Team.DisplayName != team.DisplayName {
t.Fatal("full name didn't match")
}
ruser := rts.Data.(*model.TeamSignup).User
rteam := rts.Data.(*model.TeamSignup).Team
Client.SetTeamId(rteam.Id)
if result, err := Client.LoginById(ruser.Id, user.Password); err != nil {
t.Fatal(err)
} else {
if result.Data.(*model.User).Email != user.Email {
t.Fatal("email's didn't match")
}
}
user2 := th.CreateUser(th.BasicClient)
if result, err := th.BasicClient.AddUserToTeam(user2.Id); err != nil {
t.Fatal(err)
} else {
rm := result.Data.(map[string]string)
if rm["user_id"] != user2.Id {
t.Fatal("email's didn't match")
}
}
}
func TestAddUserToTeamFromInvite(t *testing.T) {
th := Setup().InitBasic()
th.BasicClient.Logout()
Client := th.BasicClient
props := make(map[string]string)
props["email"] = strings.ToLower(model.NewId()) + "success+test@simulator.amazonses.com"
props["name"] = "Test Company name"
props["time"] = fmt.Sprintf("%v", model.GetMillis())
data := model.MapToJson(props)
hash := model.HashPassword(fmt.Sprintf("%v:%v", data, utils.Cfg.EmailSettings.InviteSalt))
team := model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: props["email"], Type: model.TEAM_OPEN}
user := model.User{Email: props["email"], Nickname: "Corey Hulen", Password: "hello"}
ts := model.TeamSignup{Team: team, User: user, Invites: []string{"success+test@simulator.amazonses.com"}, Data: data, Hash: hash}
rts, err := Client.CreateTeamFromSignup(&ts)
if err != nil {
t.Fatal(err)
}
if rts.Data.(*model.TeamSignup).Team.DisplayName != team.DisplayName {
t.Fatal("full name didn't match")
}
ruser := rts.Data.(*model.TeamSignup).User
rteam := rts.Data.(*model.TeamSignup).Team
Client.SetTeamId(rteam.Id)
if result, err := Client.LoginById(ruser.Id, user.Password); err != nil {
t.Fatal(err)
} else {
if result.Data.(*model.User).Email != user.Email {
t.Fatal("email's didn't match")
}
}
user2 := th.CreateUser(th.BasicClient)
Client.Must(Client.Logout())
Client.Must(Client.LoginByEmail("", user2.Email, user2.Password))
if result, err := th.BasicClient.AddUserToTeamFromInvite("", "", rteam.InviteId); err != nil {
t.Fatal(err)
} else {
rtm := result.Data.(*model.Team)
if rtm.Id != rteam.Id {
t.Fatal()
}
}
}
func TestGetAllTeams(t *testing.T) {
th := Setup().InitBasic()
th.BasicClient.Logout()
Client := th.BasicClient
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN}
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team) team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
user := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"} user := &model.User{Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User) user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
LinkUserToTeam(user, team)
store.Must(Srv.Store.User().VerifyEmail(user.Id)) store.Must(Srv.Store.User().VerifyEmail(user.Id))
Client.LoginByEmail(team.Name, user.Email, "pwd") Client.LoginByEmail(team.Name, user.Email, "pwd")
Client.SetTeamId(team.Id)
enableIncomingHooks := *utils.Cfg.TeamSettings.EnableTeamListing
defer func() {
*utils.Cfg.TeamSettings.EnableTeamListing = enableIncomingHooks
}()
*utils.Cfg.TeamSettings.EnableTeamListing = true
if r1, err := Client.GetAllTeams(); err != nil { if r1, err := Client.GetAllTeams(); err != nil {
t.Fatal(err) t.Fatal(err)
@@ -144,6 +255,56 @@ func TestGetAllTeams(t *testing.T) {
UpdateRoles(c, user, model.ROLE_SYSTEM_ADMIN) UpdateRoles(c, user, model.ROLE_SYSTEM_ADMIN)
Client.LoginByEmail(team.Name, user.Email, "pwd") Client.LoginByEmail(team.Name, user.Email, "pwd")
Client.SetTeamId(team.Id)
if r1, err := Client.GetAllTeams(); err != nil {
t.Fatal(err)
} else {
teams := r1.Data.(map[string]*model.Team)
if teams[team.Id].Name != team.Name {
t.Fatal()
}
if teams[team.Id].Email != team.Email {
t.Fatal()
}
}
}
func TestGetAllTeamListings(t *testing.T) {
th := Setup().InitBasic()
th.BasicClient.Logout()
Client := th.BasicClient
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN, AllowOpenInvite: true}
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
user := &model.User{Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
LinkUserToTeam(user, team)
store.Must(Srv.Store.User().VerifyEmail(user.Id))
Client.LoginByEmail(team.Name, user.Email, "pwd")
Client.SetTeamId(team.Id)
if r1, err := Client.GetAllTeamListings(); err != nil {
t.Fatal(err)
} else {
teams := r1.Data.(map[string]*model.Team)
if teams[team.Id].Name != team.Name {
t.Fatal()
}
if teams[team.Id].Email != "" {
t.Fatal("Non admin users shoudn't get full listings")
}
}
c := &Context{}
c.RequestId = model.NewId()
c.IpAddress = "cmd_line"
UpdateRoles(c, user, model.ROLE_SYSTEM_ADMIN)
Client.LoginByEmail(team.Name, user.Email, "pwd")
Client.SetTeamId(team.Id)
if r1, err := Client.GetAllTeams(); err != nil { if r1, err := Client.GetAllTeams(); err != nil {
t.Fatal(err) t.Fatal(err)
@@ -159,16 +320,20 @@ func TestGetAllTeams(t *testing.T) {
} }
func TestTeamPermDelete(t *testing.T) { func TestTeamPermDelete(t *testing.T) {
Setup() th := Setup().InitBasic()
th.BasicClient.Logout()
Client := th.BasicClient
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN}
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team) team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"} user1 := &model.User{Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User) user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
LinkUserToTeam(user1, team)
store.Must(Srv.Store.User().VerifyEmail(user1.Id)) store.Must(Srv.Store.User().VerifyEmail(user1.Id))
Client.LoginByEmail(team.Name, user1.Email, "pwd") Client.LoginByEmail(team.Name, user1.Email, "pwd")
Client.SetTeamId(team.Id)
channel1 := &model.Channel{DisplayName: "TestGetPosts", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} channel1 := &model.Channel{DisplayName: "TestGetPosts", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel) channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel)
@@ -198,19 +363,23 @@ func TestTeamPermDelete(t *testing.T) {
} }
func TestInviteMembers(t *testing.T) { func TestInviteMembers(t *testing.T) {
Setup() th := Setup().InitBasic()
th.BasicClient.Logout()
Client := th.BasicClient
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN}
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team) team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
user := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"} user := &model.User{Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User) user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
LinkUserToTeam(user, team)
store.Must(Srv.Store.User().VerifyEmail(user.Id)) store.Must(Srv.Store.User().VerifyEmail(user.Id))
Client.LoginByEmail(team.Name, user.Email, "pwd") Client.LoginByEmail(team.Name, user.Email, "pwd")
Client.SetTeamId(team.Id)
invite := make(map[string]string) invite := make(map[string]string)
invite["email"] = model.NewId() + "success+test@simulator.amazonses.com" invite["email"] = "success+" + model.NewId() + "@simulator.amazonses.com"
invite["first_name"] = "Test" invite["first_name"] = "Test"
invite["last_name"] = "Guy" invite["last_name"] = "Guy"
invites := &model.Invites{Invites: []map[string]string{invite}} invites := &model.Invites{Invites: []map[string]string{invite}}
@@ -227,20 +396,25 @@ func TestInviteMembers(t *testing.T) {
} }
func TestUpdateTeamDisplayName(t *testing.T) { func TestUpdateTeamDisplayName(t *testing.T) {
Setup() th := Setup().InitBasic()
th.BasicClient.Logout()
Client := th.BasicClient
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "success+" + model.NewId() + "@simulator.amazonses.com", Type: model.TEAM_OPEN}
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team) team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
user := &model.User{TeamId: team.Id, Email: "test@nowhere.com", Nickname: "Corey Hulen", Password: "pwd"} user := &model.User{Email: team.Email, Nickname: "Corey Hulen", Password: "pwd"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User) user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
LinkUserToTeam(user, team)
store.Must(Srv.Store.User().VerifyEmail(user.Id)) store.Must(Srv.Store.User().VerifyEmail(user.Id))
user2 := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"} user2 := &model.User{Email: "success+" + model.NewId() + "@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User) user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User)
LinkUserToTeam(user2, team)
store.Must(Srv.Store.User().VerifyEmail(user2.Id)) store.Must(Srv.Store.User().VerifyEmail(user2.Id))
Client.LoginByEmail(team.Name, user2.Email, "pwd") Client.LoginByEmail(team.Name, user2.Email, "pwd")
Client.SetTeamId(team.Id)
vteam := &model.Team{DisplayName: team.DisplayName, Name: team.Name, Email: team.Email, Type: team.Type} vteam := &model.Team{DisplayName: team.DisplayName, Name: team.Name, Email: team.Email, Type: team.Type}
vteam.DisplayName = "NewName" vteam.DisplayName = "NewName"
@@ -262,6 +436,9 @@ func TestUpdateTeamDisplayName(t *testing.T) {
} }
func TestFuzzyTeamCreate(t *testing.T) { func TestFuzzyTeamCreate(t *testing.T) {
th := Setup().InitBasic()
th.BasicClient.Logout()
Client := th.BasicClient
for i := 0; i < len(utils.FUZZY_STRINGS_NAMES) || i < len(utils.FUZZY_STRINGS_EMAILS); i++ { for i := 0; i < len(utils.FUZZY_STRINGS_NAMES) || i < len(utils.FUZZY_STRINGS_EMAILS); i++ {
testDisplayName := "Name" testDisplayName := "Name"
@@ -284,19 +461,24 @@ func TestFuzzyTeamCreate(t *testing.T) {
} }
func TestGetMyTeam(t *testing.T) { func TestGetMyTeam(t *testing.T) {
Setup() th := Setup().InitBasic()
th.BasicClient.Logout()
Client := th.BasicClient
team := model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN}
rteam, _ := Client.CreateTeam(&team) rteam, _ := Client.CreateTeam(team)
team = rteam.Data.(*model.Team)
user := model.User{TeamId: rteam.Data.(*model.Team).Id, Email: strings.ToLower(model.NewId()) + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"} user := model.User{Email: "success+" + model.NewId() + "@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
ruser, _ := Client.CreateUser(&user, "") ruser, _ := Client.CreateUser(&user, "")
LinkUserToTeam(ruser.Data.(*model.User), rteam.Data.(*model.Team))
store.Must(Srv.Store.User().VerifyEmail(ruser.Data.(*model.User).Id)) store.Must(Srv.Store.User().VerifyEmail(ruser.Data.(*model.User).Id))
Client.LoginByEmail(team.Name, user.Email, user.Password) Client.LoginByEmail(team.Name, user.Email, user.Password)
Client.SetTeamId(team.Id)
if result, err := Client.GetMyTeam(""); err != nil { if result, err := Client.GetMyTeam(""); err != nil {
t.Fatal("Failed to get user") t.Fatal(err)
} else { } else {
if result.Data.(*model.Team).DisplayName != team.DisplayName { if result.Data.(*model.Team).DisplayName != team.DisplayName {
t.Fatal("team names did not match") t.Fatal("team names did not match")
@@ -309,3 +491,14 @@ func TestGetMyTeam(t *testing.T) {
} }
} }
} }
func TestGetTeamMembers(t *testing.T) {
th := Setup().InitBasic()
if result, err := th.BasicClient.GetTeamMembers(th.BasicTeam.Id); err != nil {
t.Fatal(err)
} else {
members := result.Data.([]*model.TeamMember)
t.Log(members)
}
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@@ -7,7 +7,6 @@ import (
l4g "github.com/alecthomas/log4go" l4g "github.com/alecthomas/log4go"
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
"github.com/mattermost/platform/model" "github.com/mattermost/platform/model"
"github.com/mattermost/platform/store"
"github.com/mattermost/platform/utils" "github.com/mattermost/platform/utils"
"time" "time"
) )
@@ -21,14 +20,15 @@ const (
) )
type WebConn struct { type WebConn struct {
WebSocket *websocket.Conn WebSocket *websocket.Conn
Send chan *model.Message Send chan *model.Message
TeamId string SessionId string
UserId string UserId string
ChannelAccessCache map[string]bool hasPermissionsToChannel map[string]bool
hasPermissionsToTeam map[string]bool
} }
func NewWebConn(ws *websocket.Conn, teamId string, userId string, sessionId string) *WebConn { func NewWebConn(ws *websocket.Conn, userId string, sessionId string) *WebConn {
go func() { go func() {
achan := Srv.Store.User().UpdateUserAndSessionActivity(userId, sessionId, model.GetMillis()) achan := Srv.Store.User().UpdateUserAndSessionActivity(userId, sessionId, model.GetMillis())
pchan := Srv.Store.User().UpdateLastPingAt(userId, model.GetMillis()) pchan := Srv.Store.User().UpdateLastPingAt(userId, model.GetMillis())
@@ -42,7 +42,14 @@ func NewWebConn(ws *websocket.Conn, teamId string, userId string, sessionId stri
} }
}() }()
return &WebConn{Send: make(chan *model.Message, 64), WebSocket: ws, UserId: userId, TeamId: teamId, ChannelAccessCache: make(map[string]bool)} return &WebConn{
Send: make(chan *model.Message, 64),
WebSocket: ws,
UserId: userId,
SessionId: sessionId,
hasPermissionsToChannel: make(map[string]bool),
hasPermissionsToTeam: make(map[string]bool),
}
} }
func (c *WebConn) readPump() { func (c *WebConn) readPump() {
@@ -69,7 +76,6 @@ func (c *WebConn) readPump() {
if err := c.WebSocket.ReadJSON(&msg); err != nil { if err := c.WebSocket.ReadJSON(&msg); err != nil {
return return
} else { } else {
msg.TeamId = c.TeamId
msg.UserId = c.UserId msg.UserId = c.UserId
PublishAndForget(&msg) PublishAndForget(&msg)
} }
@@ -107,19 +113,53 @@ func (c *WebConn) writePump() {
} }
} }
func (c *WebConn) updateChannelAccessCache(channelId string) bool { func (c *WebConn) InvalidateCache() {
allowed := hasPermissionsToChannel(Srv.Store.Channel().CheckPermissionsTo(c.TeamId, channelId, c.UserId)) c.hasPermissionsToChannel = make(map[string]bool)
c.ChannelAccessCache[channelId] = allowed c.hasPermissionsToTeam = make(map[string]bool)
return allowed
} }
func hasPermissionsToChannel(sc store.StoreChannel) bool { func (c *WebConn) HasPermissionsToTeam(teamId string) bool {
if cresult := <-sc; cresult.Err != nil { perm, ok := c.hasPermissionsToTeam[teamId]
return false if !ok {
} else if cresult.Data.(int64) != 1 { session := GetSession(c.SessionId)
return false if session == nil {
perm = false
c.hasPermissionsToTeam[teamId] = perm
} else {
member := session.GetTeamByTeamId(teamId)
if member != nil {
perm = true
c.hasPermissionsToTeam[teamId] = perm
} else {
perm = true
c.hasPermissionsToTeam[teamId] = perm
}
}
} }
return true return perm
}
func (c *WebConn) HasPermissionsToChannel(channelId string) bool {
perm, ok := c.hasPermissionsToChannel[channelId]
if !ok {
if cresult := <-Srv.Store.Channel().CheckPermissionsToNoTeam(channelId, c.UserId); cresult.Err != nil {
perm = false
c.hasPermissionsToChannel[channelId] = perm
} else {
count := cresult.Data.(int64)
if count == 1 {
perm = true
c.hasPermissionsToChannel[channelId] = perm
} else {
perm = false
c.hasPermissionsToChannel[channelId] = perm
}
}
}
return perm
} }

Просмотреть файл

@@ -10,19 +10,21 @@ import (
) )
type Hub struct { type Hub struct {
teamHubs map[string]*TeamHub connections map[*WebConn]bool
register chan *WebConn register chan *WebConn
unregister chan *WebConn unregister chan *WebConn
broadcast chan *model.Message broadcast chan *model.Message
stop chan string stop chan string
invalidateUser chan string
} }
var hub = &Hub{ var hub = &Hub{
register: make(chan *WebConn), register: make(chan *WebConn),
unregister: make(chan *WebConn), unregister: make(chan *WebConn),
teamHubs: make(map[string]*TeamHub), connections: make(map[*WebConn]bool),
broadcast: make(chan *model.Message), broadcast: make(chan *model.Message),
stop: make(chan string), stop: make(chan string),
invalidateUser: make(chan string),
} }
func PublishAndForget(message *model.Message) { func PublishAndForget(message *model.Message) {
@@ -31,16 +33,8 @@ func PublishAndForget(message *model.Message) {
}() }()
} }
func UpdateChannelAccessCache(teamId, userId, channelId string) { func InvalidateCacheForUser(userId string) {
if nh, ok := hub.teamHubs[teamId]; ok { hub.invalidateUser <- userId
nh.UpdateChannelAccessCache(userId, channelId)
}
}
func UpdateChannelAccessCacheAndForget(teamId, userId, channelId string) {
go func() {
UpdateChannelAccessCache(teamId, userId, channelId)
}()
} }
func (h *Hub) Register(webConn *WebConn) { func (h *Hub) Register(webConn *WebConn) {
@@ -65,34 +59,92 @@ func (h *Hub) Start() {
go func() { go func() {
for { for {
select { select {
case webCon := <-h.register:
h.connections[webCon] = true
case c := <-h.register: case webCon := <-h.unregister:
nh := h.teamHubs[c.TeamId] if _, ok := h.connections[webCon]; ok {
delete(h.connections, webCon)
if nh == nil { close(webCon.Send)
nh = NewTeamHub(c.TeamId) }
h.teamHubs[c.TeamId] = nh case userId := <-h.invalidateUser:
nh.Start() for webCon := range h.connections {
if webCon.UserId == userId {
webCon.InvalidateCache()
}
} }
nh.Register(c)
case c := <-h.unregister:
if nh, ok := h.teamHubs[c.TeamId]; ok {
nh.Unregister(c)
}
case msg := <-h.broadcast: case msg := <-h.broadcast:
nh := h.teamHubs[msg.TeamId] for webCon := range h.connections {
if nh != nil { if shouldSendEvent(webCon, msg) {
nh.broadcast <- msg select {
case webCon.Send <- msg:
default:
close(webCon.Send)
delete(h.connections, webCon)
}
}
} }
case s := <-h.stop: case s := <-h.stop:
l4g.Debug(utils.T("api.web_hub.start.stopping.debug"), s) l4g.Debug(utils.T("api.web_hub.start.stopping.debug"), s)
for _, v := range h.teamHubs {
v.Stop() for webCon := range h.connections {
webCon.WebSocket.Close()
} }
return return
} }
} }
}() }()
} }
func shouldSendEvent(webCon *WebConn, msg *model.Message) bool {
if webCon.UserId == msg.UserId {
// Don't need to tell the user they are typing
if msg.Action == model.ACTION_TYPING {
return false
}
// We have to make sure the user is in the channel. Otherwise system messages that
// post about users in channels they are not in trigger warnings.
if len(msg.ChannelId) > 0 {
allowed := webCon.HasPermissionsToChannel(msg.ChannelId)
if !allowed {
return false
}
}
} else {
// Don't share a user's view or preference events with other users
if msg.Action == model.ACTION_CHANNEL_VIEWED {
return false
} else if msg.Action == model.ACTION_PREFERENCE_CHANGED {
return false
} else if msg.Action == model.ACTION_EPHEMERAL_MESSAGE {
// For now, ephemeral messages are sent directly to individual users
return false
}
// Only report events to users who are in the team for the event
if len(msg.TeamId) > 0 {
allowed := webCon.HasPermissionsToTeam(msg.TeamId)
if !allowed {
return false
}
}
// Only report events to users who are in the channel for the event
if len(msg.ChannelId) > 0 {
allowed := webCon.HasPermissionsToChannel(msg.ChannelId)
if !allowed {
return false
}
}
}
return true
}

Просмотреть файл

@@ -5,16 +5,15 @@ package api
import ( import (
l4g "github.com/alecthomas/log4go" l4g "github.com/alecthomas/log4go"
"github.com/gorilla/mux"
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
"github.com/mattermost/platform/model" "github.com/mattermost/platform/model"
"github.com/mattermost/platform/utils" "github.com/mattermost/platform/utils"
"net/http" "net/http"
) )
func InitWebSocket(r *mux.Router) { func InitWebSocket() {
l4g.Debug(utils.T("api.web_socket.init.debug")) l4g.Debug(utils.T("api.web_socket.init.debug"))
r.Handle("/websocket", ApiUserRequiredTrustRequester(connect)).Methods("GET") BaseRoutes.Users.Handle("/websocket", ApiUserRequiredTrustRequester(connect)).Methods("GET")
hub.Start() hub.Start()
} }
@@ -34,7 +33,7 @@ func connect(c *Context, w http.ResponseWriter, r *http.Request) {
return return
} }
wc := NewWebConn(ws, c.Session.TeamId, c.Session.UserId, c.Session.Id) wc := NewWebConn(ws, c.Session.UserId, c.Session.Id)
hub.Register(wc) hub.Register(wc)
go wc.writePump() go wc.writePump()
wc.readPump() wc.readPump()

Просмотреть файл

@@ -6,7 +6,6 @@ package api
import ( import (
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
"github.com/mattermost/platform/model" "github.com/mattermost/platform/model"
"github.com/mattermost/platform/store"
"github.com/mattermost/platform/utils" "github.com/mattermost/platform/utils"
"net/http" "net/http"
"testing" "testing"
@@ -14,22 +13,14 @@ import (
) )
func TestSocket(t *testing.T) { func TestSocket(t *testing.T) {
Setup() th := Setup().InitBasic()
Client := th.BasicClient
team := th.BasicTeam
channel1 := th.BasicChannel
channel2 := th.CreateChannel(Client, team)
Client.Must(Client.AddChannelMember(channel1.Id, th.BasicUser2.Id))
url := "ws://localhost" + utils.Cfg.ServiceSettings.ListenAddress + "/api/v1/websocket" url := "ws://localhost" + utils.Cfg.ServiceSettings.ListenAddress + model.API_URL_SUFFIX + "/users/websocket"
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN}
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user1.Id))
Client.LoginByEmail(team.Name, user1.Email, "pwd")
channel1 := &model.Channel{DisplayName: "Test Web Scoket 1", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel)
channel2 := &model.Channel{DisplayName: "Test Web Scoket 2", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
channel2 = Client.Must(Client.CreateChannel(channel2)).Data.(*model.Channel)
header1 := http.Header{} header1 := http.Header{}
header1.Set(model.HEADER_AUTH, "BEARER "+Client.AuthToken) header1.Set(model.HEADER_AUTH, "BEARER "+Client.AuthToken)
@@ -39,10 +30,7 @@ func TestSocket(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
user2 := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"} th.LoginBasic2()
user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user2.Id))
Client.LoginByEmail(team.Name, user2.Email, "pwd")
header2 := http.Header{} header2 := http.Header{}
header2.Set(model.HEADER_AUTH, "BEARER "+Client.AuthToken) header2.Set(model.HEADER_AUTH, "BEARER "+Client.AuthToken)
@@ -53,21 +41,11 @@ func TestSocket(t *testing.T) {
} }
time.Sleep(300 * time.Millisecond) time.Sleep(300 * time.Millisecond)
Client.Must(Client.JoinChannel(channel1.Id))
// Read the user_added message that gets generated
var rmsg model.Message var rmsg model.Message
if err := c2.ReadJSON(&rmsg); err != nil {
t.Fatal(err)
}
// Read the second user_added message that gets generated
if err := c2.ReadJSON(&rmsg); err != nil {
t.Fatal(err)
}
// Test sending message without a channelId // Test sending message without a channelId
m := model.NewMessage("", "", "", model.ACTION_TYPING) m := model.NewMessage(team.Id, "", "", model.ACTION_TYPING)
m.Add("RootId", model.NewId()) m.Add("RootId", model.NewId())
m.Add("ParentId", model.NewId()) m.Add("ParentId", model.NewId())
@@ -77,6 +55,8 @@ func TestSocket(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
t.Log(rmsg.ToJson())
if team.Id != rmsg.TeamId { if team.Id != rmsg.TeamId {
t.Fatal("Ids do not match") t.Fatal("Ids do not match")
} }
@@ -86,7 +66,7 @@ func TestSocket(t *testing.T) {
} }
// Test sending messsage to Channel you have access to // Test sending messsage to Channel you have access to
m = model.NewMessage("", channel1.Id, "", model.ACTION_TYPING) m = model.NewMessage(team.Id, channel1.Id, "", model.ACTION_TYPING)
m.Add("RootId", model.NewId()) m.Add("RootId", model.NewId())
m.Add("ParentId", model.NewId()) m.Add("ParentId", model.NewId())

Просмотреть файл

@@ -1,123 +0,0 @@
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api
import (
l4g "github.com/alecthomas/log4go"
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/utils"
)
type TeamHub struct {
connections map[*WebConn]bool
broadcast chan *model.Message
register chan *WebConn
unregister chan *WebConn
stop chan bool
teamId string
}
func NewTeamHub(teamId string) *TeamHub {
return &TeamHub{
broadcast: make(chan *model.Message),
register: make(chan *WebConn),
unregister: make(chan *WebConn),
connections: make(map[*WebConn]bool),
stop: make(chan bool),
teamId: teamId,
}
}
func (h *TeamHub) Register(webConn *WebConn) {
h.register <- webConn
}
func (h *TeamHub) Unregister(webConn *WebConn) {
h.unregister <- webConn
}
func (h *TeamHub) Stop() {
h.stop <- true
}
func (h *TeamHub) Start() {
go func() {
for {
select {
case webCon := <-h.register:
h.connections[webCon] = true
case webCon := <-h.unregister:
if _, ok := h.connections[webCon]; ok {
delete(h.connections, webCon)
close(webCon.Send)
}
case msg := <-h.broadcast:
for webCon := range h.connections {
if ShouldSendEvent(webCon, msg) {
select {
case webCon.Send <- msg:
default:
close(webCon.Send)
delete(h.connections, webCon)
}
}
}
case s := <-h.stop:
if s {
l4g.Debug(utils.T("api.web_team_hun.start.debug"), h.teamId)
for webCon := range h.connections {
webCon.WebSocket.Close()
}
return
}
}
}
}()
}
func (h *TeamHub) UpdateChannelAccessCache(userId string, channelId string) {
for webCon := range h.connections {
if webCon.UserId == userId {
webCon.updateChannelAccessCache(channelId)
break
}
}
}
func ShouldSendEvent(webCon *WebConn, msg *model.Message) bool {
if webCon.UserId == msg.UserId {
// Don't need to tell the user they are typing
if msg.Action == model.ACTION_TYPING {
return false
}
} else {
// Don't share a user's view or preference events with other users
if msg.Action == model.ACTION_CHANNEL_VIEWED {
return false
} else if msg.Action == model.ACTION_PREFERENCE_CHANGED {
return false
} else if msg.Action == model.ACTION_EPHEMERAL_MESSAGE {
// For now, ephemeral messages are sent directly to individual users
return false
}
// Only report events to a user who is the subject of the event, or is in the channel of the event
if len(msg.ChannelId) > 0 {
allowed, ok := webCon.ChannelAccessCache[msg.ChannelId]
if !ok {
allowed = webCon.updateChannelAccessCache(msg.ChannelId)
}
if !allowed {
return false
}
}
}
return true
}

Просмотреть файл

@@ -14,20 +14,19 @@ import (
"github.com/mattermost/platform/utils" "github.com/mattermost/platform/utils"
) )
func InitWebhook(r *mux.Router) { func InitWebhook() {
l4g.Debug(utils.T("api.webhook.init.debug")) l4g.Debug(utils.T("api.webhook.init.debug"))
sr := r.PathPrefix("/hooks").Subrouter() BaseRoutes.Hooks.Handle("/incoming/create", ApiUserRequired(createIncomingHook)).Methods("POST")
sr.Handle("/incoming/create", ApiUserRequired(createIncomingHook)).Methods("POST") BaseRoutes.Hooks.Handle("/incoming/delete", ApiUserRequired(deleteIncomingHook)).Methods("POST")
sr.Handle("/incoming/delete", ApiUserRequired(deleteIncomingHook)).Methods("POST") BaseRoutes.Hooks.Handle("/incoming/list", ApiUserRequired(getIncomingHooks)).Methods("GET")
sr.Handle("/incoming/list", ApiUserRequired(getIncomingHooks)).Methods("GET")
sr.Handle("/outgoing/create", ApiUserRequired(createOutgoingHook)).Methods("POST") BaseRoutes.Hooks.Handle("/outgoing/create", ApiUserRequired(createOutgoingHook)).Methods("POST")
sr.Handle("/outgoing/regen_token", ApiUserRequired(regenOutgoingHookToken)).Methods("POST") BaseRoutes.Hooks.Handle("/outgoing/regen_token", ApiUserRequired(regenOutgoingHookToken)).Methods("POST")
sr.Handle("/outgoing/delete", ApiUserRequired(deleteOutgoingHook)).Methods("POST") BaseRoutes.Hooks.Handle("/outgoing/delete", ApiUserRequired(deleteOutgoingHook)).Methods("POST")
sr.Handle("/outgoing/list", ApiUserRequired(getOutgoingHooks)).Methods("GET") BaseRoutes.Hooks.Handle("/outgoing/list", ApiUserRequired(getOutgoingHooks)).Methods("GET")
sr.Handle("/{id:[A-Za-z0-9]+}", ApiAppHandler(incomingWebhook)).Methods("POST") BaseRoutes.Hooks.Handle("/{id:[A-Za-z0-9]+}", ApiAppHandler(incomingWebhook)).Methods("POST")
// Old route. Remove eventually. // Old route. Remove eventually.
mr := Srv.Router mr := Srv.Router
@@ -59,10 +58,10 @@ func createIncomingHook(c *Context, w http.ResponseWriter, r *http.Request) {
} }
cchan := Srv.Store.Channel().Get(hook.ChannelId) cchan := Srv.Store.Channel().Get(hook.ChannelId)
pchan := Srv.Store.Channel().CheckPermissionsTo(c.Session.TeamId, hook.ChannelId, c.Session.UserId) pchan := Srv.Store.Channel().CheckPermissionsTo(c.TeamId, hook.ChannelId, c.Session.UserId)
hook.UserId = c.Session.UserId hook.UserId = c.Session.UserId
hook.TeamId = c.Session.TeamId hook.TeamId = c.TeamId
var channel *model.Channel var channel *model.Channel
if result := <-cchan; result.Err != nil { if result := <-cchan; result.Err != nil {
@@ -73,7 +72,7 @@ func createIncomingHook(c *Context, w http.ResponseWriter, r *http.Request) {
} }
if !c.HasPermissionsToChannel(pchan, "createIncomingHook") { if !c.HasPermissionsToChannel(pchan, "createIncomingHook") {
if channel.Type != model.CHANNEL_OPEN || channel.TeamId != c.Session.TeamId { if channel.Type != model.CHANNEL_OPEN || channel.TeamId != c.TeamId {
c.LogAudit("fail - bad channel permissions") c.LogAudit("fail - bad channel permissions")
return return
} }
@@ -149,7 +148,7 @@ func getIncomingHooks(c *Context, w http.ResponseWriter, r *http.Request) {
} }
} }
if result := <-Srv.Store.Webhook().GetIncomingByTeam(c.Session.TeamId); result.Err != nil { if result := <-Srv.Store.Webhook().GetIncomingByTeam(c.TeamId); result.Err != nil {
c.Err = result.Err c.Err = result.Err
return return
} else { } else {
@@ -183,11 +182,11 @@ func createOutgoingHook(c *Context, w http.ResponseWriter, r *http.Request) {
} }
hook.CreatorId = c.Session.UserId hook.CreatorId = c.Session.UserId
hook.TeamId = c.Session.TeamId hook.TeamId = c.TeamId
if len(hook.ChannelId) != 0 { if len(hook.ChannelId) != 0 {
cchan := Srv.Store.Channel().Get(hook.ChannelId) cchan := Srv.Store.Channel().Get(hook.ChannelId)
pchan := Srv.Store.Channel().CheckPermissionsTo(c.Session.TeamId, hook.ChannelId, c.Session.UserId) pchan := Srv.Store.Channel().CheckPermissionsTo(c.TeamId, hook.ChannelId, c.Session.UserId)
var channel *model.Channel var channel *model.Channel
if result := <-cchan; result.Err != nil { if result := <-cchan; result.Err != nil {
@@ -199,11 +198,14 @@ func createOutgoingHook(c *Context, w http.ResponseWriter, r *http.Request) {
if channel.Type != model.CHANNEL_OPEN { if channel.Type != model.CHANNEL_OPEN {
c.LogAudit("fail - not open channel") c.LogAudit("fail - not open channel")
c.Err = model.NewLocAppError("createOutgoingHook", "api.webhook.create_outgoing.not_open.app_error", nil, "")
return
} }
if !c.HasPermissionsToChannel(pchan, "createOutgoingHook") { if !c.HasPermissionsToChannel(pchan, "createOutgoingHook") {
if channel.Type != model.CHANNEL_OPEN || channel.TeamId != c.Session.TeamId { if channel.Type != model.CHANNEL_OPEN || channel.TeamId != c.TeamId {
c.LogAudit("fail - bad channel permissions") c.LogAudit("fail - bad channel permissions")
c.Err = model.NewLocAppError("createOutgoingHook", "api.webhook.create_outgoing.permissions.app_error", nil, "")
return return
} }
} }
@@ -237,7 +239,7 @@ func getOutgoingHooks(c *Context, w http.ResponseWriter, r *http.Request) {
} }
} }
if result := <-Srv.Store.Webhook().GetOutgoingByTeam(c.Session.TeamId); result.Err != nil { if result := <-Srv.Store.Webhook().GetOutgoingByTeam(c.TeamId); result.Err != nil {
c.Err = result.Err c.Err = result.Err
return return
} else { } else {
@@ -292,7 +294,7 @@ func deleteOutgoingHook(c *Context, w http.ResponseWriter, r *http.Request) {
} }
func regenOutgoingHookToken(c *Context, w http.ResponseWriter, r *http.Request) { func regenOutgoingHookToken(c *Context, w http.ResponseWriter, r *http.Request) {
if !utils.Cfg.ServiceSettings.EnableIncomingWebhooks { if !utils.Cfg.ServiceSettings.EnableOutgoingWebhooks {
c.Err = model.NewLocAppError("regenOutgoingHookToken", "api.webhook.regen_outgoing_token.disabled.app_error", nil, "") c.Err = model.NewLocAppError("regenOutgoingHookToken", "api.webhook.regen_outgoing_token.disabled.app_error", nil, "")
c.Err.StatusCode = http.StatusNotImplemented c.Err.StatusCode = http.StatusNotImplemented
return return
@@ -323,7 +325,7 @@ func regenOutgoingHookToken(c *Context, w http.ResponseWriter, r *http.Request)
} else { } else {
hook = result.Data.(*model.OutgoingWebhook) hook = result.Data.(*model.OutgoingWebhook)
if c.Session.TeamId != hook.TeamId && c.Session.UserId != hook.CreatorId && !c.IsTeamAdmin() { if c.TeamId != hook.TeamId && c.Session.UserId != hook.CreatorId && !c.IsTeamAdmin() {
c.LogAudit("fail - inappropriate permissions") c.LogAudit("fail - inappropriate permissions")
c.Err = model.NewLocAppError("regenOutgoingHookToken", "api.webhook.regen_outgoing_token.permissions.app_error", nil, "user_id="+c.Session.UserId) c.Err = model.NewLocAppError("regenOutgoingHookToken", "api.webhook.regen_outgoing_token.permissions.app_error", nil, "user_id="+c.Session.UserId)
return return
@@ -398,7 +400,7 @@ func incomingWebhook(c *Context, w http.ResponseWriter, r *http.Request) {
if len(channelName) != 0 { if len(channelName) != 0 {
if channelName[0] == '@' { if channelName[0] == '@' {
if result := <-Srv.Store.User().GetByUsername(hook.TeamId, channelName[1:]); result.Err != nil { if result := <-Srv.Store.User().GetByUsername(channelName[1:]); result.Err != nil {
c.Err = model.NewLocAppError("incomingWebhook", "web.incoming_webhook.user.app_error", nil, "err="+result.Err.Message) c.Err = model.NewLocAppError("incomingWebhook", "web.incoming_webhook.user.app_error", nil, "err="+result.Err.Message)
return return
} else { } else {
@@ -426,7 +428,11 @@ func incomingWebhook(c *Context, w http.ResponseWriter, r *http.Request) {
pchan := Srv.Store.Channel().CheckPermissionsTo(hook.TeamId, channel.Id, hook.UserId) pchan := Srv.Store.Channel().CheckPermissionsTo(hook.TeamId, channel.Id, hook.UserId)
// create a mock session // create a mock session
c.Session = model.Session{UserId: hook.UserId, TeamId: hook.TeamId, IsOAuth: false} c.Session = model.Session{
UserId: hook.UserId,
TeamMembers: []*model.TeamMember{{TeamId: hook.TeamId, UserId: hook.UserId}},
IsOAuth: false,
}
if !c.HasPermissionsToChannel(pchan, "createIncomingHook") && channel.Type != model.CHANNEL_OPEN { if !c.HasPermissionsToChannel(pchan, "createIncomingHook") && channel.Type != model.CHANNEL_OPEN {
c.Err = model.NewLocAppError("incomingWebhook", "web.incoming_webhook.permissions.app_error", nil, "") c.Err = model.NewLocAppError("incomingWebhook", "web.incoming_webhook.permissions.app_error", nil, "")

Просмотреть файл

@@ -4,416 +4,599 @@
package api package api
import ( import (
"fmt"
"github.com/mattermost/platform/model" "github.com/mattermost/platform/model"
"github.com/mattermost/platform/store"
"github.com/mattermost/platform/utils" "github.com/mattermost/platform/utils"
"testing" "testing"
"time" "time"
) )
func TestCreateIncomingHook(t *testing.T) { func TestCreateIncomingHook(t *testing.T) {
Setup() th := Setup().InitSystemAdmin()
Client := th.SystemAdminClient
user := th.SystemAdminUser
team := th.SystemAdminTeam
channel1 := th.CreateChannel(Client, team)
channel2 := th.CreatePrivateChannel(Client, team)
user2 := th.CreateUser(Client)
LinkUserToTeam(user2, team)
enableIncomingHooks := utils.Cfg.ServiceSettings.EnableIncomingWebhooks enableIncomingHooks := utils.Cfg.ServiceSettings.EnableIncomingWebhooks
enableOutgoingHooks := utils.Cfg.ServiceSettings.EnableOutgoingWebhooks enableAdminOnlyHooks := utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations
defer func() { defer func() {
utils.Cfg.ServiceSettings.EnableIncomingWebhooks = enableIncomingHooks utils.Cfg.ServiceSettings.EnableIncomingWebhooks = enableIncomingHooks
utils.Cfg.ServiceSettings.EnableOutgoingWebhooks = enableOutgoingHooks utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations = enableAdminOnlyHooks
}() }()
utils.Cfg.ServiceSettings.EnableIncomingWebhooks = true utils.Cfg.ServiceSettings.EnableIncomingWebhooks = true
utils.Cfg.ServiceSettings.EnableOutgoingWebhooks = true *utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations = true
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN}
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
user := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user.Id))
c := &Context{}
c.RequestId = model.NewId()
c.IpAddress = "cmd_line"
UpdateRoles(c, user, model.ROLE_SYSTEM_ADMIN)
Client.LoginByEmail(team.Name, user.Email, "pwd")
channel1 := &model.Channel{DisplayName: "Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel)
channel2 := &model.Channel{DisplayName: "Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
channel2 = Client.Must(Client.CreateChannel(channel2)).Data.(*model.Channel)
hook := &model.IncomingWebhook{ChannelId: channel1.Id} hook := &model.IncomingWebhook{ChannelId: channel1.Id}
if utils.Cfg.ServiceSettings.EnableIncomingWebhooks { var rhook *model.IncomingWebhook
var rhook *model.IncomingWebhook if result, err := Client.CreateIncomingWebhook(hook); err != nil {
if result, err := Client.CreateIncomingWebhook(hook); err != nil { t.Fatal(err)
t.Fatal(err)
} else {
rhook = result.Data.(*model.IncomingWebhook)
}
if hook.ChannelId != rhook.ChannelId {
t.Fatal("channel ids didn't match")
}
if rhook.UserId != user.Id {
t.Fatal("user ids didn't match")
}
if rhook.TeamId != team.Id {
t.Fatal("team ids didn't match")
}
hook = &model.IncomingWebhook{ChannelId: "junk"}
if _, err := Client.CreateIncomingWebhook(hook); err == nil {
t.Fatal("should have failed - bad channel id")
}
hook = &model.IncomingWebhook{ChannelId: channel2.Id, UserId: "123", TeamId: "456"}
if result, err := Client.CreateIncomingWebhook(hook); err != nil {
t.Fatal(err)
} else {
if result.Data.(*model.IncomingWebhook).UserId != user.Id {
t.Fatal("bad user id wasn't overwritten")
}
if result.Data.(*model.IncomingWebhook).TeamId != team.Id {
t.Fatal("bad team id wasn't overwritten")
}
}
} else { } else {
if _, err := Client.CreateIncomingWebhook(hook); err == nil { rhook = result.Data.(*model.IncomingWebhook)
t.Fatal("should have errored - webhooks turned off") }
if hook.ChannelId != rhook.ChannelId {
t.Fatal("channel ids didn't match")
}
if rhook.UserId != user.Id {
t.Fatal("user ids didn't match")
}
if rhook.TeamId != team.Id {
t.Fatal("team ids didn't match")
}
hook = &model.IncomingWebhook{ChannelId: "junk"}
if _, err := Client.CreateIncomingWebhook(hook); err == nil {
t.Fatal("should have failed - bad channel id")
}
hook = &model.IncomingWebhook{ChannelId: channel2.Id, UserId: "123", TeamId: "456"}
if result, err := Client.CreateIncomingWebhook(hook); err != nil {
t.Fatal(err)
} else {
if result.Data.(*model.IncomingWebhook).UserId != user.Id {
t.Fatal("bad user id wasn't overwritten")
} }
if result.Data.(*model.IncomingWebhook).TeamId != team.Id {
t.Fatal("bad team id wasn't overwritten")
}
}
Client.Logout()
Client.Must(Client.LoginById(user2.Id, user2.Password))
Client.SetTeamId(team.Id)
hook = &model.IncomingWebhook{ChannelId: channel1.Id}
if _, err := Client.CreateIncomingWebhook(hook); err == nil {
t.Fatal("should have failed - not system/team admin")
}
*utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations = false
if _, err := Client.CreateIncomingWebhook(hook); err != nil {
t.Fatal(err)
}
hook = &model.IncomingWebhook{ChannelId: channel2.Id}
if _, err := Client.CreateIncomingWebhook(hook); err == nil {
t.Fatal("should have failed - channel is private and not a member")
}
utils.Cfg.ServiceSettings.EnableIncomingWebhooks = false
if _, err := Client.CreateIncomingWebhook(hook); err == nil {
t.Fatal("should have errored - webhooks turned off")
} }
} }
func TestListIncomingHooks(t *testing.T) { func TestListIncomingHooks(t *testing.T) {
Setup() th := Setup().InitSystemAdmin()
Client := th.SystemAdminClient
team := th.SystemAdminTeam
channel1 := th.CreateChannel(Client, team)
user2 := th.CreateUser(Client)
LinkUserToTeam(user2, team)
enableIncomingHooks := utils.Cfg.ServiceSettings.EnableIncomingWebhooks enableIncomingHooks := utils.Cfg.ServiceSettings.EnableIncomingWebhooks
enableOutgoingHooks := utils.Cfg.ServiceSettings.EnableOutgoingWebhooks enableAdminOnlyHooks := utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations
defer func() { defer func() {
utils.Cfg.ServiceSettings.EnableIncomingWebhooks = enableIncomingHooks utils.Cfg.ServiceSettings.EnableIncomingWebhooks = enableIncomingHooks
utils.Cfg.ServiceSettings.EnableOutgoingWebhooks = enableOutgoingHooks utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations = enableAdminOnlyHooks
}() }()
utils.Cfg.ServiceSettings.EnableIncomingWebhooks = true utils.Cfg.ServiceSettings.EnableIncomingWebhooks = true
utils.Cfg.ServiceSettings.EnableOutgoingWebhooks = true *utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations = true
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} hook1 := &model.IncomingWebhook{ChannelId: channel1.Id}
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team) hook1 = Client.Must(Client.CreateIncomingWebhook(hook1)).Data.(*model.IncomingWebhook)
user := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"} hook2 := &model.IncomingWebhook{ChannelId: channel1.Id}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User) hook2 = Client.Must(Client.CreateIncomingWebhook(hook2)).Data.(*model.IncomingWebhook)
store.Must(Srv.Store.User().VerifyEmail(user.Id))
c := &Context{} if result, err := Client.ListIncomingWebhooks(); err != nil {
c.RequestId = model.NewId() t.Fatal(err)
c.IpAddress = "cmd_line"
UpdateRoles(c, user, model.ROLE_SYSTEM_ADMIN)
Client.LoginByEmail(team.Name, user.Email, "pwd")
channel1 := &model.Channel{DisplayName: "Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel)
if utils.Cfg.ServiceSettings.EnableIncomingWebhooks {
hook1 := &model.IncomingWebhook{ChannelId: channel1.Id}
hook1 = Client.Must(Client.CreateIncomingWebhook(hook1)).Data.(*model.IncomingWebhook)
hook2 := &model.IncomingWebhook{ChannelId: channel1.Id}
hook2 = Client.Must(Client.CreateIncomingWebhook(hook2)).Data.(*model.IncomingWebhook)
if result, err := Client.ListIncomingWebhooks(); err != nil {
t.Fatal(err)
} else {
hooks := result.Data.([]*model.IncomingWebhook)
if len(hooks) != 2 {
t.Fatal("incorrect number of hooks")
}
}
} else { } else {
if _, err := Client.ListIncomingWebhooks(); err == nil { hooks := result.Data.([]*model.IncomingWebhook)
t.Fatal("should have errored - webhooks turned off")
if len(hooks) != 2 {
t.Fatal("incorrect number of hooks")
} }
} }
Client.Logout()
Client.Must(Client.LoginById(user2.Id, user2.Password))
Client.SetTeamId(team.Id)
if _, err := Client.ListIncomingWebhooks(); err == nil {
t.Fatal("should have errored - not system/team admin")
}
*utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations = false
if _, err := Client.ListIncomingWebhooks(); err != nil {
t.Fatal(err)
}
utils.Cfg.ServiceSettings.EnableIncomingWebhooks = false
if _, err := Client.ListIncomingWebhooks(); err == nil {
t.Fatal("should have errored - webhooks turned off")
}
} }
func TestDeleteIncomingHook(t *testing.T) { func TestDeleteIncomingHook(t *testing.T) {
Setup() th := Setup().InitSystemAdmin()
Client := th.SystemAdminClient
team := th.SystemAdminTeam
channel1 := th.CreateChannel(Client, team)
user2 := th.CreateUser(Client)
LinkUserToTeam(user2, team)
enableIncomingHooks := utils.Cfg.ServiceSettings.EnableIncomingWebhooks enableIncomingHooks := utils.Cfg.ServiceSettings.EnableIncomingWebhooks
enableOutgoingHooks := utils.Cfg.ServiceSettings.EnableOutgoingWebhooks enableAdminOnlyHooks := utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations
defer func() { defer func() {
utils.Cfg.ServiceSettings.EnableIncomingWebhooks = enableIncomingHooks utils.Cfg.ServiceSettings.EnableIncomingWebhooks = enableIncomingHooks
utils.Cfg.ServiceSettings.EnableOutgoingWebhooks = enableOutgoingHooks utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations = enableAdminOnlyHooks
}() }()
utils.Cfg.ServiceSettings.EnableIncomingWebhooks = true utils.Cfg.ServiceSettings.EnableIncomingWebhooks = true
utils.Cfg.ServiceSettings.EnableOutgoingWebhooks = true *utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations = true
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} hook := &model.IncomingWebhook{ChannelId: channel1.Id}
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team) hook = Client.Must(Client.CreateIncomingWebhook(hook)).Data.(*model.IncomingWebhook)
user := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"} if _, err := Client.DeleteIncomingWebhook(hook.Id); err != nil {
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User) t.Fatal(err)
store.Must(Srv.Store.User().VerifyEmail(user.Id)) }
c := &Context{} if _, err := Client.DeleteIncomingWebhook("junk"); err == nil {
c.RequestId = model.NewId() t.Fatal("should have failed - bad id")
c.IpAddress = "cmd_line" }
UpdateRoles(c, user, model.ROLE_SYSTEM_ADMIN)
Client.LoginByEmail(team.Name, user.Email, "pwd")
channel1 := &model.Channel{DisplayName: "Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} if _, err := Client.DeleteIncomingWebhook(""); err == nil {
channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel) t.Fatal("should have failed - empty id")
}
if utils.Cfg.ServiceSettings.EnableIncomingWebhooks { hooks := Client.Must(Client.ListIncomingWebhooks()).Data.([]*model.IncomingWebhook)
hook := &model.IncomingWebhook{ChannelId: channel1.Id} if len(hooks) != 0 {
hook = Client.Must(Client.CreateIncomingWebhook(hook)).Data.(*model.IncomingWebhook) t.Fatal("delete didn't work properly")
}
data := make(map[string]string) hook = &model.IncomingWebhook{ChannelId: channel1.Id}
data["id"] = hook.Id hook = Client.Must(Client.CreateIncomingWebhook(hook)).Data.(*model.IncomingWebhook)
if _, err := Client.DeleteIncomingWebhook(data); err != nil { Client.Logout()
t.Fatal(err) Client.Must(Client.LoginById(user2.Id, user2.Password))
} Client.SetTeamId(team.Id)
hooks := Client.Must(Client.ListIncomingWebhooks()).Data.([]*model.IncomingWebhook) if _, err := Client.DeleteIncomingWebhook(hook.Id); err == nil {
if len(hooks) != 0 { t.Fatal("should have failed - not system/team admin")
t.Fatal("delete didn't work properly") }
}
} else {
data := make(map[string]string)
data["id"] = "123"
if _, err := Client.DeleteIncomingWebhook(data); err == nil { *utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations = false
t.Fatal("should have errored - webhooks turned off")
} if _, err := Client.DeleteIncomingWebhook(hook.Id); err == nil {
t.Fatal("should have failed - not creator or team admin")
}
hook = &model.IncomingWebhook{ChannelId: channel1.Id}
hook = Client.Must(Client.CreateIncomingWebhook(hook)).Data.(*model.IncomingWebhook)
if _, err := Client.DeleteIncomingWebhook(hook.Id); err != nil {
t.Fatal(err)
}
utils.Cfg.ServiceSettings.EnableIncomingWebhooks = false
if _, err := Client.DeleteIncomingWebhook(hook.Id); err == nil {
t.Fatal("should have errored - webhooks turned off")
} }
} }
func TestCreateOutgoingHook(t *testing.T) { func TestCreateOutgoingHook(t *testing.T) {
Setup() th := Setup().InitSystemAdmin()
enableIncomingHooks := utils.Cfg.ServiceSettings.EnableIncomingWebhooks Client := th.SystemAdminClient
user := th.SystemAdminUser
team := th.SystemAdminTeam
team2 := th.CreateTeam(Client)
channel1 := th.CreateChannel(Client, team)
channel2 := th.CreatePrivateChannel(Client, team)
user2 := th.CreateUser(Client)
LinkUserToTeam(user2, team)
user3 := th.CreateUser(Client)
LinkUserToTeam(user3, team2)
enableOutgoingHooks := utils.Cfg.ServiceSettings.EnableOutgoingWebhooks enableOutgoingHooks := utils.Cfg.ServiceSettings.EnableOutgoingWebhooks
enableAdminOnlyHooks := utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations
defer func() { defer func() {
utils.Cfg.ServiceSettings.EnableIncomingWebhooks = enableIncomingHooks
utils.Cfg.ServiceSettings.EnableOutgoingWebhooks = enableOutgoingHooks utils.Cfg.ServiceSettings.EnableOutgoingWebhooks = enableOutgoingHooks
utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations = enableAdminOnlyHooks
}() }()
utils.Cfg.ServiceSettings.EnableIncomingWebhooks = true
utils.Cfg.ServiceSettings.EnableOutgoingWebhooks = true utils.Cfg.ServiceSettings.EnableOutgoingWebhooks = true
*utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations = true
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN}
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
user := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user.Id))
c := &Context{}
c.RequestId = model.NewId()
c.IpAddress = "cmd_line"
UpdateRoles(c, user, model.ROLE_SYSTEM_ADMIN)
Client.LoginByEmail(team.Name, user.Email, "pwd")
channel1 := &model.Channel{DisplayName: "Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel)
channel2 := &model.Channel{DisplayName: "Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
channel2 = Client.Must(Client.CreateChannel(channel2)).Data.(*model.Channel)
hook := &model.OutgoingWebhook{ChannelId: channel1.Id, CallbackURLs: []string{"http://nowhere.com"}} hook := &model.OutgoingWebhook{ChannelId: channel1.Id, CallbackURLs: []string{"http://nowhere.com"}}
if utils.Cfg.ServiceSettings.EnableOutgoingWebhooks { var rhook *model.OutgoingWebhook
var rhook *model.OutgoingWebhook if result, err := Client.CreateOutgoingWebhook(hook); err != nil {
if result, err := Client.CreateOutgoingWebhook(hook); err != nil { t.Fatal(err)
t.Fatal(err)
} else {
rhook = result.Data.(*model.OutgoingWebhook)
}
if hook.ChannelId != rhook.ChannelId {
t.Fatal("channel ids didn't match")
}
if rhook.CreatorId != user.Id {
t.Fatal("user ids didn't match")
}
if rhook.TeamId != team.Id {
t.Fatal("team ids didn't match")
}
hook = &model.OutgoingWebhook{ChannelId: "junk", CallbackURLs: []string{"http://nowhere.com"}}
if _, err := Client.CreateOutgoingWebhook(hook); err == nil {
t.Fatal("should have failed - bad channel id")
}
hook = &model.OutgoingWebhook{ChannelId: channel2.Id, CreatorId: "123", TeamId: "456", CallbackURLs: []string{"http://nowhere.com"}}
if result, err := Client.CreateOutgoingWebhook(hook); err != nil {
t.Fatal(err)
} else {
if result.Data.(*model.OutgoingWebhook).CreatorId != user.Id {
t.Fatal("bad user id wasn't overwritten")
}
if result.Data.(*model.OutgoingWebhook).TeamId != team.Id {
t.Fatal("bad team id wasn't overwritten")
}
}
} else { } else {
if _, err := Client.CreateOutgoingWebhook(hook); err == nil { rhook = result.Data.(*model.OutgoingWebhook)
t.Fatal("should have errored - webhooks turned off") }
if hook.ChannelId != rhook.ChannelId {
t.Fatal("channel ids didn't match")
}
if rhook.CreatorId != user.Id {
t.Fatal("user ids didn't match")
}
if rhook.TeamId != team.Id {
t.Fatal("team ids didn't match")
}
hook = &model.OutgoingWebhook{ChannelId: "junk", CallbackURLs: []string{"http://nowhere.com"}}
if _, err := Client.CreateOutgoingWebhook(hook); err == nil {
t.Fatal("should have failed - bad channel id")
}
hook = &model.OutgoingWebhook{ChannelId: channel1.Id, CreatorId: "123", TeamId: "456", CallbackURLs: []string{"http://nowhere.com"}}
if result, err := Client.CreateOutgoingWebhook(hook); err != nil {
t.Fatal(err)
} else {
if result.Data.(*model.OutgoingWebhook).CreatorId != user.Id {
t.Fatal("bad user id wasn't overwritten")
} }
if result.Data.(*model.OutgoingWebhook).TeamId != team.Id {
t.Fatal("bad team id wasn't overwritten")
}
}
hook = &model.OutgoingWebhook{ChannelId: channel2.Id, CallbackURLs: []string{"http://nowhere.com"}}
if _, err := Client.CreateOutgoingWebhook(hook); err == nil {
t.Fatal("should have failed - private channel")
}
hook = &model.OutgoingWebhook{CallbackURLs: []string{"http://nowhere.com"}}
if _, err := Client.CreateOutgoingWebhook(hook); err == nil {
t.Fatal("should have failed - blank channel and trigger words")
}
Client.Logout()
Client.Must(Client.LoginById(user2.Id, user2.Password))
Client.SetTeamId(team.Id)
hook = &model.OutgoingWebhook{ChannelId: channel1.Id, CallbackURLs: []string{"http://nowhere.com"}}
if _, err := Client.CreateOutgoingWebhook(hook); err == nil {
t.Fatal("should have failed - not system/team admin")
}
*utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations = false
if _, err := Client.CreateOutgoingWebhook(hook); err != nil {
t.Fatal(err)
}
Client.Logout()
Client.Must(Client.LoginById(user3.Id, user3.Password))
Client.SetTeamId(team2.Id)
if _, err := Client.CreateOutgoingWebhook(hook); err == nil {
t.Fatal("should have failed - wrong team")
}
utils.Cfg.ServiceSettings.EnableOutgoingWebhooks = false
if _, err := Client.CreateOutgoingWebhook(hook); err == nil {
t.Fatal("should have errored - webhooks turned off")
} }
} }
func TestListOutgoingHooks(t *testing.T) { func TestListOutgoingHooks(t *testing.T) {
Setup() th := Setup().InitSystemAdmin()
enableIncomingHooks := utils.Cfg.ServiceSettings.EnableIncomingWebhooks Client := th.SystemAdminClient
team := th.SystemAdminTeam
channel1 := th.CreateChannel(Client, team)
user2 := th.CreateUser(Client)
LinkUserToTeam(user2, team)
enableOutgoingHooks := utils.Cfg.ServiceSettings.EnableOutgoingWebhooks enableOutgoingHooks := utils.Cfg.ServiceSettings.EnableOutgoingWebhooks
enableAdminOnlyHooks := utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations
defer func() { defer func() {
utils.Cfg.ServiceSettings.EnableIncomingWebhooks = enableIncomingHooks
utils.Cfg.ServiceSettings.EnableOutgoingWebhooks = enableOutgoingHooks utils.Cfg.ServiceSettings.EnableOutgoingWebhooks = enableOutgoingHooks
utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations = enableAdminOnlyHooks
}() }()
utils.Cfg.ServiceSettings.EnableIncomingWebhooks = true
utils.Cfg.ServiceSettings.EnableOutgoingWebhooks = true utils.Cfg.ServiceSettings.EnableOutgoingWebhooks = true
*utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations = true
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} hook1 := &model.OutgoingWebhook{ChannelId: channel1.Id, CallbackURLs: []string{"http://nowhere.com"}}
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team) hook1 = Client.Must(Client.CreateOutgoingWebhook(hook1)).Data.(*model.OutgoingWebhook)
user := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"} hook2 := &model.OutgoingWebhook{TriggerWords: []string{"trigger"}, CallbackURLs: []string{"http://nowhere.com"}}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User) hook2 = Client.Must(Client.CreateOutgoingWebhook(hook2)).Data.(*model.OutgoingWebhook)
store.Must(Srv.Store.User().VerifyEmail(user.Id))
c := &Context{} if result, err := Client.ListOutgoingWebhooks(); err != nil {
c.RequestId = model.NewId() t.Fatal(err)
c.IpAddress = "cmd_line"
UpdateRoles(c, user, model.ROLE_SYSTEM_ADMIN)
Client.LoginByEmail(team.Name, user.Email, "pwd")
channel1 := &model.Channel{DisplayName: "Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel)
if utils.Cfg.ServiceSettings.EnableOutgoingWebhooks {
hook1 := &model.OutgoingWebhook{ChannelId: channel1.Id, CallbackURLs: []string{"http://nowhere.com"}}
hook1 = Client.Must(Client.CreateOutgoingWebhook(hook1)).Data.(*model.OutgoingWebhook)
hook2 := &model.OutgoingWebhook{TriggerWords: []string{"trigger"}, CallbackURLs: []string{"http://nowhere.com"}}
hook2 = Client.Must(Client.CreateOutgoingWebhook(hook2)).Data.(*model.OutgoingWebhook)
if result, err := Client.ListOutgoingWebhooks(); err != nil {
t.Fatal(err)
} else {
hooks := result.Data.([]*model.OutgoingWebhook)
if len(hooks) != 2 {
t.Fatal("incorrect number of hooks")
}
}
} else { } else {
if _, err := Client.ListOutgoingWebhooks(); err == nil { hooks := result.Data.([]*model.OutgoingWebhook)
t.Fatal("should have errored - webhooks turned off")
if len(hooks) != 2 {
t.Fatal("incorrect number of hooks")
} }
} }
Client.Logout()
Client.Must(Client.LoginById(user2.Id, user2.Password))
Client.SetTeamId(team.Id)
if _, err := Client.ListOutgoingWebhooks(); err == nil {
t.Fatal("should have failed - not system/team admin")
}
*utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations = false
if _, err := Client.ListOutgoingWebhooks(); err != nil {
t.Fatal(err)
}
utils.Cfg.ServiceSettings.EnableOutgoingWebhooks = false
if _, err := Client.ListOutgoingWebhooks(); err == nil {
t.Fatal("should have errored - webhooks turned off")
}
} }
func TestDeleteOutgoingHook(t *testing.T) { func TestDeleteOutgoingHook(t *testing.T) {
Setup() th := Setup().InitSystemAdmin()
enableIncomingHooks := utils.Cfg.ServiceSettings.EnableIncomingWebhooks Client := th.SystemAdminClient
team := th.SystemAdminTeam
channel1 := th.CreateChannel(Client, team)
user2 := th.CreateUser(Client)
LinkUserToTeam(user2, team)
enableOutgoingHooks := utils.Cfg.ServiceSettings.EnableOutgoingWebhooks enableOutgoingHooks := utils.Cfg.ServiceSettings.EnableOutgoingWebhooks
enableAdminOnlyHooks := utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations
defer func() { defer func() {
utils.Cfg.ServiceSettings.EnableIncomingWebhooks = enableIncomingHooks
utils.Cfg.ServiceSettings.EnableOutgoingWebhooks = enableOutgoingHooks utils.Cfg.ServiceSettings.EnableOutgoingWebhooks = enableOutgoingHooks
utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations = enableAdminOnlyHooks
}() }()
utils.Cfg.ServiceSettings.EnableIncomingWebhooks = true
utils.Cfg.ServiceSettings.EnableOutgoingWebhooks = true utils.Cfg.ServiceSettings.EnableOutgoingWebhooks = true
*utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations = true
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} hook := &model.OutgoingWebhook{ChannelId: channel1.Id, CallbackURLs: []string{"http://nowhere.com"}}
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team) hook = Client.Must(Client.CreateOutgoingWebhook(hook)).Data.(*model.OutgoingWebhook)
user := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"} if _, err := Client.DeleteOutgoingWebhook("junk"); err == nil {
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User) t.Fatal("should have failed - bad hook id")
store.Must(Srv.Store.User().VerifyEmail(user.Id)) }
c := &Context{} if _, err := Client.DeleteOutgoingWebhook(""); err == nil {
c.RequestId = model.NewId() t.Fatal("should have failed - empty hook id")
c.IpAddress = "cmd_line" }
UpdateRoles(c, user, model.ROLE_SYSTEM_ADMIN)
Client.LoginByEmail(team.Name, user.Email, "pwd")
channel1 := &model.Channel{DisplayName: "Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} if _, err := Client.DeleteOutgoingWebhook(hook.Id); err != nil {
channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel) t.Fatal(err)
}
if utils.Cfg.ServiceSettings.EnableOutgoingWebhooks { hooks := Client.Must(Client.ListOutgoingWebhooks()).Data.([]*model.OutgoingWebhook)
hook := &model.OutgoingWebhook{ChannelId: channel1.Id, CallbackURLs: []string{"http://nowhere.com"}} if len(hooks) != 0 {
hook = Client.Must(Client.CreateOutgoingWebhook(hook)).Data.(*model.OutgoingWebhook) t.Fatal("delete didn't work properly")
}
data := make(map[string]string) hook = &model.OutgoingWebhook{ChannelId: channel1.Id, CallbackURLs: []string{"http://nowhere.com"}}
data["id"] = hook.Id hook = Client.Must(Client.CreateOutgoingWebhook(hook)).Data.(*model.OutgoingWebhook)
if _, err := Client.DeleteOutgoingWebhook(data); err != nil { Client.Logout()
t.Fatal(err) Client.Must(Client.LoginById(user2.Id, user2.Password))
} Client.SetTeamId(team.Id)
hooks := Client.Must(Client.ListOutgoingWebhooks()).Data.([]*model.OutgoingWebhook) if _, err := Client.DeleteOutgoingWebhook(hook.Id); err == nil {
if len(hooks) != 0 { t.Fatal("should have failed - not system/team admin")
t.Fatal("delete didn't work properly") }
}
} else {
data := make(map[string]string)
data["id"] = "123"
if _, err := Client.DeleteOutgoingWebhook(data); err == nil { *utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations = false
t.Fatal("should have errored - webhooks turned off")
} if _, err := Client.DeleteOutgoingWebhook(hook.Id); err == nil {
t.Fatal("should have failed - not creator or team admin")
}
hook = &model.OutgoingWebhook{ChannelId: channel1.Id, CallbackURLs: []string{"http://nowhere.com"}}
hook = Client.Must(Client.CreateOutgoingWebhook(hook)).Data.(*model.OutgoingWebhook)
if _, err := Client.DeleteOutgoingWebhook(hook.Id); err != nil {
t.Fatal(err)
}
utils.Cfg.ServiceSettings.EnableOutgoingWebhooks = false
if _, err := Client.DeleteOutgoingWebhook(hook.Id); err == nil {
t.Fatal("should have errored - webhooks turned off")
} }
} }
func TestRegenOutgoingHookToken(t *testing.T) { func TestRegenOutgoingHookToken(t *testing.T) {
Setup() th := Setup().InitSystemAdmin()
enableIncomingHooks := utils.Cfg.ServiceSettings.EnableIncomingWebhooks Client := th.SystemAdminClient
team := th.SystemAdminTeam
team2 := th.CreateTeam(Client)
channel1 := th.CreateChannel(Client, team)
user2 := th.CreateUser(Client)
LinkUserToTeam(user2, team)
user3 := th.CreateUser(Client)
LinkUserToTeam(user3, team2)
enableOutgoingHooks := utils.Cfg.ServiceSettings.EnableOutgoingWebhooks enableOutgoingHooks := utils.Cfg.ServiceSettings.EnableOutgoingWebhooks
enableAdminOnlyHooks := utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations
defer func() {
utils.Cfg.ServiceSettings.EnableOutgoingWebhooks = enableOutgoingHooks
utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations = enableAdminOnlyHooks
}()
utils.Cfg.ServiceSettings.EnableOutgoingWebhooks = true
*utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations = true
hook := &model.OutgoingWebhook{ChannelId: channel1.Id, CallbackURLs: []string{"http://nowhere.com"}}
hook = Client.Must(Client.CreateOutgoingWebhook(hook)).Data.(*model.OutgoingWebhook)
if _, err := Client.RegenOutgoingWebhookToken("junk"); err == nil {
t.Fatal("should have failed - bad id")
}
if _, err := Client.RegenOutgoingWebhookToken(""); err == nil {
t.Fatal("should have failed - empty id")
}
if result, err := Client.RegenOutgoingWebhookToken(hook.Id); err != nil {
t.Fatal(err)
} else {
if result.Data.(*model.OutgoingWebhook).Token == hook.Token {
t.Fatal("regen didn't work properly")
}
}
Client.Logout()
Client.Must(Client.LoginById(user2.Id, user2.Password))
Client.SetTeamId(team.Id)
if _, err := Client.RegenOutgoingWebhookToken(hook.Id); err == nil {
t.Fatal("should have failed - not system/team admin")
}
*utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations = false
hook = &model.OutgoingWebhook{ChannelId: channel1.Id, CallbackURLs: []string{"http://nowhere.com"}}
hook = Client.Must(Client.CreateOutgoingWebhook(hook)).Data.(*model.OutgoingWebhook)
if _, err := Client.RegenOutgoingWebhookToken(hook.Id); err != nil {
t.Fatal(err)
}
Client.Logout()
Client.Must(Client.LoginById(user3.Id, user3.Password))
Client.SetTeamId(team2.Id)
if _, err := Client.RegenOutgoingWebhookToken(hook.Id); err == nil {
t.Fatal("should have failed - wrong team")
}
utils.Cfg.ServiceSettings.EnableOutgoingWebhooks = false
if _, err := Client.RegenOutgoingWebhookToken(hook.Id); err == nil {
t.Fatal("should have errored - webhooks turned off")
}
}
func TestIncomingWebhooks(t *testing.T) {
th := Setup().InitSystemAdmin()
Client := th.SystemAdminClient
team := th.SystemAdminTeam
channel1 := th.CreateChannel(Client, team)
user2 := th.CreateUser(Client)
LinkUserToTeam(user2, team)
enableIncomingHooks := utils.Cfg.ServiceSettings.EnableIncomingWebhooks
defer func() { defer func() {
utils.Cfg.ServiceSettings.EnableIncomingWebhooks = enableIncomingHooks utils.Cfg.ServiceSettings.EnableIncomingWebhooks = enableIncomingHooks
utils.Cfg.ServiceSettings.EnableOutgoingWebhooks = enableOutgoingHooks
}() }()
utils.Cfg.ServiceSettings.EnableIncomingWebhooks = true utils.Cfg.ServiceSettings.EnableIncomingWebhooks = true
utils.Cfg.ServiceSettings.EnableOutgoingWebhooks = true
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} hook := &model.IncomingWebhook{ChannelId: channel1.Id}
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team) hook = Client.Must(Client.CreateIncomingWebhook(hook)).Data.(*model.IncomingWebhook)
user := &model.User{TeamId: team.Id, Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"} url := "/hooks/" + hook.Id
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user.Id))
c := &Context{} if _, err := Client.DoPost(url, "{\"text\":\"this is a test\"}", "application/json"); err != nil {
c.RequestId = model.NewId() t.Fatal(err)
c.IpAddress = "cmd_line" }
UpdateRoles(c, user, model.ROLE_SYSTEM_ADMIN)
Client.LoginByEmail(team.Name, user.Email, "pwd")
channel1 := &model.Channel{DisplayName: "Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} if _, err := Client.DoPost(url, fmt.Sprintf("{\"text\":\"this is a test\", \"channel\":\"%s\"}", channel1.Name), "application/json"); err != nil {
channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel) t.Fatal(err)
}
if utils.Cfg.ServiceSettings.EnableOutgoingWebhooks { if _, err := Client.DoPost(url, fmt.Sprintf("{\"text\":\"this is a test\", \"channel\":\"#%s\"}", channel1.Name), "application/json"); err != nil {
hook := &model.OutgoingWebhook{ChannelId: channel1.Id, CallbackURLs: []string{"http://nowhere.com"}} t.Fatal(err)
hook = Client.Must(Client.CreateOutgoingWebhook(hook)).Data.(*model.OutgoingWebhook) }
data := make(map[string]string) Client.Must(Client.CreateDirectChannel(user2.Id))
data["id"] = hook.Id
if result, err := Client.RegenOutgoingWebhookToken(data); err != nil { if _, err := Client.DoPost(url, fmt.Sprintf("{\"text\":\"this is a test\", \"channel\":\"@%s\"}", user2.Username), "application/json"); err != nil {
t.Fatal(err) t.Fatal(err)
} else { }
if result.Data.(*model.OutgoingWebhook).Token == hook.Token {
t.Fatal("regen didn't work properly")
}
}
} else { if _, err := Client.DoPost(url, "payload={\"text\":\"this is a test\"}", "application/x-www-form-urlencoded"); err != nil {
data := make(map[string]string) t.Fatal(err)
data["id"] = "123" }
if _, err := Client.RegenOutgoingWebhookToken(data); err == nil { attachmentPayload := `{
t.Fatal("should have errored - webhooks turned off") "text": "this is a test",
} "attachments": [
{
"fallback": "Required plain-text summary of the attachment.",
"color": "#36a64f",
"pretext": "Optional text that appears above the attachment block",
"author_name": "Bobby Tables",
"author_link": "http://flickr.com/bobby/",
"author_icon": "http://flickr.com/icons/bobby.jpg",
"title": "Slack API Documentation",
"title_link": "https://api.slack.com/",
"text": "Optional text that appears within the attachment",
"fields": [
{
"title": "Priority",
"value": "High",
"short": false
}
],
"image_url": "http://my-website.com/path/to/image.jpg",
"thumb_url": "http://example.com/path/to/thumb.png"
}
]
}`
if _, err := Client.DoPost(url, attachmentPayload, "application/json"); err != nil {
t.Fatal(err)
}
if _, err := Client.DoPost(url, "{\"text\":\"\"}", "application/json"); err == nil {
t.Fatal("should have failed - no text")
}
utils.Cfg.ServiceSettings.EnableIncomingWebhooks = false
if _, err := Client.DoPost(url, "{\"text\":\"this is a test\"}", "application/json"); err == nil {
t.Fatal("should have failed - webhooks turned off")
} }
} }

Просмотреть файл

@@ -30,9 +30,9 @@
"MaxUsersPerTeam": 50, "MaxUsersPerTeam": 50,
"EnableTeamCreation": true, "EnableTeamCreation": true,
"EnableUserCreation": true, "EnableUserCreation": true,
"EnableOpenServer": false,
"RestrictCreationToDomains": "", "RestrictCreationToDomains": "",
"RestrictTeamNames": true, "RestrictTeamNames": true,
"EnableTeamListing": false,
"EnableCustomBrand": false, "EnableCustomBrand": false,
"CustomBrandText": "" "CustomBrandText": ""
}, },
@@ -143,6 +143,7 @@
"LastNameAttribute": "", "LastNameAttribute": "",
"EmailAttribute": "", "EmailAttribute": "",
"UsernameAttribute": "", "UsernameAttribute": "",
"NicknameAttribute": "",
"IdAttribute": "", "IdAttribute": "",
"SkipCertificateVerification": false, "SkipCertificateVerification": false,
"QueryTimeout": 60, "QueryTimeout": 60,
@@ -154,4 +155,4 @@
"Directory": "./data/", "Directory": "./data/",
"EnableDaily": false "EnableDaily": false
} }
} }

Просмотреть файл

@@ -8,10 +8,10 @@ import (
) )
type LdapInterface interface { type LdapInterface interface {
DoLogin(team *model.Team, id string, password string) (*model.User, *model.AppError) DoLogin(id string, password string) (*model.User, *model.AppError)
GetUser(id string) (*model.User, *model.AppError) GetUser(id string) (*model.User, *model.AppError)
CheckPassword(id string, password string) *model.AppError CheckPassword(id string, password string) *model.AppError
SwitchToEmail(userId, ldapId, ldapPassword string) *model.AppError SwitchToLdap(userId, ldapId, ldapPassword string) *model.AppError
ValidateFilter(filter string) *model.AppError ValidateFilter(filter string) *model.AppError
} }

Просмотреть файл

@@ -8,7 +8,7 @@ import (
) )
type MfaInterface interface { type MfaInterface interface {
GenerateQrCode(team *model.Team, user *model.User) ([]byte, *model.AppError) GenerateQrCode(user *model.User) ([]byte, *model.AppError)
Activate(user *model.User, token string) *model.AppError Activate(user *model.User, token string) *model.AppError
Deactivate(userId string) *model.AppError Deactivate(userId string) *model.AppError
ValidateToken(secret, token string) (bool, *model.AppError) ValidateToken(secret, token string) (bool, *model.AppError)

Просмотреть файл

@@ -1313,11 +1313,11 @@
}, },
{ {
"id": "api.templates.singin_change_email.body.info", "id": "api.templates.singin_change_email.body.info",
"translation": "You updated your sign-in method for {{.TeamDisplayName}} on {{ .TeamURL }} to {{.Method}}.<br>If this change wasn't initiated by you, please contact your system administrator." "translation": "You updated your sign-in method for on {{ .SiteName }} to {{.Method}}.<br>If this change wasn't initiated by you, please contact your system administrator."
}, },
{ {
"id": "api.templates.singin_change_email.subject", "id": "api.templates.singin_change_email.subject",
"translation": "You updated your sign-in method for {{.TeamDisplayName}} on {{ .SiteName }}" "translation": "You updated your sign-in method on {{ .SiteName }}"
}, },
{ {
"id": "api.templates.verify_body.button", "id": "api.templates.verify_body.button",
@@ -1425,11 +1425,11 @@
}, },
{ {
"id": "api.user.create_oauth_user.already_attached.app_error", "id": "api.user.create_oauth_user.already_attached.app_error",
"translation": "Team {{.DisplayName}} already has a user with the email address attached to your {{.Service}} account" "translation": "An existing user is already attached to your {{.Service}} account"
}, },
{ {
"id": "api.user.create_oauth_user.already_used.app_error", "id": "api.user.create_oauth_user.already_used.app_error",
"translation": "This {{.Service}} account has already been used to sign up for team {{.DisplayName}}" "translation": "This {{.Service}} account has already been used to sign up"
}, },
{ {
"id": "api.user.create_oauth_user.create.app_error", "id": "api.user.create_oauth_user.create.app_error",
@@ -1451,6 +1451,10 @@
"id": "api.user.create_profile_image.initial.app_error", "id": "api.user.create_profile_image.initial.app_error",
"translation": "Could not add user initial to default profile picture" "translation": "Could not add user initial to default profile picture"
}, },
{
"id": "api.user.create_user.no_open_server",
"translation": "This server does not allow open signups. Please speak with your Administrator to receive an invitation."
},
{ {
"id": "api.user.create_user.accepted_domain.app_error", "id": "api.user.create_user.accepted_domain.app_error",
"translation": "The email you provided does not belong to an accepted domain. Please contact your administrator or sign up with a different email." "translation": "The email you provided does not belong to an accepted domain. Please contact your administrator or sign up with a different email."
@@ -1759,6 +1763,14 @@
"id": "api.webhook.create_incoming.disabled.app_errror", "id": "api.webhook.create_incoming.disabled.app_errror",
"translation": "Incoming webhooks have been disabled by the system admin." "translation": "Incoming webhooks have been disabled by the system admin."
}, },
{
"id": "api.webhook.create_outgoing.not_open.app_error",
"translation": "Outgoing webhooks can only be created for public channels."
},
{
"id": "api.webhook.create_outgoing.permissions.app_error",
"translation": "Inappropriate permissions to create outcoming webhook."
},
{ {
"id": "api.webhook.create_outgoing.disabled.app_error", "id": "api.webhook.create_outgoing.disabled.app_error",
"translation": "Outgoing webhooks have been disabled by the system admin." "translation": "Outgoing webhooks have been disabled by the system admin."
@@ -2111,6 +2123,18 @@
"id": "model.channel.is_valid.type.app_error", "id": "model.channel.is_valid.type.app_error",
"translation": "Invalid type" "translation": "Invalid type"
}, },
{
"id": "model.team_member.is_valid.team_id.app_error",
"translation": "Invalid team id"
},
{
"id": "model.team_member.is_valid.user_id.app_error",
"translation": "Invalid user id"
},
{
"id": "model.team_member.is_valid.role.app_error",
"translation": "Invalid role"
},
{ {
"id": "model.channel.is_valid.update_at.app_error", "id": "model.channel.is_valid.update_at.app_error",
"translation": "Update at must be a valid time" "translation": "Update at must be a valid time"
@@ -2943,6 +2967,22 @@
"id": "store.sql_channel.update_member.app_error", "id": "store.sql_channel.update_member.app_error",
"translation": "We encountered an error updating the channel member" "translation": "We encountered an error updating the channel member"
}, },
{
"id": "store.sql_team.save_member.exists.app_error",
"translation": "A team member with that id already exists"
},
{
"id": "store.sql_team.save_member.save.app_error",
"translation": "We couldn't save the team member"
},
{
"id": "store.sql_team.get_members.app_error",
"translation": "We couldn't get the team members"
},
{
"id": "store.sql_team.remove_member.app_error",
"translation": "We couldn't remove the team member"
},
{ {
"id": "store.sql_command.analytics_command_count.app_error", "id": "store.sql_command.analytics_command_count.app_error",
"translation": "We couldn't count the commands" "translation": "We couldn't count the commands"
@@ -3237,7 +3277,7 @@
}, },
{ {
"id": "store.sql_session.remove_all_sessions_for_team.app_error", "id": "store.sql_session.remove_all_sessions_for_team.app_error",
"translation": "We couldn't remove all the sessions for the team" "translation": "We couldn't remove all the sessions"
}, },
{ {
"id": "store.sql_session.save.app_error", "id": "store.sql_session.save.app_error",

Просмотреть файл

@@ -1311,14 +1311,6 @@
"id": "api.templates.signup_team_subject", "id": "api.templates.signup_team_subject",
"translation": "Configuración del equipo en {{ .SiteName }}" "translation": "Configuración del equipo en {{ .SiteName }}"
}, },
{
"id": "api.templates.singin_change_email.body.info",
"translation": "Haz actualizado el método con el que inicias sesión en {{.TeamURL}} para el equipo {{.TeamDisplayName}} por {{.Method}}.<br>Si este cambio no fue realizado por ti, por favor contacta a un administrador del sistema."
},
{
"id": "api.templates.singin_change_email.subject",
"translation": "Cambio del método de inicio de sesión para {{.TeamDisplayName}} en {{ .SiteName }}"
},
{ {
"id": "api.templates.verify_body.button", "id": "api.templates.verify_body.button",
"translation": "Confirmar Correo" "translation": "Confirmar Correo"
@@ -1423,14 +1415,6 @@
"id": "api.user.complete_switch_with_oauth.unavailable.app_error", "id": "api.user.complete_switch_with_oauth.unavailable.app_error",
"translation": "OAuth para {{.Service}} no está disponible en este servidor" "translation": "OAuth para {{.Service}} no está disponible en este servidor"
}, },
{
"id": "api.user.create_oauth_user.already_attached.app_error",
"translation": "El Equipo {{.DisplayName}} ya tiene un usuario con esta dirección de correo asociada a tu cuenta de {{.Service}}"
},
{
"id": "api.user.create_oauth_user.already_used.app_error",
"translation": "Esta cuenta de {{.Service}} ya fue utilizada para registrarse en el equipo {{.DisplayName}}"
},
{ {
"id": "api.user.create_oauth_user.create.app_error", "id": "api.user.create_oauth_user.create.app_error",
"translation": "No se pudo crear el usuario basandose en el objeto de {{.Service}}" "translation": "No se pudo crear el usuario basandose en el objeto de {{.Service}}"
@@ -3235,10 +3219,6 @@
"id": "store.sql_session.remove.app_error", "id": "store.sql_session.remove.app_error",
"translation": "No pudimos remover la sesión" "translation": "No pudimos remover la sesión"
}, },
{
"id": "store.sql_session.remove_all_sessions_for_team.app_error",
"translation": "No pudimos remover todas las sesiones para el equipo"
},
{ {
"id": "store.sql_session.save.app_error", "id": "store.sql_session.save.app_error",
"translation": "No pudimos guardar la sesión" "translation": "No pudimos guardar la sesión"

Просмотреть файл

@@ -1235,14 +1235,6 @@
"id": "api.templates.signup_team_subject", "id": "api.templates.signup_team_subject",
"translation": "Paramétrage Équipe {{ .SiteName }}" "translation": "Paramétrage Équipe {{ .SiteName }}"
}, },
{
"id": "api.templates.singin_change_email.body.info",
"translation": "Vous avez mis à jour la méthode de connexion de {{.TeamDisplayName}} sur {{.TeamURL}} pour {{.Method}}.<br>Si cette modification n'a pas été effectuée par vous, veuillez prendre contact avec votre administrateur système."
},
{
"id": "api.templates.singin_change_email.subject",
"translation": "Vous avez mis à jour la méthode de connexion de {{.TeamDisplayName}} sur {{ .SiteName }}"
},
{ {
"id": "api.templates.verify_body.button", "id": "api.templates.verify_body.button",
"translation": "Vérifier l'adresse électronique" "translation": "Vérifier l'adresse électronique"
@@ -1339,14 +1331,6 @@
"id": "api.user.complete_switch_with_oauth.unavailable.app_error", "id": "api.user.complete_switch_with_oauth.unavailable.app_error",
"translation": "{{.Service}} oauth non disponible sur ce serveur" "translation": "{{.Service}} oauth non disponible sur ce serveur"
}, },
{
"id": "api.user.create_oauth_user.already_attached.app_error",
"translation": "L'équipe {{.DisplayName}} dispose déjà d'un utilisateur ayant la même adresse électronique que celle attachée à votre compte {{.Service}}"
},
{
"id": "api.user.create_oauth_user.already_used.app_error",
"translation": "Ce compte {{.Service}} a déjà été utilisé pour pour se connecter à l'équipe {{.DisplayName}}"
},
{ {
"id": "api.user.create_oauth_user.create.app_error", "id": "api.user.create_oauth_user.create.app_error",
"translation": "Impossible de créer un utilisateur à partir du user object {{.Service}}" "translation": "Impossible de créer un utilisateur à partir du user object {{.Service}}"

Просмотреть файл

@@ -1311,14 +1311,6 @@
"id": "api.templates.signup_team_subject", "id": "api.templates.signup_team_subject",
"translation": "{{ .SiteName }} Configuração da Equipe" "translation": "{{ .SiteName }} Configuração da Equipe"
}, },
{
"id": "api.templates.singin_change_email.body.info",
"translation": "Você atualizou seu método de login para {{.TeamDisplayName}} no {{ .TeamURL }} para {{.Method}}.<br>Se esta mudança não foi iniciada por você, por favor entre em contato com o administrador do sistema."
},
{
"id": "api.templates.singin_change_email.subject",
"translation": "Você atualizou seu método de login para {{.TeamDisplayName}} em {{ .SiteName }}"
},
{ {
"id": "api.templates.verify_body.button", "id": "api.templates.verify_body.button",
"translation": "Verificar Email" "translation": "Verificar Email"
@@ -1423,14 +1415,6 @@
"id": "api.user.complete_switch_with_oauth.unavailable.app_error", "id": "api.user.complete_switch_with_oauth.unavailable.app_error",
"translation": "{{.Service}} oauth não disponível neste servidor" "translation": "{{.Service}} oauth não disponível neste servidor"
}, },
{
"id": "api.user.create_oauth_user.already_attached.app_error",
"translation": "Equipe {{.DisplayName}} já tem um usuário com o endereço de email anexado a sua conta {{.Service}}"
},
{
"id": "api.user.create_oauth_user.already_used.app_error",
"translation": "Está conta {{.Service}} já foi utilizada para se inscrever na equipe {{.DisplayName}}"
},
{ {
"id": "api.user.create_oauth_user.create.app_error", "id": "api.user.create_oauth_user.create.app_error",
"translation": "Não foi possível criar o usuário fora do {{.Service}} do objeto de usuário" "translation": "Não foi possível criar o usuário fora do {{.Service}} do objeto de usuário"
@@ -3235,10 +3219,6 @@
"id": "store.sql_session.remove.app_error", "id": "store.sql_session.remove.app_error",
"translation": "Não foi possível remover a sessão" "translation": "Não foi possível remover a sessão"
}, },
{
"id": "store.sql_session.remove_all_sessions_for_team.app_error",
"translation": "Não foi possível remover todas as sessões para a equipe"
},
{ {
"id": "store.sql_session.save.app_error", "id": "store.sql_session.save.app_error",
"translation": "Não foi possível salvar a sessão" "translation": "Não foi possível salvar a sessão"

Просмотреть файл

@@ -66,7 +66,7 @@ func manualTest(c *api.Context, w http.ResponseWriter, r *http.Request) {
team := &model.Team{ team := &model.Team{
DisplayName: teamDisplayName[0], DisplayName: teamDisplayName[0],
Name: utils.RandomName(utils.Range{20, 20}, utils.LOWERCASE), Name: utils.RandomName(utils.Range{20, 20}, utils.LOWERCASE),
Email: utils.RandomEmail(utils.Range{20, 20}, utils.LOWERCASE), Email: "success+" + model.NewId() + "simulator.amazonses.com",
Type: model.TEAM_OPEN, Type: model.TEAM_OPEN,
} }
@@ -88,8 +88,7 @@ func manualTest(c *api.Context, w http.ResponseWriter, r *http.Request) {
// Create user for testing // Create user for testing
user := &model.User{ user := &model.User{
TeamId: teamID, Email: "success+" + model.NewId() + "simulator.amazonses.com",
Email: utils.RandomEmail(utils.Range{20, 20}, utils.LOWERCASE),
Nickname: username[0], Nickname: username[0],
Password: api.USER_PASSWORD} Password: api.USER_PASSWORD}
@@ -98,7 +97,10 @@ func manualTest(c *api.Context, w http.ResponseWriter, r *http.Request) {
c.Err = err c.Err = err
return return
} }
api.Srv.Store.User().VerifyEmail(result.Data.(*model.User).Id)
<-api.Srv.Store.User().VerifyEmail(result.Data.(*model.User).Id)
<-api.Srv.Store.Team().SaveMember(&model.TeamMember{TeamId: teamID, UserId: result.Data.(*model.User).Id})
newuser := result.Data.(*model.User) newuser := result.Data.(*model.User)
userID = newuser.Id userID = newuser.Id

Просмотреть файл

@@ -22,6 +22,7 @@ import (
"github.com/mattermost/platform/einterfaces" "github.com/mattermost/platform/einterfaces"
"github.com/mattermost/platform/manualtesting" "github.com/mattermost/platform/manualtesting"
"github.com/mattermost/platform/model" "github.com/mattermost/platform/model"
"github.com/mattermost/platform/store"
"github.com/mattermost/platform/utils" "github.com/mattermost/platform/utils"
"github.com/mattermost/platform/web" "github.com/mattermost/platform/web"
@@ -36,13 +37,18 @@ import (
//ENTERPRISE_IMPORTS //ENTERPRISE_IMPORTS
var flagCmdUpdateDb30 bool
var flagCmdCreateTeam bool var flagCmdCreateTeam bool
var flagCmdCreateUser bool var flagCmdCreateUser bool
var flagCmdAssignRole bool var flagCmdAssignRole bool
var flagCmdVersion bool var flagCmdVersion bool
var flagCmdResetPassword bool var flagCmdResetPassword bool
var flagCmdResetMfa bool
var flagCmdPermanentDeleteUser bool var flagCmdPermanentDeleteUser bool
var flagCmdPermanentDeleteTeam bool var flagCmdPermanentDeleteTeam bool
var flagCmdPermanentDeleteAllUsers bool
var flagCmdResetDatabase bool
var flagUsername string
var flagCmdUploadLicense bool var flagCmdUploadLicense bool
var flagConfigFile string var flagConfigFile string
var flagLicenseFile string var flagLicenseFile string
@@ -69,6 +75,10 @@ func main() {
l4g.Info(utils.T("mattermost.working_dir"), pwd) l4g.Info(utils.T("mattermost.working_dir"), pwd)
l4g.Info(utils.T("mattermost.config_file"), utils.FindConfigFile(flagConfigFile)) l4g.Info(utils.T("mattermost.config_file"), utils.FindConfigFile(flagConfigFile))
// Speical case for upgrading the db to 3.0
// ADDED for 3.0 REMOVE for 3.4
cmdUpdateDb30()
api.NewServer() api.NewServer()
api.InitApi() api.InitApi()
web.InitWeb() web.InitWeb()
@@ -223,19 +233,24 @@ func parseCmds() {
} }
flag.StringVar(&flagConfigFile, "config", "config.json", "") flag.StringVar(&flagConfigFile, "config", "config.json", "")
flag.StringVar(&flagUsername, "username", "", "")
flag.StringVar(&flagLicenseFile, "license", "", "") flag.StringVar(&flagLicenseFile, "license", "", "")
flag.StringVar(&flagEmail, "email", "", "") flag.StringVar(&flagEmail, "email", "", "")
flag.StringVar(&flagPassword, "password", "", "") flag.StringVar(&flagPassword, "password", "", "")
flag.StringVar(&flagTeamName, "team_name", "", "") flag.StringVar(&flagTeamName, "team_name", "", "")
flag.StringVar(&flagRole, "role", "", "") flag.StringVar(&flagRole, "role", "", "")
flag.BoolVar(&flagCmdUpdateDb30, "upgrade_db_30", false, "")
flag.BoolVar(&flagCmdCreateTeam, "create_team", false, "") flag.BoolVar(&flagCmdCreateTeam, "create_team", false, "")
flag.BoolVar(&flagCmdCreateUser, "create_user", false, "") flag.BoolVar(&flagCmdCreateUser, "create_user", false, "")
flag.BoolVar(&flagCmdAssignRole, "assign_role", false, "") flag.BoolVar(&flagCmdAssignRole, "assign_role", false, "")
flag.BoolVar(&flagCmdVersion, "version", false, "") flag.BoolVar(&flagCmdVersion, "version", false, "")
flag.BoolVar(&flagCmdResetPassword, "reset_password", false, "") flag.BoolVar(&flagCmdResetPassword, "reset_password", false, "")
flag.BoolVar(&flagCmdResetMfa, "reset_mfa", false, "")
flag.BoolVar(&flagCmdPermanentDeleteUser, "permanent_delete_user", false, "") flag.BoolVar(&flagCmdPermanentDeleteUser, "permanent_delete_user", false, "")
flag.BoolVar(&flagCmdPermanentDeleteTeam, "permanent_delete_team", false, "") flag.BoolVar(&flagCmdPermanentDeleteTeam, "permanent_delete_team", false, "")
flag.BoolVar(&flagCmdPermanentDeleteAllUsers, "permanent_delete_all_users", false, "")
flag.BoolVar(&flagCmdResetDatabase, "reset_database", false, "")
flag.BoolVar(&flagCmdUploadLicense, "upload_license", false, "") flag.BoolVar(&flagCmdUploadLicense, "upload_license", false, "")
flag.Parse() flag.Parse()
@@ -244,9 +259,12 @@ func parseCmds() {
flagCmdCreateUser || flagCmdCreateUser ||
flagCmdAssignRole || flagCmdAssignRole ||
flagCmdResetPassword || flagCmdResetPassword ||
flagCmdResetMfa ||
flagCmdVersion || flagCmdVersion ||
flagCmdPermanentDeleteUser || flagCmdPermanentDeleteUser ||
flagCmdPermanentDeleteTeam || flagCmdPermanentDeleteTeam ||
flagCmdPermanentDeleteAllUsers ||
flagCmdResetDatabase ||
flagCmdUploadLicense) flagCmdUploadLicense)
} }
@@ -256,11 +274,258 @@ func runCmds() {
cmdCreateUser() cmdCreateUser()
cmdAssignRole() cmdAssignRole()
cmdResetPassword() cmdResetPassword()
cmdResetMfa()
cmdPermDeleteUser() cmdPermDeleteUser()
cmdPermDeleteTeam() cmdPermDeleteTeam()
cmdPermDeleteAllUsers()
cmdResetDatabase()
cmdUploadLicense() cmdUploadLicense()
} }
type TeamForUpgrade struct {
Id string
Name string
}
// ADDED for 3.0 REMOVE for 3.4
func cmdUpdateDb30() {
if flagCmdUpdateDb30 {
api.Srv = &api.Server{}
api.Srv.Store = store.NewSqlStoreForUpgrade30()
store := api.Srv.Store.(*store.SqlStore)
l4g.Info("Attempting to run speical upgrade of the database schema to version 3.0 for user model changes")
time.Sleep(time.Second)
if !store.DoesColumnExist("Users", "TeamId") {
fmt.Println("**WARNING** the database schema appears to be upgraded to 3.0")
flushLogAndExit(1)
}
if !(store.SchemaVersion == "2.2.0" ||
store.SchemaVersion == "2.1.0" ||
store.SchemaVersion == "2.0.0") {
fmt.Println("**WARNING** the database schema needs to be version 2.2.0, 2.1.0 or 2.0.0 to upgrade")
flushLogAndExit(1)
}
var confirmBackup string
fmt.Println("\nPlease see http://www.mattermost.org/upgrade-to-3-0/")
fmt.Println("**WARNING** This upgrade process will be irreversible.")
fmt.Print("Have you performed a database backup? (YES/NO): ")
fmt.Scanln(&confirmBackup)
if confirmBackup != "YES" {
fmt.Fprintln(os.Stderr, "ABORTED: You did not answer YES exactly, in all capitals.")
flushLogAndExit(1)
}
var flagTeamName string
var teams []*TeamForUpgrade
if _, err := store.GetMaster().Select(&teams, "SELECT Id, Name FROM Teams"); err != nil {
l4g.Error("Failed to load all teams details=%v", err)
flushLogAndExit(1)
}
fmt.Println(fmt.Sprintf("We found %v teams.", len(teams)))
for _, team := range teams {
fmt.Println(team.Name)
}
fmt.Print("Please pick a primary team from the list above: ")
fmt.Scanln(&flagTeamName)
var team *TeamForUpgrade
for _, t := range teams {
if t.Name == flagTeamName {
team = t
break
}
}
if team == nil {
l4g.Error("Failed to find primary team details")
flushLogAndExit(1)
}
l4g.Info("Starting speical 3.0 database upgrade with performed_backup=YES team_name=%v", team.Name)
l4g.Info("Primary team %v will be left unchanged", team.Name)
l4g.Info("Upgrading primary team %v", team.Name)
uniqueEmails := make(map[string]bool)
uniqueUsernames := make(map[string]bool)
primaryUsers := convertTeamTo30(team, uniqueEmails, uniqueUsernames)
l4g.Info("Upgraded %v users", len(primaryUsers))
for _, otherTeam := range teams {
if otherTeam.Id != team.Id {
l4g.Info("Upgrading team %v", otherTeam.Name)
users := convertTeamTo30(otherTeam, uniqueEmails, uniqueUsernames)
l4g.Info("Upgraded %v users", len(users))
}
}
l4g.Info("Altering other scheme changes needed 3.0 for user model changes")
if _, err := store.GetMaster().Exec(`
UPDATE Channels
SET
TeamId = ''
WHERE
Type = 'D'
`,
); err != nil {
l4g.Error("Failed to update direct channel types details=%v", err)
flushLogAndExit(1)
}
extraLength := store.GetMaxLengthOfColumnIfExists("Audits", "ExtraInfo")
if len(extraLength) > 0 && extraLength != "1024" {
store.AlterColumnTypeIfExists("Audits", "ExtraInfo", "VARCHAR(1024)", "VARCHAR(1024)")
}
actionLength := store.GetMaxLengthOfColumnIfExists("Audits", "Action")
if len(actionLength) > 0 && actionLength != "512" {
store.AlterColumnTypeIfExists("Audits", "Action", "VARCHAR(512)", "VARCHAR(512)")
}
if store.DoesColumnExist("Sessions", "TeamId") {
store.RemoveColumnIfExists("Sessions", "TeamId")
store.GetMaster().Exec(`TRUNCATE Sessions`)
}
// ADDED for 2.2 REMOVE for 2.6
store.CreateColumnIfNotExists("Users", "MfaActive", "tinyint(1)", "boolean", "0")
store.CreateColumnIfNotExists("Users", "MfaSecret", "varchar(128)", "character varying(128)", "")
// ADDED for 2.2 REMOVE for 2.6
if store.DoesColumnExist("Users", "TeamId") {
store.RemoveIndexIfExists("idx_users_team_id", "Users")
store.CreateUniqueIndexIfNotExists("idx_users_email_unique", "Users", "Email")
store.CreateUniqueIndexIfNotExists("idx_users_username_unique", "Users", "Username")
store.RemoveColumnIfExists("Teams", "AllowTeamListing")
store.RemoveColumnIfExists("Users", "TeamId")
}
l4g.Info("Finished running speical upgrade of the database schema to version 3.0 for user model changes")
if result := <-store.System().Update(&model.System{Name: "Version", Value: model.CurrentVersion}); result.Err != nil {
l4g.Error("Failed to update system schema version details=%v", result.Err)
flushLogAndExit(1)
}
l4g.Info(utils.T("store.sql.upgraded.warn"), model.CurrentVersion)
fmt.Println("**SUCCESS** with upgrade")
flushLogAndExit(0)
}
}
type UserForUpgrade struct {
Id string
Username string
Email string
Roles string
TeamId string
}
func convertTeamTo30(team *TeamForUpgrade, uniqueEmails map[string]bool, uniqueUsernames map[string]bool) []*UserForUpgrade {
store := api.Srv.Store.(*store.SqlStore)
var users []*UserForUpgrade
if _, err := store.GetMaster().Select(&users, "SELECT Users.Id, Users.Username, Users.Email, Users.Roles, Users.TeamId FROM Users WHERE Users.TeamId = :TeamId", map[string]interface{}{"TeamId": team.Id}); err != nil {
l4g.Error("Failed to load profiles for team details=%v", err)
flushLogAndExit(1)
}
var members []*model.TeamMember
if result := <-api.Srv.Store.Team().GetMembers(team.Id); result.Err != nil {
l4g.Error("Failed to load team membership details=%v", result.Err)
flushLogAndExit(1)
} else {
members = result.Data.([]*model.TeamMember)
}
for _, user := range users {
shouldUpdateUser := false
previousRole := user.Roles
previousEmail := user.Email
previousUsername := user.Username
member := &model.TeamMember{
TeamId: team.Id,
UserId: user.Id,
}
if model.IsInRole(user.Roles, model.ROLE_TEAM_ADMIN) {
member.Roles = model.ROLE_TEAM_ADMIN
user.Roles = ""
shouldUpdateUser = true
}
exists := false
for _, member := range members {
if member.UserId == user.Id {
exists = true
break
}
}
if !exists {
if result := <-api.Srv.Store.Team().SaveMember(member); result.Err != nil {
l4g.Error("Failed to save membership for %v details=%v", user.Email, result.Err)
flushLogAndExit(1)
}
}
if uniqueEmails[user.Email] {
shouldUpdateUser = true
emailParts := strings.Split(user.Email, "@")
if len(emailParts) == 2 {
user.Email = emailParts[0] + "+" + team.Name + "@" + emailParts[1]
} else {
user.Email = user.Email + "." + team.Name
}
}
if uniqueUsernames[user.Username] {
shouldUpdateUser = true
user.Username = user.Username + "." + team.Name
}
if shouldUpdateUser {
if _, err := store.GetMaster().Exec(`
UPDATE Users
SET
Email = :Email,
Username = :Username,
Roles = :Roles
WHERE
Id = :Id
`,
map[string]interface{}{
"Email": user.Email,
"Username": user.Username,
"Roles": user.Roles,
"Id": user.Id,
},
); err != nil {
l4g.Error("Failed to update user %v details=%v", user.Email, err)
flushLogAndExit(1)
}
l4g.Info("modified user_id=%v, changed email from=%v to=%v, changed username from=%v to %v changed roles from=%v to=%v", user.Id, previousEmail, user.Email, previousUsername, user.Username, previousRole, user.Roles)
}
uniqueEmails[user.Email] = true
uniqueUsernames[user.Username] = true
}
return users
}
func cmdCreateTeam() { func cmdCreateTeam() {
if flagCmdCreateTeam { if flagCmdCreateTeam {
if len(flagTeamName) == 0 { if len(flagTeamName) == 0 {
@@ -327,10 +592,9 @@ func cmdCreateUser() {
flushLogAndExit(1) flushLogAndExit(1)
} else { } else {
team = result.Data.(*model.Team) team = result.Data.(*model.Team)
user.TeamId = team.Id
} }
_, err := api.CreateUser(team, user) ruser, err := api.CreateUser(user)
if err != nil { if err != nil {
if err.Id != "store.sql_user.save.email_exists.app_error" { if err.Id != "store.sql_user.save.email_exists.app_error" {
l4g.Error("%v", err) l4g.Error("%v", err)
@@ -338,6 +602,12 @@ func cmdCreateUser() {
} }
} }
err = api.JoinUserToTeam(team, ruser)
if err != nil {
l4g.Error("%v", err)
flushLogAndExit(1)
}
os.Exit(0) os.Exit(0)
} }
} }
@@ -368,7 +638,7 @@ func cmdAssignRole() {
os.Exit(1) os.Exit(1)
} }
if !model.IsValidRoles(flagRole) { if !model.IsValidUserRoles(flagRole) {
fmt.Fprintln(os.Stderr, "flag invalid argument: -role") fmt.Fprintln(os.Stderr, "flag invalid argument: -role")
flag.Usage() flag.Usage()
os.Exit(1) os.Exit(1)
@@ -376,16 +646,8 @@ func cmdAssignRole() {
c := getMockContext() c := getMockContext()
var team *model.Team
if result := <-api.Srv.Store.Team().GetByName(flagTeamName); result.Err != nil {
l4g.Error("%v", result.Err)
flushLogAndExit(1)
} else {
team = result.Data.(*model.Team)
}
var user *model.User var user *model.User
if result := <-api.Srv.Store.User().GetByEmail(team.Id, flagEmail); result.Err != nil { if result := <-api.Srv.Store.User().GetByEmail(flagEmail); result.Err != nil {
l4g.Error("%v", result.Err) l4g.Error("%v", result.Err)
flushLogAndExit(1) flushLogAndExit(1)
} else { } else {
@@ -426,16 +688,8 @@ func cmdResetPassword() {
os.Exit(1) os.Exit(1)
} }
var team *model.Team
if result := <-api.Srv.Store.Team().GetByName(flagTeamName); result.Err != nil {
l4g.Error("%v", result.Err)
flushLogAndExit(1)
} else {
team = result.Data.(*model.Team)
}
var user *model.User var user *model.User
if result := <-api.Srv.Store.User().GetByEmail(team.Id, flagEmail); result.Err != nil { if result := <-api.Srv.Store.User().GetByEmail(flagEmail); result.Err != nil {
l4g.Error("%v", result.Err) l4g.Error("%v", result.Err)
flushLogAndExit(1) flushLogAndExit(1)
} else { } else {
@@ -451,14 +705,42 @@ func cmdResetPassword() {
} }
} }
func cmdPermDeleteUser() { func cmdResetMfa() {
if flagCmdPermanentDeleteUser { if flagCmdResetMfa {
if len(flagTeamName) == 0 { if len(flagEmail) == 0 && len(flagUsername) == 0 {
fmt.Fprintln(os.Stderr, "flag needs an argument: -team_name") fmt.Fprintln(os.Stderr, "flag needs an argument: -email OR -username")
flag.Usage() flag.Usage()
os.Exit(1) os.Exit(1)
} }
var user *model.User
if len(flagEmail) > 0 {
if result := <-api.Srv.Store.User().GetByEmail(flagEmail); result.Err != nil {
l4g.Error("%v", result.Err)
flushLogAndExit(1)
} else {
user = result.Data.(*model.User)
}
} else {
if result := <-api.Srv.Store.User().GetByUsername(flagUsername); result.Err != nil {
l4g.Error("%v", result.Err)
flushLogAndExit(1)
} else {
user = result.Data.(*model.User)
}
}
if err := api.DeactivateMfa(user.Id); err != nil {
l4g.Error("%v", err)
flushLogAndExit(1)
}
os.Exit(0)
}
}
func cmdPermDeleteUser() {
if flagCmdPermanentDeleteUser {
if len(flagEmail) == 0 { if len(flagEmail) == 0 {
fmt.Fprintln(os.Stderr, "flag needs an argument: -email") fmt.Fprintln(os.Stderr, "flag needs an argument: -email")
flag.Usage() flag.Usage()
@@ -467,16 +749,8 @@ func cmdPermDeleteUser() {
c := getMockContext() c := getMockContext()
var team *model.Team
if result := <-api.Srv.Store.Team().GetByName(flagTeamName); result.Err != nil {
l4g.Error("%v", result.Err)
flushLogAndExit(1)
} else {
team = result.Data.(*model.Team)
}
var user *model.User var user *model.User
if result := <-api.Srv.Store.User().GetByEmail(team.Id, flagEmail); result.Err != nil { if result := <-api.Srv.Store.User().GetByEmail(flagEmail); result.Err != nil {
l4g.Error("%v", result.Err) l4g.Error("%v", result.Err)
flushLogAndExit(1) flushLogAndExit(1)
} else { } else {
@@ -487,6 +761,7 @@ func cmdPermDeleteUser() {
fmt.Print("Have you performed a database backup? (YES/NO): ") fmt.Print("Have you performed a database backup? (YES/NO): ")
fmt.Scanln(&confirmBackup) fmt.Scanln(&confirmBackup)
if confirmBackup != "YES" { if confirmBackup != "YES" {
fmt.Print("ABORTED: You did not answer YES exactly, in all capitals.")
flushLogAndExit(1) flushLogAndExit(1)
} }
@@ -494,6 +769,7 @@ func cmdPermDeleteUser() {
fmt.Printf("Are you sure you want to delete the user %v? All data will be permanently deleted? (YES/NO): ", user.Email) fmt.Printf("Are you sure you want to delete the user %v? All data will be permanently deleted? (YES/NO): ", user.Email)
fmt.Scanln(&confirm) fmt.Scanln(&confirm)
if confirm != "YES" { if confirm != "YES" {
fmt.Print("ABORTED: You did not answer YES exactly, in all capitals.")
flushLogAndExit(1) flushLogAndExit(1)
} }
@@ -501,6 +777,7 @@ func cmdPermDeleteUser() {
l4g.Error("%v", err) l4g.Error("%v", err)
flushLogAndExit(1) flushLogAndExit(1)
} else { } else {
fmt.Print("SUCCESS: User deleted.")
flushLogAndExit(0) flushLogAndExit(0)
} }
} }
@@ -528,6 +805,7 @@ func cmdPermDeleteTeam() {
fmt.Print("Have you performed a database backup? (YES/NO): ") fmt.Print("Have you performed a database backup? (YES/NO): ")
fmt.Scanln(&confirmBackup) fmt.Scanln(&confirmBackup)
if confirmBackup != "YES" { if confirmBackup != "YES" {
fmt.Print("ABORTED: You did not answer YES exactly, in all capitals.")
flushLogAndExit(1) flushLogAndExit(1)
} }
@@ -535,6 +813,7 @@ func cmdPermDeleteTeam() {
fmt.Printf("Are you sure you want to delete the team %v? All data will be permanently deleted? (YES/NO): ", team.Name) fmt.Printf("Are you sure you want to delete the team %v? All data will be permanently deleted? (YES/NO): ", team.Name)
fmt.Scanln(&confirm) fmt.Scanln(&confirm)
if confirm != "YES" { if confirm != "YES" {
fmt.Print("ABORTED: You did not answer YES exactly, in all capitals.")
flushLogAndExit(1) flushLogAndExit(1)
} }
@@ -542,11 +821,67 @@ func cmdPermDeleteTeam() {
l4g.Error("%v", err) l4g.Error("%v", err)
flushLogAndExit(1) flushLogAndExit(1)
} else { } else {
fmt.Print("SUCCESS: Team deleted.")
flushLogAndExit(0) flushLogAndExit(0)
} }
} }
} }
func cmdPermDeleteAllUsers() {
if flagCmdPermanentDeleteAllUsers {
c := getMockContext()
var confirmBackup string
fmt.Print("Have you performed a database backup? (YES/NO): ")
fmt.Scanln(&confirmBackup)
if confirmBackup != "YES" {
fmt.Print("ABORTED: You did not answer YES exactly, in all capitals.")
flushLogAndExit(1)
}
var confirm string
fmt.Printf("Are you sure you want to delete all the users? All data will be permanently deleted? (YES/NO): ")
fmt.Scanln(&confirm)
if confirm != "YES" {
fmt.Print("ABORTED: You did not answer YES exactly, in all capitals.")
flushLogAndExit(1)
}
if err := api.PermanentDeleteAllUsers(c); err != nil {
l4g.Error("%v", err)
flushLogAndExit(1)
} else {
fmt.Print("SUCCESS: All users deleted.")
flushLogAndExit(0)
}
}
}
func cmdResetDatabase() {
if flagCmdResetDatabase {
var confirmBackup string
fmt.Print("Have you performed a database backup? (YES/NO): ")
fmt.Scanln(&confirmBackup)
if confirmBackup != "YES" {
fmt.Print("ABORTED: You did not answer YES exactly, in all capitals.")
flushLogAndExit(1)
}
var confirm string
fmt.Printf("Are you sure you want to delete everything? ALL data will be permanently deleted? (YES/NO): ")
fmt.Scanln(&confirm)
if confirm != "YES" {
fmt.Print("ABORTED: You did not answer YES exactly, in all capitals.")
flushLogAndExit(1)
}
api.Srv.Store.DropAllTables()
fmt.Print("SUCCESS: Database reset.")
flushLogAndExit(0)
}
}
func cmdUploadLicense() { func cmdUploadLicense() {
if flagCmdUploadLicense { if flagCmdUploadLicense {
if model.BuildEnterpriseReady != "true" { if model.BuildEnterpriseReady != "true" {
@@ -574,7 +909,7 @@ func cmdUploadLicense() {
flushLogAndExit(0) flushLogAndExit(0)
} }
os.Exit(0) flushLogAndExit(0)
} }
} }
@@ -604,6 +939,8 @@ USAGE:
FLAGS: FLAGS:
-config="config.json" Path to the config file -config="config.json" Path to the config file
-username="someuser" Username used in other commands
-license="ex.mattermost-license" Path to your license file -license="ex.mattermost-license" Path to your license file
-email="user@example.com" Email address used in other commands -email="user@example.com" Email address used in other commands
@@ -644,14 +981,33 @@ COMMANDS:
Example: Example:
platform -reset_password -team_name="name" -email="user@example.com" -password="newpassword" platform -reset_password -team_name="name" -email="user@example.com" -password="newpassword"
-reset_mfa Turns off multi-factor authentication for a user. It requires the
-email or -username flag.
Example:
platform -reset_mfa -username="someuser"
-reset_database Completely erases the database causing the loss of all data. This
will reset Mattermost to it's initial state. (note this will not
erase your configuration.)
Example:
platform -reset_mfa -username="someuser"
-permanent_delete_user Permanently deletes a user and all related information -permanent_delete_user Permanently deletes a user and all related information
including posts from the database. It requires the
-email flag. You may need to restart the
server to invalidate the cache
Example:
platform -permanent_delete_user -email="user@example.com"
-permanent_delete_all_users Permanently deletes all users and all related information
including posts from the database. It requires the including posts from the database. It requires the
-team_name, and -email flag. You may need to restart the -team_name, and -email flag. You may need to restart the
server to invalidate the cache server to invalidate the cache
Example: Example:
platform -permanent_delete_user -team_name="name" -email="user@example.com" platform -permanent_delete_all_users -team_name="name" -email="user@example.com"
-permanent_delete_team Permanently deletes a team and all users along with -permanent_delete_team Permanently deletes a team allong with
all related information including posts from the database. all related information including posts from the database.
It requires the -team_name flag. You may need to restart It requires the -team_name flag. You may need to restart
the server to invalidate the cache. the server to invalidate the cache.

Просмотреть файл

@@ -28,7 +28,10 @@ const (
HEADER_AUTH = "Authorization" HEADER_AUTH = "Authorization"
HEADER_REQUESTED_WITH = "X-Requested-With" HEADER_REQUESTED_WITH = "X-Requested-With"
HEADER_REQUESTED_WITH_XML = "XMLHttpRequest" HEADER_REQUESTED_WITH_XML = "XMLHttpRequest"
API_URL_SUFFIX = "/api/v1"
API_URL_SUFFIX_V1 = "/api/v1"
API_URL_SUFFIX_V3 = "/api/v3"
API_URL_SUFFIX = API_URL_SUFFIX_V3
) )
type Result struct { type Result struct {
@@ -39,16 +42,52 @@ type Result struct {
type Client struct { type Client struct {
Url string // The location of the server like "http://localhost:8065" Url string // The location of the server like "http://localhost:8065"
ApiUrl string // The api location of the server like "http://localhost:8065/api/v1" ApiUrl string // The api location of the server like "http://localhost:8065/api/v3"
HttpClient *http.Client // The http client HttpClient *http.Client // The http client
AuthToken string AuthToken string
AuthType string AuthType string
TeamId string
} }
// NewClient constructs a new client with convienence methods for talking to // NewClient constructs a new client with convienence methods for talking to
// the server. // the server.
func NewClient(url string) *Client { func NewClient(url string) *Client {
return &Client{url, url + API_URL_SUFFIX, &http.Client{}, "", ""} return &Client{url, url + API_URL_SUFFIX, &http.Client{}, "", "", ""}
}
func (c *Client) SetOAuthToken(token string) {
c.AuthToken = token
c.AuthType = HEADER_TOKEN
}
func (c *Client) ClearOAuthToken() {
c.AuthToken = ""
c.AuthType = HEADER_BEARER
}
func (c *Client) SetTeamId(teamId string) {
c.TeamId = teamId
}
func (c *Client) GetTeamId() string {
if len(c.TeamId) == 0 {
println(`You are trying to use a route that requires a team_id,
but you have not called SetTeamId() in client.go`)
}
return c.TeamId
}
func (c *Client) ClearTeamId() {
c.TeamId = ""
}
func (c *Client) GetTeamRoute() string {
return fmt.Sprintf("/teams/%v", c.GetTeamId())
}
func (c *Client) GetChannelRoute(channelId string) string {
return fmt.Sprintf("/teams/%v/channels/%v", c.GetTeamId(), channelId)
} }
func (c *Client) DoPost(url, data, contentType string) (*http.Response, *AppError) { func (c *Client) DoPost(url, data, contentType string) (*http.Response, *AppError) {
@@ -162,10 +201,19 @@ func (c *Client) GetAllTeams() (*Result, *AppError) {
} }
} }
func (c *Client) FindTeamByName(name string, allServers bool) (*Result, *AppError) { func (c *Client) GetAllTeamListings() (*Result, *AppError) {
if r, err := c.DoApiGet("/teams/all_team_listings", "", ""); err != nil {
return nil, err
} else {
return &Result{r.Header.Get(HEADER_REQUEST_ID),
r.Header.Get(HEADER_ETAG_SERVER), TeamMapFromJson(r.Body)}, nil
}
}
func (c *Client) FindTeamByName(name string) (*Result, *AppError) {
m := make(map[string]string) m := make(map[string]string)
m["name"] = name m["name"] = name
m["all"] = fmt.Sprintf("%v", allServers)
if r, err := c.DoApiPost("/teams/find_team_by_name", MapToJson(m)); err != nil { if r, err := c.DoApiPost("/teams/find_team_by_name", MapToJson(m)); err != nil {
return nil, err return nil, err
} else { } else {
@@ -179,8 +227,32 @@ func (c *Client) FindTeamByName(name string, allServers bool) (*Result, *AppErro
} }
} }
func (c *Client) AddUserToTeam(userId string) (*Result, *AppError) {
data := make(map[string]string)
data["user_id"] = userId
if r, err := c.DoApiPost(c.GetTeamRoute()+"/add_user_to_team", MapToJson(data)); err != nil {
return nil, err
} else {
return &Result{r.Header.Get(HEADER_REQUEST_ID),
r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil
}
}
func (c *Client) AddUserToTeamFromInvite(hash, dataToHash, inviteId string) (*Result, *AppError) {
data := make(map[string]string)
data["hash"] = hash
data["data"] = dataToHash
data["invite_id"] = inviteId
if r, err := c.DoApiPost("/teams/add_user_to_team_from_invite", MapToJson(data)); err != nil {
return nil, err
} else {
return &Result{r.Header.Get(HEADER_REQUEST_ID),
r.Header.Get(HEADER_ETAG_SERVER), TeamFromJson(r.Body)}, nil
}
}
func (c *Client) InviteMembers(invites *Invites) (*Result, *AppError) { func (c *Client) InviteMembers(invites *Invites) (*Result, *AppError) {
if r, err := c.DoApiPost("/teams/invite_members", invites.ToJson()); err != nil { if r, err := c.DoApiPost(c.GetTeamRoute()+"/invite_members", invites.ToJson()); err != nil {
return nil, err return nil, err
} else { } else {
return &Result{r.Header.Get(HEADER_REQUEST_ID), return &Result{r.Header.Get(HEADER_REQUEST_ID),
@@ -189,7 +261,7 @@ func (c *Client) InviteMembers(invites *Invites) (*Result, *AppError) {
} }
func (c *Client) UpdateTeam(team *Team) (*Result, *AppError) { func (c *Client) UpdateTeam(team *Team) (*Result, *AppError) {
if r, err := c.DoApiPost("/teams/update", team.ToJson()); err != nil { if r, err := c.DoApiPost(c.GetTeamRoute()+"/update", team.ToJson()); err != nil {
return nil, err return nil, err
} else { } else {
return &Result{r.Header.Get(HEADER_REQUEST_ID), return &Result{r.Header.Get(HEADER_REQUEST_ID),
@@ -206,6 +278,18 @@ func (c *Client) CreateUser(user *User, hash string) (*Result, *AppError) {
} }
} }
func (c *Client) CreateUserWithInvite(user *User, hash string, data string, inviteId string) (*Result, *AppError) {
url := "/users/create?d=" + url.QueryEscape(data) + "&h=" + url.QueryEscape(hash) + "&iid=" + url.QueryEscape(inviteId)
if r, err := c.DoApiPost(url, user.ToJson()); err != nil {
return nil, err
} else {
return &Result{r.Header.Get(HEADER_REQUEST_ID),
r.Header.Get(HEADER_ETAG_SERVER), UserFromJson(r.Body)}, nil
}
}
func (c *Client) CreateUserFromSignup(user *User, data string, hash string) (*Result, *AppError) { func (c *Client) CreateUserFromSignup(user *User, data string, hash string) (*Result, *AppError) {
if r, err := c.DoApiPost("/users/create?d="+url.QueryEscape(data)+"&h="+hash, user.ToJson()); err != nil { if r, err := c.DoApiPost("/users/create?d="+url.QueryEscape(data)+"&h="+hash, user.ToJson()); err != nil {
return nil, err return nil, err
@@ -216,7 +300,7 @@ func (c *Client) CreateUserFromSignup(user *User, data string, hash string) (*Re
} }
func (c *Client) GetUser(id string, etag string) (*Result, *AppError) { func (c *Client) GetUser(id string, etag string) (*Result, *AppError) {
if r, err := c.DoApiGet("/users/"+id, "", etag); err != nil { if r, err := c.DoApiGet("/users/"+id+"/get", "", etag); err != nil {
return nil, err return nil, err
} else { } else {
return &Result{r.Header.Get(HEADER_REQUEST_ID), return &Result{r.Header.Get(HEADER_REQUEST_ID),
@@ -242,6 +326,24 @@ func (c *Client) GetProfiles(teamId string, etag string) (*Result, *AppError) {
} }
} }
func (c *Client) GetProfilesForTeam(teamId string, etag string) (*Result, *AppError) {
if r, err := c.DoApiGet("/users/profiles/"+teamId+"?skip_direct=true", "", etag); err != nil {
return nil, err
} else {
return &Result{r.Header.Get(HEADER_REQUEST_ID),
r.Header.Get(HEADER_ETAG_SERVER), UserMapFromJson(r.Body)}, nil
}
}
func (c *Client) GetDirectProfiles(etag string) (*Result, *AppError) {
if r, err := c.DoApiGet("/users/direct_profiles", "", etag); err != nil {
return nil, err
} else {
return &Result{r.Header.Get(HEADER_REQUEST_ID),
r.Header.Get(HEADER_ETAG_SERVER), UserMapFromJson(r.Body)}, nil
}
}
func (c *Client) LoginById(id string, password string) (*Result, *AppError) { func (c *Client) LoginById(id string, password string) (*Result, *AppError) {
m := make(map[string]string) m := make(map[string]string)
m["id"] = id m["id"] = id
@@ -274,6 +376,26 @@ func (c *Client) LoginByEmailWithDevice(name string, email string, password stri
return c.login(m) return c.login(m)
} }
func (c *Client) LoginByLdap(userid string, password string, mfatoken string) (*Result, *AppError) {
m := make(map[string]string)
m["id"] = userid
m["password"] = password
m["token"] = mfatoken
if r, err := c.DoApiPost("/users/login_ldap", MapToJson(m)); err != nil {
return nil, err
} else {
c.AuthToken = r.Header.Get(HEADER_TOKEN)
c.AuthType = HEADER_BEARER
sessionToken := getCookie(SESSION_COOKIE_TOKEN, r)
if c.AuthToken != sessionToken.Value {
NewLocAppError("/users/login_ldap", "model.client.login.app_error", nil, "")
}
return &Result{r.Header.Get(HEADER_REQUEST_ID),
r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil
}
}
func (c *Client) login(m map[string]string) (*Result, *AppError) { func (c *Client) login(m map[string]string) (*Result, *AppError) {
if r, err := c.DoApiPost("/users/login", MapToJson(m)); err != nil { if r, err := c.DoApiPost("/users/login", MapToJson(m)); err != nil {
return nil, err return nil, err
@@ -297,16 +419,16 @@ func (c *Client) Logout() (*Result, *AppError) {
} else { } else {
c.AuthToken = "" c.AuthToken = ""
c.AuthType = HEADER_BEARER c.AuthType = HEADER_BEARER
c.TeamId = ""
return &Result{r.Header.Get(HEADER_REQUEST_ID), return &Result{r.Header.Get(HEADER_REQUEST_ID),
r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil
} }
} }
func (c *Client) CheckMfa(method, teamName, loginId string) (*Result, *AppError) { func (c *Client) CheckMfa(method, loginId string) (*Result, *AppError) {
m := make(map[string]string) m := make(map[string]string)
m["method"] = method m["method"] = method
m["team_name"] = teamName
m["login_id"] = loginId m["login_id"] = loginId
if r, err := c.DoApiPost("/users/mfa", MapToJson(m)); err != nil { if r, err := c.DoApiPost("/users/mfa", MapToJson(m)); err != nil {
@@ -339,14 +461,16 @@ func (c *Client) UpdateMfa(activate bool, token string) (*Result, *AppError) {
} }
} }
func (c *Client) SetOAuthToken(token string) { func (c *Client) AdminResetMfa(userId string) (*Result, *AppError) {
c.AuthToken = token m := make(map[string]string)
c.AuthType = HEADER_TOKEN m["user_id"] = userId
}
func (c *Client) ClearOAuthToken() { if r, err := c.DoApiPost("/admin/reset_mfa", MapToJson(m)); err != nil {
c.AuthToken = "" return nil, err
c.AuthType = HEADER_BEARER } else {
return &Result{r.Header.Get(HEADER_REQUEST_ID),
r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil
}
} }
func (c *Client) RevokeSession(sessionAltId string) (*Result, *AppError) { func (c *Client) RevokeSession(sessionAltId string) (*Result, *AppError) {
@@ -411,7 +535,7 @@ func (c *Client) Command(channelId string, command string, suggest bool) (*Resul
m["command"] = command m["command"] = command
m["channelId"] = channelId m["channelId"] = channelId
m["suggest"] = strconv.FormatBool(suggest) m["suggest"] = strconv.FormatBool(suggest)
if r, err := c.DoApiPost("/commands/execute", MapToJson(m)); err != nil { if r, err := c.DoApiPost(c.GetTeamRoute()+"/commands/execute", MapToJson(m)); err != nil {
return nil, err return nil, err
} else { } else {
return &Result{r.Header.Get(HEADER_REQUEST_ID), return &Result{r.Header.Get(HEADER_REQUEST_ID),
@@ -420,7 +544,7 @@ func (c *Client) Command(channelId string, command string, suggest bool) (*Resul
} }
func (c *Client) ListCommands() (*Result, *AppError) { func (c *Client) ListCommands() (*Result, *AppError) {
if r, err := c.DoApiGet("/commands/list", "", ""); err != nil { if r, err := c.DoApiGet(c.GetTeamRoute()+"/commands/list", "", ""); err != nil {
return nil, err return nil, err
} else { } else {
return &Result{r.Header.Get(HEADER_REQUEST_ID), return &Result{r.Header.Get(HEADER_REQUEST_ID),
@@ -429,7 +553,7 @@ func (c *Client) ListCommands() (*Result, *AppError) {
} }
func (c *Client) ListTeamCommands() (*Result, *AppError) { func (c *Client) ListTeamCommands() (*Result, *AppError) {
if r, err := c.DoApiGet("/commands/list_team_commands", "", ""); err != nil { if r, err := c.DoApiGet(c.GetTeamRoute()+"/commands/list_team_commands", "", ""); err != nil {
return nil, err return nil, err
} else { } else {
return &Result{r.Header.Get(HEADER_REQUEST_ID), return &Result{r.Header.Get(HEADER_REQUEST_ID),
@@ -438,7 +562,7 @@ func (c *Client) ListTeamCommands() (*Result, *AppError) {
} }
func (c *Client) CreateCommand(cmd *Command) (*Result, *AppError) { func (c *Client) CreateCommand(cmd *Command) (*Result, *AppError) {
if r, err := c.DoApiPost("/commands/create", cmd.ToJson()); err != nil { if r, err := c.DoApiPost(c.GetTeamRoute()+"/commands/create", cmd.ToJson()); err != nil {
return nil, err return nil, err
} else { } else {
return &Result{r.Header.Get(HEADER_REQUEST_ID), return &Result{r.Header.Get(HEADER_REQUEST_ID),
@@ -447,7 +571,7 @@ func (c *Client) CreateCommand(cmd *Command) (*Result, *AppError) {
} }
func (c *Client) RegenCommandToken(data map[string]string) (*Result, *AppError) { func (c *Client) RegenCommandToken(data map[string]string) (*Result, *AppError) {
if r, err := c.DoApiPost("/commands/regen_token", MapToJson(data)); err != nil { if r, err := c.DoApiPost(c.GetTeamRoute()+"/commands/regen_token", MapToJson(data)); err != nil {
return nil, err return nil, err
} else { } else {
return &Result{r.Header.Get(HEADER_REQUEST_ID), return &Result{r.Header.Get(HEADER_REQUEST_ID),
@@ -456,7 +580,7 @@ func (c *Client) RegenCommandToken(data map[string]string) (*Result, *AppError)
} }
func (c *Client) DeleteCommand(data map[string]string) (*Result, *AppError) { func (c *Client) DeleteCommand(data map[string]string) (*Result, *AppError) {
if r, err := c.DoApiPost("/commands/delete", MapToJson(data)); err != nil { if r, err := c.DoApiPost(c.GetTeamRoute()+"/commands/delete", MapToJson(data)); err != nil {
return nil, err return nil, err
} else { } else {
return &Result{r.Header.Get(HEADER_REQUEST_ID), return &Result{r.Header.Get(HEADER_REQUEST_ID),
@@ -582,7 +706,7 @@ func (c *Client) GetSystemAnalytics(name string) (*Result, *AppError) {
} }
func (c *Client) CreateChannel(channel *Channel) (*Result, *AppError) { func (c *Client) CreateChannel(channel *Channel) (*Result, *AppError) {
if r, err := c.DoApiPost("/channels/create", channel.ToJson()); err != nil { if r, err := c.DoApiPost(c.GetTeamRoute()+"/channels/create", channel.ToJson()); err != nil {
return nil, err return nil, err
} else { } else {
return &Result{r.Header.Get(HEADER_REQUEST_ID), return &Result{r.Header.Get(HEADER_REQUEST_ID),
@@ -590,8 +714,10 @@ func (c *Client) CreateChannel(channel *Channel) (*Result, *AppError) {
} }
} }
func (c *Client) CreateDirectChannel(data map[string]string) (*Result, *AppError) { func (c *Client) CreateDirectChannel(userId string) (*Result, *AppError) {
if r, err := c.DoApiPost("/channels/create_direct", MapToJson(data)); err != nil { data := make(map[string]string)
data["user_id"] = userId
if r, err := c.DoApiPost(c.GetTeamRoute()+"/channels/create_direct", MapToJson(data)); err != nil {
return nil, err return nil, err
} else { } else {
return &Result{r.Header.Get(HEADER_REQUEST_ID), return &Result{r.Header.Get(HEADER_REQUEST_ID),
@@ -600,7 +726,7 @@ func (c *Client) CreateDirectChannel(data map[string]string) (*Result, *AppError
} }
func (c *Client) UpdateChannel(channel *Channel) (*Result, *AppError) { func (c *Client) UpdateChannel(channel *Channel) (*Result, *AppError) {
if r, err := c.DoApiPost("/channels/update", channel.ToJson()); err != nil { if r, err := c.DoApiPost(c.GetTeamRoute()+"/channels/update", channel.ToJson()); err != nil {
return nil, err return nil, err
} else { } else {
return &Result{r.Header.Get(HEADER_REQUEST_ID), return &Result{r.Header.Get(HEADER_REQUEST_ID),
@@ -609,7 +735,7 @@ func (c *Client) UpdateChannel(channel *Channel) (*Result, *AppError) {
} }
func (c *Client) UpdateChannelHeader(data map[string]string) (*Result, *AppError) { func (c *Client) UpdateChannelHeader(data map[string]string) (*Result, *AppError) {
if r, err := c.DoApiPost("/channels/update_header", MapToJson(data)); err != nil { if r, err := c.DoApiPost(c.GetTeamRoute()+"/channels/update_header", MapToJson(data)); err != nil {
return nil, err return nil, err
} else { } else {
return &Result{r.Header.Get(HEADER_REQUEST_ID), return &Result{r.Header.Get(HEADER_REQUEST_ID),
@@ -618,7 +744,7 @@ func (c *Client) UpdateChannelHeader(data map[string]string) (*Result, *AppError
} }
func (c *Client) UpdateChannelPurpose(data map[string]string) (*Result, *AppError) { func (c *Client) UpdateChannelPurpose(data map[string]string) (*Result, *AppError) {
if r, err := c.DoApiPost("/channels/update_purpose", MapToJson(data)); err != nil { if r, err := c.DoApiPost(c.GetTeamRoute()+"/channels/update_purpose", MapToJson(data)); err != nil {
return nil, err return nil, err
} else { } else {
return &Result{r.Header.Get(HEADER_REQUEST_ID), return &Result{r.Header.Get(HEADER_REQUEST_ID),
@@ -627,7 +753,7 @@ func (c *Client) UpdateChannelPurpose(data map[string]string) (*Result, *AppErro
} }
func (c *Client) UpdateNotifyProps(data map[string]string) (*Result, *AppError) { func (c *Client) UpdateNotifyProps(data map[string]string) (*Result, *AppError) {
if r, err := c.DoApiPost("/channels/update_notify_props", MapToJson(data)); err != nil { if r, err := c.DoApiPost(c.GetTeamRoute()+"/channels/update_notify_props", MapToJson(data)); err != nil {
return nil, err return nil, err
} else { } else {
return &Result{r.Header.Get(HEADER_REQUEST_ID), return &Result{r.Header.Get(HEADER_REQUEST_ID),
@@ -636,7 +762,7 @@ func (c *Client) UpdateNotifyProps(data map[string]string) (*Result, *AppError)
} }
func (c *Client) GetChannels(etag string) (*Result, *AppError) { func (c *Client) GetChannels(etag string) (*Result, *AppError) {
if r, err := c.DoApiGet("/channels/", "", etag); err != nil { if r, err := c.DoApiGet(c.GetTeamRoute()+"/channels/", "", etag); err != nil {
return nil, err return nil, err
} else { } else {
return &Result{r.Header.Get(HEADER_REQUEST_ID), return &Result{r.Header.Get(HEADER_REQUEST_ID),
@@ -645,7 +771,7 @@ func (c *Client) GetChannels(etag string) (*Result, *AppError) {
} }
func (c *Client) GetChannel(id, etag string) (*Result, *AppError) { func (c *Client) GetChannel(id, etag string) (*Result, *AppError) {
if r, err := c.DoApiGet("/channels/"+id+"/", "", etag); err != nil { if r, err := c.DoApiGet(c.GetChannelRoute(id)+"/", "", etag); err != nil {
return nil, err return nil, err
} else { } else {
return &Result{r.Header.Get(HEADER_REQUEST_ID), return &Result{r.Header.Get(HEADER_REQUEST_ID),
@@ -654,7 +780,7 @@ func (c *Client) GetChannel(id, etag string) (*Result, *AppError) {
} }
func (c *Client) GetMoreChannels(etag string) (*Result, *AppError) { func (c *Client) GetMoreChannels(etag string) (*Result, *AppError) {
if r, err := c.DoApiGet("/channels/more", "", etag); err != nil { if r, err := c.DoApiGet(c.GetTeamRoute()+"/channels/more", "", etag); err != nil {
return nil, err return nil, err
} else { } else {
return &Result{r.Header.Get(HEADER_REQUEST_ID), return &Result{r.Header.Get(HEADER_REQUEST_ID),
@@ -663,7 +789,7 @@ func (c *Client) GetMoreChannels(etag string) (*Result, *AppError) {
} }
func (c *Client) GetChannelCounts(etag string) (*Result, *AppError) { func (c *Client) GetChannelCounts(etag string) (*Result, *AppError) {
if r, err := c.DoApiGet("/channels/counts", "", etag); err != nil { if r, err := c.DoApiGet(c.GetTeamRoute()+"/channels/counts", "", etag); err != nil {
return nil, err return nil, err
} else { } else {
return &Result{r.Header.Get(HEADER_REQUEST_ID), return &Result{r.Header.Get(HEADER_REQUEST_ID),
@@ -672,7 +798,7 @@ func (c *Client) GetChannelCounts(etag string) (*Result, *AppError) {
} }
func (c *Client) JoinChannel(id string) (*Result, *AppError) { func (c *Client) JoinChannel(id string) (*Result, *AppError) {
if r, err := c.DoApiPost("/channels/"+id+"/join", ""); err != nil { if r, err := c.DoApiPost(c.GetChannelRoute(id)+"/join", ""); err != nil {
return nil, err return nil, err
} else { } else {
return &Result{r.Header.Get(HEADER_REQUEST_ID), return &Result{r.Header.Get(HEADER_REQUEST_ID),
@@ -681,7 +807,7 @@ func (c *Client) JoinChannel(id string) (*Result, *AppError) {
} }
func (c *Client) LeaveChannel(id string) (*Result, *AppError) { func (c *Client) LeaveChannel(id string) (*Result, *AppError) {
if r, err := c.DoApiPost("/channels/"+id+"/leave", ""); err != nil { if r, err := c.DoApiPost(c.GetChannelRoute(id)+"/leave", ""); err != nil {
return nil, err return nil, err
} else { } else {
return &Result{r.Header.Get(HEADER_REQUEST_ID), return &Result{r.Header.Get(HEADER_REQUEST_ID),
@@ -690,7 +816,7 @@ func (c *Client) LeaveChannel(id string) (*Result, *AppError) {
} }
func (c *Client) DeleteChannel(id string) (*Result, *AppError) { func (c *Client) DeleteChannel(id string) (*Result, *AppError) {
if r, err := c.DoApiPost("/channels/"+id+"/delete", ""); err != nil { if r, err := c.DoApiPost(c.GetChannelRoute(id)+"/delete", ""); err != nil {
return nil, err return nil, err
} else { } else {
return &Result{r.Header.Get(HEADER_REQUEST_ID), return &Result{r.Header.Get(HEADER_REQUEST_ID),
@@ -701,7 +827,7 @@ func (c *Client) DeleteChannel(id string) (*Result, *AppError) {
func (c *Client) AddChannelMember(id, user_id string) (*Result, *AppError) { func (c *Client) AddChannelMember(id, user_id string) (*Result, *AppError) {
data := make(map[string]string) data := make(map[string]string)
data["user_id"] = user_id data["user_id"] = user_id
if r, err := c.DoApiPost("/channels/"+id+"/add", MapToJson(data)); err != nil { if r, err := c.DoApiPost(c.GetChannelRoute(id)+"/add", MapToJson(data)); err != nil {
return nil, err return nil, err
} else { } else {
return &Result{r.Header.Get(HEADER_REQUEST_ID), return &Result{r.Header.Get(HEADER_REQUEST_ID),
@@ -712,7 +838,7 @@ func (c *Client) AddChannelMember(id, user_id string) (*Result, *AppError) {
func (c *Client) RemoveChannelMember(id, user_id string) (*Result, *AppError) { func (c *Client) RemoveChannelMember(id, user_id string) (*Result, *AppError) {
data := make(map[string]string) data := make(map[string]string)
data["user_id"] = user_id data["user_id"] = user_id
if r, err := c.DoApiPost("/channels/"+id+"/remove", MapToJson(data)); err != nil { if r, err := c.DoApiPost(c.GetChannelRoute(id)+"/remove", MapToJson(data)); err != nil {
return nil, err return nil, err
} else { } else {
return &Result{r.Header.Get(HEADER_REQUEST_ID), return &Result{r.Header.Get(HEADER_REQUEST_ID),
@@ -721,7 +847,7 @@ func (c *Client) RemoveChannelMember(id, user_id string) (*Result, *AppError) {
} }
func (c *Client) UpdateLastViewedAt(channelId string) (*Result, *AppError) { func (c *Client) UpdateLastViewedAt(channelId string) (*Result, *AppError) {
if r, err := c.DoApiPost("/channels/"+channelId+"/update_last_viewed_at", ""); err != nil { if r, err := c.DoApiPost(c.GetChannelRoute(channelId)+"/update_last_viewed_at", ""); err != nil {
return nil, err return nil, err
} else { } else {
return &Result{r.Header.Get(HEADER_REQUEST_ID), return &Result{r.Header.Get(HEADER_REQUEST_ID),
@@ -730,7 +856,7 @@ func (c *Client) UpdateLastViewedAt(channelId string) (*Result, *AppError) {
} }
func (c *Client) GetChannelExtraInfo(id string, memberLimit int, etag string) (*Result, *AppError) { func (c *Client) GetChannelExtraInfo(id string, memberLimit int, etag string) (*Result, *AppError) {
if r, err := c.DoApiGet("/channels/"+id+"/extra_info/"+strconv.FormatInt(int64(memberLimit), 10), "", etag); err != nil { if r, err := c.DoApiGet(c.GetChannelRoute(id)+"/extra_info/"+strconv.FormatInt(int64(memberLimit), 10), "", etag); err != nil {
return nil, err return nil, err
} else { } else {
return &Result{r.Header.Get(HEADER_REQUEST_ID), return &Result{r.Header.Get(HEADER_REQUEST_ID),
@@ -739,7 +865,7 @@ func (c *Client) GetChannelExtraInfo(id string, memberLimit int, etag string) (*
} }
func (c *Client) CreatePost(post *Post) (*Result, *AppError) { func (c *Client) CreatePost(post *Post) (*Result, *AppError) {
if r, err := c.DoApiPost("/channels/"+post.ChannelId+"/create", post.ToJson()); err != nil { if r, err := c.DoApiPost(c.GetChannelRoute(post.ChannelId)+"/posts/create", post.ToJson()); err != nil {
return nil, err return nil, err
} else { } else {
return &Result{r.Header.Get(HEADER_REQUEST_ID), return &Result{r.Header.Get(HEADER_REQUEST_ID),
@@ -748,7 +874,7 @@ func (c *Client) CreatePost(post *Post) (*Result, *AppError) {
} }
func (c *Client) UpdatePost(post *Post) (*Result, *AppError) { func (c *Client) UpdatePost(post *Post) (*Result, *AppError) {
if r, err := c.DoApiPost("/channels/"+post.ChannelId+"/update", post.ToJson()); err != nil { if r, err := c.DoApiPost(c.GetChannelRoute(post.ChannelId)+"/posts/update", post.ToJson()); err != nil {
return nil, err return nil, err
} else { } else {
return &Result{r.Header.Get(HEADER_REQUEST_ID), return &Result{r.Header.Get(HEADER_REQUEST_ID),
@@ -757,7 +883,7 @@ func (c *Client) UpdatePost(post *Post) (*Result, *AppError) {
} }
func (c *Client) GetPosts(channelId string, offset int, limit int, etag string) (*Result, *AppError) { func (c *Client) GetPosts(channelId string, offset int, limit int, etag string) (*Result, *AppError) {
if r, err := c.DoApiGet(fmt.Sprintf("/channels/%v/posts/%v/%v", channelId, offset, limit), "", etag); err != nil { if r, err := c.DoApiGet(c.GetChannelRoute(channelId)+fmt.Sprintf("/posts/page/%v/%v", offset, limit), "", etag); err != nil {
return nil, err return nil, err
} else { } else {
return &Result{r.Header.Get(HEADER_REQUEST_ID), return &Result{r.Header.Get(HEADER_REQUEST_ID),
@@ -766,7 +892,7 @@ func (c *Client) GetPosts(channelId string, offset int, limit int, etag string)
} }
func (c *Client) GetPostsSince(channelId string, time int64) (*Result, *AppError) { func (c *Client) GetPostsSince(channelId string, time int64) (*Result, *AppError) {
if r, err := c.DoApiGet(fmt.Sprintf("/channels/%v/posts/%v", channelId, time), "", ""); err != nil { if r, err := c.DoApiGet(c.GetChannelRoute(channelId)+fmt.Sprintf("/posts/since/%v", time), "", ""); err != nil {
return nil, err return nil, err
} else { } else {
return &Result{r.Header.Get(HEADER_REQUEST_ID), return &Result{r.Header.Get(HEADER_REQUEST_ID),
@@ -775,7 +901,7 @@ func (c *Client) GetPostsSince(channelId string, time int64) (*Result, *AppError
} }
func (c *Client) GetPostsBefore(channelId string, postid string, offset int, limit int, etag string) (*Result, *AppError) { func (c *Client) GetPostsBefore(channelId string, postid string, offset int, limit int, etag string) (*Result, *AppError) {
if r, err := c.DoApiGet(fmt.Sprintf("/channels/%v/post/%v/before/%v/%v", channelId, postid, offset, limit), "", etag); err != nil { if r, err := c.DoApiGet(c.GetChannelRoute(channelId)+fmt.Sprintf("/posts/%v/before/%v/%v", postid, offset, limit), "", etag); err != nil {
return nil, err return nil, err
} else { } else {
return &Result{r.Header.Get(HEADER_REQUEST_ID), return &Result{r.Header.Get(HEADER_REQUEST_ID),
@@ -784,7 +910,7 @@ func (c *Client) GetPostsBefore(channelId string, postid string, offset int, lim
} }
func (c *Client) GetPostsAfter(channelId string, postid string, offset int, limit int, etag string) (*Result, *AppError) { func (c *Client) GetPostsAfter(channelId string, postid string, offset int, limit int, etag string) (*Result, *AppError) {
if r, err := c.DoApiGet(fmt.Sprintf("/channels/%v/post/%v/after/%v/%v", channelId, postid, offset, limit), "", etag); err != nil { if r, err := c.DoApiGet(fmt.Sprintf(c.GetChannelRoute(channelId)+"/posts/%v/after/%v/%v", postid, offset, limit), "", etag); err != nil {
return nil, err return nil, err
} else { } else {
return &Result{r.Header.Get(HEADER_REQUEST_ID), return &Result{r.Header.Get(HEADER_REQUEST_ID),
@@ -793,7 +919,7 @@ func (c *Client) GetPostsAfter(channelId string, postid string, offset int, limi
} }
func (c *Client) GetPost(channelId string, postId string, etag string) (*Result, *AppError) { func (c *Client) GetPost(channelId string, postId string, etag string) (*Result, *AppError) {
if r, err := c.DoApiGet(fmt.Sprintf("/channels/%v/post/%v", channelId, postId), "", etag); err != nil { if r, err := c.DoApiGet(c.GetChannelRoute(channelId)+fmt.Sprintf("/posts/%v/get", postId), "", etag); err != nil {
return nil, err return nil, err
} else { } else {
return &Result{r.Header.Get(HEADER_REQUEST_ID), return &Result{r.Header.Get(HEADER_REQUEST_ID),
@@ -802,7 +928,7 @@ func (c *Client) GetPost(channelId string, postId string, etag string) (*Result,
} }
func (c *Client) DeletePost(channelId string, postId string) (*Result, *AppError) { func (c *Client) DeletePost(channelId string, postId string) (*Result, *AppError) {
if r, err := c.DoApiPost(fmt.Sprintf("/channels/%v/post/%v/delete", channelId, postId), ""); err != nil { if r, err := c.DoApiPost(c.GetChannelRoute(channelId)+fmt.Sprintf("/posts/%v/delete", postId), ""); err != nil {
return nil, err return nil, err
} else { } else {
return &Result{r.Header.Get(HEADER_REQUEST_ID), return &Result{r.Header.Get(HEADER_REQUEST_ID),
@@ -811,7 +937,7 @@ func (c *Client) DeletePost(channelId string, postId string) (*Result, *AppError
} }
func (c *Client) SearchPosts(terms string) (*Result, *AppError) { func (c *Client) SearchPosts(terms string) (*Result, *AppError) {
if r, err := c.DoApiGet("/posts/search?terms="+url.QueryEscape(terms), "", ""); err != nil { if r, err := c.DoApiGet(c.GetTeamRoute()+"/posts/search?terms="+url.QueryEscape(terms), "", ""); err != nil {
return nil, err return nil, err
} else { } else {
return &Result{r.Header.Get(HEADER_REQUEST_ID), return &Result{r.Header.Get(HEADER_REQUEST_ID),
@@ -819,8 +945,16 @@ func (c *Client) SearchPosts(terms string) (*Result, *AppError) {
} }
} }
func (c *Client) UploadFile(url string, data []byte, contentType string) (*Result, *AppError) { func (c *Client) UploadProfileFile(data []byte, contentType string) (*Result, *AppError) {
rq, _ := http.NewRequest("POST", c.ApiUrl+url, bytes.NewReader(data)) return c.uploadFile(c.ApiUrl+"/users/newimage", data, contentType)
}
func (c *Client) UploadPostAttachment(data []byte, contentType string) (*Result, *AppError) {
return c.uploadFile(c.ApiUrl+c.GetTeamRoute()+"/files/upload", data, contentType)
}
func (c *Client) uploadFile(url string, data []byte, contentType string) (*Result, *AppError) {
rq, _ := http.NewRequest("POST", url, bytes.NewReader(data))
rq.Header.Set("Content-Type", contentType) rq.Header.Set("Content-Type", contentType)
if len(c.AuthToken) > 0 { if len(c.AuthToken) > 0 {
@@ -842,7 +976,7 @@ func (c *Client) GetFile(url string, isFullUrl bool) (*Result, *AppError) {
if isFullUrl { if isFullUrl {
rq, _ = http.NewRequest("GET", url, nil) rq, _ = http.NewRequest("GET", url, nil)
} else { } else {
rq, _ = http.NewRequest("GET", c.ApiUrl+"/files/get"+url, nil) rq, _ = http.NewRequest("GET", c.ApiUrl+c.GetTeamRoute()+"/files/get"+url, nil)
} }
if len(c.AuthToken) > 0 { if len(c.AuthToken) > 0 {
@@ -861,7 +995,7 @@ func (c *Client) GetFile(url string, isFullUrl bool) (*Result, *AppError) {
func (c *Client) GetFileInfo(url string) (*Result, *AppError) { func (c *Client) GetFileInfo(url string) (*Result, *AppError) {
var rq *http.Request var rq *http.Request
rq, _ = http.NewRequest("GET", c.ApiUrl+"/files/get_info"+url, nil) rq, _ = http.NewRequest("GET", c.ApiUrl+c.GetTeamRoute()+"/files/get_info"+url, nil)
if len(c.AuthToken) > 0 { if len(c.AuthToken) > 0 {
rq.Header.Set(HEADER_AUTH, "BEARER "+c.AuthToken) rq.Header.Set(HEADER_AUTH, "BEARER "+c.AuthToken)
@@ -878,7 +1012,7 @@ func (c *Client) GetFileInfo(url string) (*Result, *AppError) {
} }
func (c *Client) GetPublicLink(data map[string]string) (*Result, *AppError) { func (c *Client) GetPublicLink(data map[string]string) (*Result, *AppError) {
if r, err := c.DoApiPost("/files/get_public_link", MapToJson(data)); err != nil { if r, err := c.DoApiPost(c.GetTeamRoute()+"/files/get_public_link", MapToJson(data)); err != nil {
return nil, err return nil, err
} else { } else {
return &Result{r.Header.Get(HEADER_REQUEST_ID), return &Result{r.Header.Get(HEADER_REQUEST_ID),
@@ -950,7 +1084,9 @@ func (c *Client) UpdateUserPassword(userId, currentPassword, newPassword string)
} }
} }
func (c *Client) SendPasswordReset(data map[string]string) (*Result, *AppError) { func (c *Client) SendPasswordReset(email string) (*Result, *AppError) {
data := map[string]string{}
data["email"] = email
if r, err := c.DoApiPost("/users/send_password_reset", MapToJson(data)); err != nil { if r, err := c.DoApiPost("/users/send_password_reset", MapToJson(data)); err != nil {
return nil, err return nil, err
} else { } else {
@@ -959,7 +1095,10 @@ func (c *Client) SendPasswordReset(data map[string]string) (*Result, *AppError)
} }
} }
func (c *Client) ResetPassword(data map[string]string) (*Result, *AppError) { func (c *Client) ResetPassword(code, newPassword string) (*Result, *AppError) {
data := map[string]string{}
data["code"] = code
data["new_password"] = newPassword
if r, err := c.DoApiPost("/users/reset_password", MapToJson(data)); err != nil { if r, err := c.DoApiPost("/users/reset_password", MapToJson(data)); err != nil {
return nil, err return nil, err
} else { } else {
@@ -968,6 +1107,18 @@ func (c *Client) ResetPassword(data map[string]string) (*Result, *AppError) {
} }
} }
func (c *Client) AdminResetPassword(userId, newPassword string) (*Result, *AppError) {
data := map[string]string{}
data["user_id"] = userId
data["new_password"] = newPassword
if r, err := c.DoApiPost("/admin/reset_password", MapToJson(data)); err != nil {
return nil, err
} else {
return &Result{r.Header.Get(HEADER_REQUEST_ID),
r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil
}
}
func (c *Client) GetStatuses(data []string) (*Result, *AppError) { func (c *Client) GetStatuses(data []string) (*Result, *AppError) {
if r, err := c.DoApiPost("/users/status", ArrayToJson(data)); err != nil { if r, err := c.DoApiPost("/users/status", ArrayToJson(data)); err != nil {
return nil, err return nil, err
@@ -978,7 +1129,7 @@ func (c *Client) GetStatuses(data []string) (*Result, *AppError) {
} }
func (c *Client) GetMyTeam(etag string) (*Result, *AppError) { func (c *Client) GetMyTeam(etag string) (*Result, *AppError) {
if r, err := c.DoApiGet("/teams/me", "", etag); err != nil { if r, err := c.DoApiGet(c.GetTeamRoute()+"/me", "", etag); err != nil {
return nil, err return nil, err
} else { } else {
return &Result{r.Header.Get(HEADER_REQUEST_ID), return &Result{r.Header.Get(HEADER_REQUEST_ID),
@@ -986,6 +1137,15 @@ func (c *Client) GetMyTeam(etag string) (*Result, *AppError) {
} }
} }
func (c *Client) GetTeamMembers(teamId string) (*Result, *AppError) {
if r, err := c.DoApiGet("/teams/members/"+teamId, "", ""); err != nil {
return nil, err
} else {
return &Result{r.Header.Get(HEADER_REQUEST_ID),
r.Header.Get(HEADER_ETAG_SERVER), TeamMembersFromJson(r.Body)}, nil
}
}
func (c *Client) RegisterApp(app *OAuthApp) (*Result, *AppError) { func (c *Client) RegisterApp(app *OAuthApp) (*Result, *AppError) {
if r, err := c.DoApiPost("/oauth/register", app.ToJson()); err != nil { if r, err := c.DoApiPost("/oauth/register", app.ToJson()); err != nil {
return nil, err return nil, err
@@ -1014,7 +1174,7 @@ func (c *Client) GetAccessToken(data url.Values) (*Result, *AppError) {
} }
func (c *Client) CreateIncomingWebhook(hook *IncomingWebhook) (*Result, *AppError) { func (c *Client) CreateIncomingWebhook(hook *IncomingWebhook) (*Result, *AppError) {
if r, err := c.DoApiPost("/hooks/incoming/create", hook.ToJson()); err != nil { if r, err := c.DoApiPost(c.GetTeamRoute()+"/hooks/incoming/create", hook.ToJson()); err != nil {
return nil, err return nil, err
} else { } else {
return &Result{r.Header.Get(HEADER_REQUEST_ID), return &Result{r.Header.Get(HEADER_REQUEST_ID),
@@ -1031,8 +1191,10 @@ func (c *Client) PostToWebhook(id, payload string) (*Result, *AppError) {
} }
} }
func (c *Client) DeleteIncomingWebhook(data map[string]string) (*Result, *AppError) { func (c *Client) DeleteIncomingWebhook(id string) (*Result, *AppError) {
if r, err := c.DoApiPost("/hooks/incoming/delete", MapToJson(data)); err != nil { data := make(map[string]string)
data["id"] = id
if r, err := c.DoApiPost(c.GetTeamRoute()+"/hooks/incoming/delete", MapToJson(data)); err != nil {
return nil, err return nil, err
} else { } else {
return &Result{r.Header.Get(HEADER_REQUEST_ID), return &Result{r.Header.Get(HEADER_REQUEST_ID),
@@ -1041,7 +1203,7 @@ func (c *Client) DeleteIncomingWebhook(data map[string]string) (*Result, *AppErr
} }
func (c *Client) ListIncomingWebhooks() (*Result, *AppError) { func (c *Client) ListIncomingWebhooks() (*Result, *AppError) {
if r, err := c.DoApiGet("/hooks/incoming/list", "", ""); err != nil { if r, err := c.DoApiGet(c.GetTeamRoute()+"/hooks/incoming/list", "", ""); err != nil {
return nil, err return nil, err
} else { } else {
return &Result{r.Header.Get(HEADER_REQUEST_ID), return &Result{r.Header.Get(HEADER_REQUEST_ID),
@@ -1085,7 +1247,7 @@ func (c *Client) GetPreferenceCategory(category string) (*Result, *AppError) {
} }
func (c *Client) CreateOutgoingWebhook(hook *OutgoingWebhook) (*Result, *AppError) { func (c *Client) CreateOutgoingWebhook(hook *OutgoingWebhook) (*Result, *AppError) {
if r, err := c.DoApiPost("/hooks/outgoing/create", hook.ToJson()); err != nil { if r, err := c.DoApiPost(c.GetTeamRoute()+"/hooks/outgoing/create", hook.ToJson()); err != nil {
return nil, err return nil, err
} else { } else {
return &Result{r.Header.Get(HEADER_REQUEST_ID), return &Result{r.Header.Get(HEADER_REQUEST_ID),
@@ -1093,8 +1255,10 @@ func (c *Client) CreateOutgoingWebhook(hook *OutgoingWebhook) (*Result, *AppErro
} }
} }
func (c *Client) DeleteOutgoingWebhook(data map[string]string) (*Result, *AppError) { func (c *Client) DeleteOutgoingWebhook(id string) (*Result, *AppError) {
if r, err := c.DoApiPost("/hooks/outgoing/delete", MapToJson(data)); err != nil { data := make(map[string]string)
data["id"] = id
if r, err := c.DoApiPost(c.GetTeamRoute()+"/hooks/outgoing/delete", MapToJson(data)); err != nil {
return nil, err return nil, err
} else { } else {
return &Result{r.Header.Get(HEADER_REQUEST_ID), return &Result{r.Header.Get(HEADER_REQUEST_ID),
@@ -1103,7 +1267,7 @@ func (c *Client) DeleteOutgoingWebhook(data map[string]string) (*Result, *AppErr
} }
func (c *Client) ListOutgoingWebhooks() (*Result, *AppError) { func (c *Client) ListOutgoingWebhooks() (*Result, *AppError) {
if r, err := c.DoApiGet("/hooks/outgoing/list", "", ""); err != nil { if r, err := c.DoApiGet(c.GetTeamRoute()+"/hooks/outgoing/list", "", ""); err != nil {
return nil, err return nil, err
} else { } else {
return &Result{r.Header.Get(HEADER_REQUEST_ID), return &Result{r.Header.Get(HEADER_REQUEST_ID),
@@ -1111,8 +1275,10 @@ func (c *Client) ListOutgoingWebhooks() (*Result, *AppError) {
} }
} }
func (c *Client) RegenOutgoingWebhookToken(data map[string]string) (*Result, *AppError) { func (c *Client) RegenOutgoingWebhookToken(id string) (*Result, *AppError) {
if r, err := c.DoApiPost("/hooks/outgoing/regen_token", MapToJson(data)); err != nil { data := make(map[string]string)
data["id"] = id
if r, err := c.DoApiPost(c.GetTeamRoute()+"/hooks/outgoing/regen_token", MapToJson(data)); err != nil {
return nil, err return nil, err
} else { } else {
return &Result{r.Header.Get(HEADER_REQUEST_ID), return &Result{r.Header.Get(HEADER_REQUEST_ID),
@@ -1134,11 +1300,11 @@ func (c *Client) GetClientLicenceConfig(etag string) (*Result, *AppError) {
} }
} }
func (c *Client) GetMeLoggedIn() (*Result, *AppError) { func (c *Client) GetInitialLoad() (*Result, *AppError) {
if r, err := c.DoApiGet("/users/me_logged_in", "", ""); err != nil { if r, err := c.DoApiGet("/users/initial_load", "", ""); err != nil {
return nil, err return nil, err
} else { } else {
return &Result{r.Header.Get(HEADER_REQUEST_ID), return &Result{r.Header.Get(HEADER_REQUEST_ID),
r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil r.Header.Get(HEADER_ETAG_SERVER), InitialLoadFromJson(r.Body)}, nil
} }
} }

Просмотреть файл

@@ -99,7 +99,7 @@ func (o *Command) IsValid() *AppError {
return NewLocAppError("Command.IsValid", "model.command.is_valid.team_id.app_error", nil, "") return NewLocAppError("Command.IsValid", "model.command.is_valid.team_id.app_error", nil, "")
} }
if len(o.Trigger) > 128 { if len(o.Trigger) == 0 || len(o.Trigger) > 128 {
return NewLocAppError("Command.IsValid", "model.command.is_valid.trigger.app_error", nil, "") return NewLocAppError("Command.IsValid", "model.command.is_valid.trigger.app_error", nil, "")
} }

Просмотреть файл

@@ -19,63 +19,115 @@ func TestCommandJson(t *testing.T) {
} }
func TestCommandIsValid(t *testing.T) { func TestCommandIsValid(t *testing.T) {
o := Command{} o := Command{
Id: NewId(),
Token: NewId(),
CreateAt: GetMillis(),
UpdateAt: GetMillis(),
CreatorId: NewId(),
TeamId: NewId(),
Trigger: "trigger",
URL: "http://example.com",
Method: COMMAND_METHOD_GET,
DisplayName: "",
Description: "",
}
if err := o.IsValid(); err != nil {
t.Fatal(err)
}
o.Id = ""
if err := o.IsValid(); err == nil { if err := o.IsValid(); err == nil {
t.Fatal("should be invalid") t.Fatal("should be invalid")
} }
o.Id = NewId() o.Id = NewId()
if err := o.IsValid(); err == nil { if err := o.IsValid(); err != nil {
t.Fatal("should be invalid") t.Fatal(err)
} }
o.CreateAt = GetMillis() o.Token = ""
if err := o.IsValid(); err == nil {
t.Fatal("should be invalid")
}
o.UpdateAt = GetMillis()
if err := o.IsValid(); err == nil {
t.Fatal("should be invalid")
}
o.CreatorId = "123"
if err := o.IsValid(); err == nil {
t.Fatal("should be invalid")
}
o.CreatorId = NewId()
if err := o.IsValid(); err == nil {
t.Fatal("should be invalid")
}
o.Token = "123"
if err := o.IsValid(); err == nil { if err := o.IsValid(); err == nil {
t.Fatal("should be invalid") t.Fatal("should be invalid")
} }
o.Token = NewId() o.Token = NewId()
if err := o.IsValid(); err != nil {
t.Fatal(err)
}
o.CreateAt = 0
if err := o.IsValid(); err == nil { if err := o.IsValid(); err == nil {
t.Fatal("should be invalid") t.Fatal("should be invalid")
} }
o.TeamId = "123" o.CreateAt = GetMillis()
if err := o.IsValid(); err != nil {
t.Fatal(err)
}
o.UpdateAt = 0
if err := o.IsValid(); err == nil {
t.Fatal("should be invalid")
}
o.UpdateAt = GetMillis()
if err := o.IsValid(); err != nil {
t.Fatal(err)
}
o.CreatorId = ""
if err := o.IsValid(); err == nil {
t.Fatal("should be invalid")
}
o.CreatorId = NewId()
if err := o.IsValid(); err != nil {
t.Fatal(err)
}
o.TeamId = ""
if err := o.IsValid(); err == nil { if err := o.IsValid(); err == nil {
t.Fatal("should be invalid") t.Fatal("should be invalid")
} }
o.TeamId = NewId() o.TeamId = NewId()
if err := o.IsValid(); err != nil {
t.Fatal(err)
}
o.Trigger = ""
if err := o.IsValid(); err == nil { if err := o.IsValid(); err == nil {
t.Fatal("should be invalid") t.Fatal("should be invalid")
} }
o.URL = "nowhere.com/" o.Trigger = strings.Repeat("1", 129)
if err := o.IsValid(); err == nil { if err := o.IsValid(); err == nil {
t.Fatal("should be invalid") t.Fatal("should be invalid")
} }
o.URL = "http://nowhere.com/" o.Trigger = strings.Repeat("1", 128)
if err := o.IsValid(); err != nil {
t.Fatal(err)
}
o.URL = ""
if err := o.IsValid(); err == nil {
t.Fatal("should be invalid")
}
o.URL = "1234"
if err := o.IsValid(); err == nil {
t.Fatal("should be invalid")
}
o.URL = "https://example.com"
if err := o.IsValid(); err != nil {
t.Fatal(err)
}
o.Method = "https://example.com"
if err := o.IsValid(); err == nil { if err := o.IsValid(); err == nil {
t.Fatal("should be invalid") t.Fatal("should be invalid")
} }
@@ -85,6 +137,11 @@ func TestCommandIsValid(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
o.Method = COMMAND_METHOD_POST
if err := o.IsValid(); err != nil {
t.Fatal(err)
}
o.DisplayName = strings.Repeat("1", 65) o.DisplayName = strings.Repeat("1", 65)
if err := o.IsValid(); err == nil { if err := o.IsValid(); err == nil {
t.Fatal("should be invalid") t.Fatal("should be invalid")

Просмотреть файл

@@ -155,9 +155,9 @@ type TeamSettings struct {
MaxUsersPerTeam int MaxUsersPerTeam int
EnableTeamCreation bool EnableTeamCreation bool
EnableUserCreation bool EnableUserCreation bool
EnableOpenServer *bool
RestrictCreationToDomains string RestrictCreationToDomains string
RestrictTeamNames *bool RestrictTeamNames *bool
EnableTeamListing *bool
EnableCustomBrand *bool EnableCustomBrand *bool
CustomBrandText *string CustomBrandText *string
} }
@@ -180,6 +180,7 @@ type LdapSettings struct {
LastNameAttribute *string LastNameAttribute *string
EmailAttribute *string EmailAttribute *string
UsernameAttribute *string UsernameAttribute *string
NicknameAttribute *string
IdAttribute *string IdAttribute *string
// Advanced // Advanced
@@ -297,11 +298,6 @@ func (o *Config) SetDefaults() {
*o.TeamSettings.RestrictTeamNames = true *o.TeamSettings.RestrictTeamNames = true
} }
if o.TeamSettings.EnableTeamListing == nil {
o.TeamSettings.EnableTeamListing = new(bool)
*o.TeamSettings.EnableTeamListing = false
}
if o.TeamSettings.EnableCustomBrand == nil { if o.TeamSettings.EnableCustomBrand == nil {
o.TeamSettings.EnableCustomBrand = new(bool) o.TeamSettings.EnableCustomBrand = new(bool)
*o.TeamSettings.EnableCustomBrand = false *o.TeamSettings.EnableCustomBrand = false
@@ -312,6 +308,11 @@ func (o *Config) SetDefaults() {
*o.TeamSettings.CustomBrandText = "" *o.TeamSettings.CustomBrandText = ""
} }
if o.TeamSettings.EnableOpenServer == nil {
o.TeamSettings.EnableOpenServer = new(bool)
*o.TeamSettings.EnableOpenServer = false
}
if o.EmailSettings.EnableSignInWithEmail == nil { if o.EmailSettings.EnableSignInWithEmail == nil {
o.EmailSettings.EnableSignInWithEmail = new(bool) o.EmailSettings.EnableSignInWithEmail = new(bool)
@@ -476,6 +477,11 @@ func (o *Config) SetDefaults() {
o.LdapSettings.SkipCertificateVerification = new(bool) o.LdapSettings.SkipCertificateVerification = new(bool)
*o.LdapSettings.SkipCertificateVerification = false *o.LdapSettings.SkipCertificateVerification = false
} }
if o.LdapSettings.NicknameAttribute == nil {
o.LdapSettings.NicknameAttribute = new(string)
*o.LdapSettings.NicknameAttribute = ""
}
} }
func (o *Config) IsValid() *AppError { func (o *Config) IsValid() *AppError {

8
model/gitlab.go Обычный файл
Просмотреть файл

@@ -0,0 +1,8 @@
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
const (
USER_AUTH_SERVICE_GITLAB = "gitlab"
)

Просмотреть файл

@@ -12,10 +12,6 @@ import (
"strings" "strings"
) )
const (
USER_AUTH_SERVICE_GITLAB = "gitlab"
)
type GitLabProvider struct { type GitLabProvider struct {
} }
@@ -29,7 +25,7 @@ type GitLabUser struct {
func init() { func init() {
provider := &GitLabProvider{} provider := &GitLabProvider{}
einterfaces.RegisterOauthProvider(USER_AUTH_SERVICE_GITLAB, provider) einterfaces.RegisterOauthProvider(model.USER_AUTH_SERVICE_GITLAB, provider)
} }
func userFromGitLabUser(glu *GitLabUser) *model.User { func userFromGitLabUser(glu *GitLabUser) *model.User {
@@ -51,7 +47,7 @@ func userFromGitLabUser(glu *GitLabUser) *model.User {
} }
user.Email = glu.Email user.Email = glu.Email
user.AuthData = strconv.FormatInt(glu.Id, 10) user.AuthData = strconv.FormatInt(glu.Id, 10)
user.AuthService = USER_AUTH_SERVICE_GITLAB user.AuthService = model.USER_AUTH_SERVICE_GITLAB
return user return user
} }
@@ -84,7 +80,7 @@ func (glu *GitLabUser) getAuthData() string {
} }
func (m *GitLabProvider) GetIdentifier() string { func (m *GitLabProvider) GetIdentifier() string {
return USER_AUTH_SERVICE_GITLAB return model.USER_AUTH_SERVICE_GITLAB
} }
func (m *GitLabProvider) GetUserFromJson(data io.Reader) *model.User { func (m *GitLabProvider) GetUserFromJson(data io.Reader) *model.User {

40
model/initial_load.go Обычный файл
Просмотреть файл

@@ -0,0 +1,40 @@
// Copyright (c) 2016 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"`
DirectProfiles map[string]*User `json:"direct_profiles"`
Preferences Preferences `json:"preferences"`
ClientCfg map[string]string `json:"client_cfg"`
LicenseCfg map[string]string `json:"license_cfg"`
NoAccounts bool `json:"no_accounts"`
}
func (me *InitialLoad) ToJson() string {
b, err := json.Marshal(me)
if err != nil {
return ""
} else {
return string(b)
}
}
func InitialLoadFromJson(data io.Reader) *InitialLoad {
decoder := json.NewDecoder(data)
var o InitialLoad
err := decoder.Decode(&o)
if err == nil {
return &o
} else {
return nil
}
}

20
model/initial_load_test.go Обычный файл
Просмотреть файл

@@ -0,0 +1,20 @@
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
import (
"strings"
"testing"
)
func TestInitialLoadJson(t *testing.T) {
u := &User{Id: NewId()}
o := InitialLoad{User: u}
json := o.ToJson()
ro := InitialLoadFromJson(strings.NewReader(json))
if o.User.Id != ro.User.Id {
t.Fatal("Ids do not match")
}
}

37
model/password_recovery.go Обычный файл
Просмотреть файл

@@ -0,0 +1,37 @@
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
const (
PASSWORD_RECOVERY_CODE_SIZE = 128
PASSWORD_RECOVER_EXPIRY_TIME = 1000 * 60 * 60 // 1 hour
)
type PasswordRecovery struct {
UserId string
Code string
CreateAt int64
}
func (p *PasswordRecovery) IsValid() *AppError {
if len(p.UserId) != 26 {
return NewLocAppError("User.IsValid", "model.password_recovery.is_valid.user_id.app_error", nil, "")
}
if len(p.Code) != PASSWORD_RECOVERY_CODE_SIZE {
return NewLocAppError("User.IsValid", "model.password_recovery.is_valid.code.app_error", nil, "")
}
if p.CreateAt == 0 {
return NewLocAppError("User.IsValid", "model.password_recovery.is_valid.create_at.app_error", nil, "")
}
return nil
}
func (p *PasswordRecovery) PreSave() {
p.Code = NewRandomString(PASSWORD_RECOVERY_CODE_SIZE)
p.CreateAt = GetMillis()
}

Просмотреть файл

@@ -17,17 +17,17 @@ const (
) )
type Session struct { type Session struct {
Id string `json:"id"` Id string `json:"id"`
Token string `json:"token"` Token string `json:"token"`
CreateAt int64 `json:"create_at"` CreateAt int64 `json:"create_at"`
ExpiresAt int64 `json:"expires_at"` ExpiresAt int64 `json:"expires_at"`
LastActivityAt int64 `json:"last_activity_at"` LastActivityAt int64 `json:"last_activity_at"`
UserId string `json:"user_id"` UserId string `json:"user_id"`
TeamId string `json:"team_id"` DeviceId string `json:"device_id"`
DeviceId string `json:"device_id"` Roles string `json:"roles"`
Roles string `json:"roles"` IsOAuth bool `json:"is_oauth"`
IsOAuth bool `json:"is_oauth"` Props StringMap `json:"props"`
Props StringMap `json:"props"` TeamMembers []*TeamMember `json:"team_members" db:"-"`
} }
func (me *Session) ToJson() string { func (me *Session) ToJson() string {
@@ -95,6 +95,16 @@ func (me *Session) AddProp(key string, value string) {
me.Props[key] = value me.Props[key] = value
} }
func (me *Session) GetTeamByTeamId(teamId string) *TeamMember {
for _, team := range me.TeamMembers {
if team.TeamId == teamId {
return team
}
}
return nil
}
func SessionsToJson(o []*Session) string { func SessionsToJson(o []*Session) string {
if b, err := json.Marshal(o); err != nil { if b, err := json.Marshal(o); err != nil {
return "[]" return "[]"

Просмотреть файл

@@ -18,19 +18,18 @@ const (
) )
type Team struct { type Team struct {
Id string `json:"id"` Id string `json:"id"`
CreateAt int64 `json:"create_at"` CreateAt int64 `json:"create_at"`
UpdateAt int64 `json:"update_at"` UpdateAt int64 `json:"update_at"`
DeleteAt int64 `json:"delete_at"` DeleteAt int64 `json:"delete_at"`
DisplayName string `json:"display_name"` DisplayName string `json:"display_name"`
Name string `json:"name"` Name string `json:"name"`
Email string `json:"email"` Email string `json:"email"`
Type string `json:"type"` Type string `json:"type"`
CompanyName string `json:"company_name"` CompanyName string `json:"company_name"`
AllowedDomains string `json:"allowed_domains"` AllowedDomains string `json:"allowed_domains"`
InviteId string `json:"invite_id"` InviteId string `json:"invite_id"`
AllowOpenInvite bool `json:"allow_open_invite"` AllowOpenInvite bool `json:"allow_open_invite"`
AllowTeamListing bool `json:"allow_team_listing"`
} }
type Invites struct { type Invites struct {

78
model/team_member.go Обычный файл
Просмотреть файл

@@ -0,0 +1,78 @@
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
import (
"encoding/json"
"io"
"strings"
)
const (
ROLE_TEAM_ADMIN = "admin"
)
type TeamMember struct {
TeamId string `json:"team_id"`
UserId string `json:"user_id"`
Roles string `json:"roles"`
}
func (o *TeamMember) ToJson() string {
b, err := json.Marshal(o)
if err != nil {
return ""
} else {
return string(b)
}
}
func TeamMemberFromJson(data io.Reader) *TeamMember {
decoder := json.NewDecoder(data)
var o TeamMember
err := decoder.Decode(&o)
if err == nil {
return &o
} else {
return nil
}
}
func TeamMembersToJson(o []*TeamMember) string {
if b, err := json.Marshal(o); err != nil {
return "[]"
} else {
return string(b)
}
}
func TeamMembersFromJson(data io.Reader) []*TeamMember {
decoder := json.NewDecoder(data)
var o []*TeamMember
err := decoder.Decode(&o)
if err == nil {
return o
} else {
return nil
}
}
func (o *TeamMember) IsValid() *AppError {
if len(o.TeamId) != 26 {
return NewLocAppError("TeamMember.IsValid", "model.team_member.is_valid.team_id.app_error", nil, "")
}
if len(o.UserId) != 26 {
return NewLocAppError("TeamMember.IsValid", "model.team_member.is_valid.user_id.app_error", nil, "")
}
for _, role := range strings.Split(o.Roles, " ") {
if !(role == "" || role == ROLE_TEAM_ADMIN) {
return NewLocAppError("TeamMember.IsValid", "model.team_member.is_valid.role.app_error", nil, "role="+role)
}
}
return nil
}

43
model/team_member_test.go Обычный файл
Просмотреть файл

@@ -0,0 +1,43 @@
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
import (
"strings"
"testing"
)
func TestTeamMemberJson(t *testing.T) {
o := TeamMember{TeamId: NewId(), UserId: NewId()}
json := o.ToJson()
ro := TeamMemberFromJson(strings.NewReader(json))
if o.TeamId != ro.TeamId {
t.Fatal("Ids do not match")
}
}
func TestTeamMemberIsValid(t *testing.T) {
o := TeamMember{}
if err := o.IsValid(); err == nil {
t.Fatal("should be invalid")
}
o.TeamId = NewId()
if err := o.IsValid(); err == nil {
t.Fatal("should be invalid")
}
o.UserId = NewId()
o.Roles = "blahblah"
if err := o.IsValid(); err == nil {
t.Fatal("should be invalid")
}
o.Roles = ""
if err := o.IsValid(); err != nil {
t.Fatal(err)
}
}

Просмотреть файл

@@ -15,7 +15,6 @@ import (
) )
const ( const (
ROLE_TEAM_ADMIN = "admin"
ROLE_SYSTEM_ADMIN = "system_admin" ROLE_SYSTEM_ADMIN = "system_admin"
USER_AWAY_TIMEOUT = 5 * 60 * 1000 // 5 minutes USER_AWAY_TIMEOUT = 5 * 60 * 1000 // 5 minutes
USER_OFFLINE_TIMEOUT = 1 * 60 * 1000 // 1 minute USER_OFFLINE_TIMEOUT = 1 * 60 * 1000 // 1 minute
@@ -28,6 +27,7 @@ const (
DEFAULT_LOCALE = "en" DEFAULT_LOCALE = "en"
USER_AUTH_SERVICE_EMAIL = "email" USER_AUTH_SERVICE_EMAIL = "email"
USER_AUTH_SERVICE_USERNAME = "username" USER_AUTH_SERVICE_USERNAME = "username"
MIN_PASSWORD_LENGTH = 5
) )
type User struct { type User struct {
@@ -35,7 +35,6 @@ type User struct {
CreateAt int64 `json:"create_at,omitempty"` CreateAt int64 `json:"create_at,omitempty"`
UpdateAt int64 `json:"update_at,omitempty"` UpdateAt int64 `json:"update_at,omitempty"`
DeleteAt int64 `json:"delete_at"` DeleteAt int64 `json:"delete_at"`
TeamId string `json:"team_id"`
Username string `json:"username"` Username string `json:"username"`
Password string `json:"password,omitempty"` Password string `json:"password,omitempty"`
AuthData string `json:"auth_data,omitempty"` AuthData string `json:"auth_data,omitempty"`
@@ -76,10 +75,6 @@ func (u *User) IsValid() *AppError {
return NewLocAppError("User.IsValid", "model.user.is_valid.update_at.app_error", nil, "user_id="+u.Id) return NewLocAppError("User.IsValid", "model.user.is_valid.update_at.app_error", nil, "user_id="+u.Id)
} }
if len(u.TeamId) != 26 {
return NewLocAppError("User.IsValid", "model.user.is_valid.team_id.app_error", nil, "")
}
if !IsValidUsername(u.Username) { if !IsValidUsername(u.Username) {
return NewLocAppError("User.IsValid", "model.user.is_valid.username.app_error", nil, "user_id="+u.Id) return NewLocAppError("User.IsValid", "model.user.is_valid.username.app_error", nil, "user_id="+u.Id)
} }
@@ -228,6 +223,7 @@ func (u *User) IsAway() bool {
func (u *User) Sanitize(options map[string]bool) { func (u *User) Sanitize(options map[string]bool) {
u.Password = "" u.Password = ""
u.AuthData = "" u.AuthData = ""
u.MfaSecret = ""
if len(options) != 0 && !options["email"] { if len(options) != 0 && !options["email"] {
u.Email = "" u.Email = ""
@@ -246,6 +242,8 @@ func (u *User) ClearNonProfileFields() {
u.Password = "" u.Password = ""
u.AuthData = "" u.AuthData = ""
u.AuthService = "" u.AuthService = ""
u.MfaActive = false
u.MfaSecret = ""
u.EmailVerified = false u.EmailVerified = false
u.LastPingAt = 0 u.LastPingAt = 0
u.AllowMarketing = false u.AllowMarketing = false
@@ -301,7 +299,7 @@ func (u *User) GetDisplayName() string {
} }
} }
func IsValidRoles(userRoles string) bool { func IsValidUserRoles(userRoles string) bool {
roles := strings.Split(userRoles, " ") roles := strings.Split(userRoles, " ")
@@ -319,10 +317,6 @@ func isValidRole(role string) bool {
return true return true
} }
if role == ROLE_TEAM_ADMIN {
return true
}
if role == ROLE_SYSTEM_ADMIN { if role == ROLE_SYSTEM_ADMIN {
return true return true
} }
@@ -351,8 +345,8 @@ func IsInRole(userRoles string, inRole string) bool {
return false return false
} }
func (u *User) IsSSOUser() bool { func (u *User) IsOAuthUser() bool {
if len(u.AuthData) != 0 && len(u.AuthService) != 0 && u.AuthService != USER_AUTH_SERVICE_LDAP { if u.AuthService == USER_AUTH_SERVICE_GITLAB {
return true return true
} }
return false return false

Просмотреть файл

@@ -63,11 +63,6 @@ func TestUserIsValid(t *testing.T) {
t.Fatal() t.Fatal()
} }
user.TeamId = NewId()
if err := user.IsValid(); err == nil {
t.Fatal()
}
user.Username = NewId() + "^hello#" user.Username = NewId() + "^hello#"
if err := user.IsValid(); err == nil { if err := user.IsValid(); err == nil {
t.Fatal() t.Fatal()
@@ -195,11 +190,11 @@ func TestCleanUsername(t *testing.T) {
func TestRoles(t *testing.T) { func TestRoles(t *testing.T) {
if !IsValidRoles("admin") { if IsValidUserRoles("admin") {
t.Fatal() t.Fatal()
} }
if IsValidRoles("junk") { if IsValidUserRoles("junk") {
t.Fatal() t.Fatal()
} }

Просмотреть файл

@@ -41,12 +41,10 @@ func (er *AppError) Error() string {
} }
func (er *AppError) Translate(T goi18n.TranslateFunc) { func (er *AppError) Translate(T goi18n.TranslateFunc) {
if len(er.Message) == 0 { if er.params == nil {
if er.params == nil { er.Message = T(er.Id)
er.Message = T(er.Id) } else {
} else { er.Message = T(er.Id, er.params)
er.Message = T(er.Id, er.params)
}
} }
} }
@@ -83,6 +81,7 @@ func NewLocAppError(where string, id string, params map[string]interface{}, deta
ap := &AppError{} ap := &AppError{}
ap.Id = id ap.Id = id
ap.params = params ap.params = params
ap.Message = id
ap.Where = where ap.Where = where
ap.DetailedError = details ap.DetailedError = details
ap.StatusCode = 500 ap.StatusCode = 500

Просмотреть файл

@@ -13,6 +13,7 @@ import (
// It should be maitained in chronological order with most current // It should be maitained in chronological order with most current
// release at the front of the list. // release at the front of the list.
var versions = []string{ var versions = []string{
"3.0.0",
"2.2.0", "2.2.0",
"2.1.0", "2.1.0",
"2.0.0", "2.0.0",

Просмотреть файл

@@ -28,17 +28,6 @@ func NewSqlAuditStore(sqlStore *SqlStore) AuditStore {
} }
func (s SqlAuditStore) UpgradeSchemaIfNeeded() { func (s SqlAuditStore) UpgradeSchemaIfNeeded() {
// ADDED for 2.2 REMOVE for 2.6
extraLength := s.GetMaxLengthOfColumnIfExists("Audits", "ExtraInfo")
if len(extraLength) > 0 && extraLength != "1024" {
s.AlterColumnTypeIfExists("Audits", "ExtraInfo", "VARCHAR(1024)", "VARCHAR(1024)")
}
// ADDED for 2.2 REMOVE for 2.6
actionLength := s.GetMaxLengthOfColumnIfExists("Audits", "Action")
if len(actionLength) > 0 && actionLength != "512" {
s.AlterColumnTypeIfExists("Audits", "Action", "VARCHAR(512)", "VARCHAR(512)")
}
} }
func (s SqlAuditStore) CreateIndexesIfNotExists() { func (s SqlAuditStore) CreateIndexesIfNotExists() {

Просмотреть файл

@@ -95,6 +95,7 @@ func (s SqlChannelStore) SaveDirectChannel(directchannel *model.Channel, member1
if transaction, err := s.GetMaster().Begin(); err != nil { if transaction, err := s.GetMaster().Begin(); err != nil {
result.Err = model.NewLocAppError("SqlChannelStore.SaveDirectChannel", "store.sql_channel.save_direct_channel.open_transaction.app_error", nil, err.Error()) result.Err = model.NewLocAppError("SqlChannelStore.SaveDirectChannel", "store.sql_channel.save_direct_channel.open_transaction.app_error", nil, err.Error())
} else { } else {
directchannel.TeamId = ""
channelResult := s.saveChannelT(transaction, directchannel) channelResult := s.saveChannelT(transaction, directchannel)
if channelResult.Err != nil { if channelResult.Err != nil {
@@ -330,7 +331,7 @@ func (s SqlChannelStore) GetChannels(teamId string, userId string) StoreChannel
result := StoreResult{} result := StoreResult{}
var data []channelWithMember var data []channelWithMember
_, err := s.GetReplica().Select(&data, "SELECT * FROM Channels, ChannelMembers WHERE Id = ChannelId AND TeamId = :TeamId AND UserId = :UserId AND DeleteAt = 0 ORDER BY DisplayName", map[string]interface{}{"TeamId": teamId, "UserId": userId}) _, err := s.GetReplica().Select(&data, "SELECT * FROM Channels, ChannelMembers WHERE Id = ChannelId AND UserId = :UserId AND DeleteAt = 0 AND (TeamId = :TeamId OR TeamId = '') ORDER BY DisplayName", map[string]interface{}{"TeamId": teamId, "UserId": userId})
if err != nil { if err != nil {
result.Err = model.NewLocAppError("SqlChannelStore.GetChannels", "store.sql_channel.get_channels.get.app_error", nil, "teamId="+teamId+", userId="+userId+", err="+err.Error()) result.Err = model.NewLocAppError("SqlChannelStore.GetChannels", "store.sql_channel.get_channels.get.app_error", nil, "teamId="+teamId+", userId="+userId+", err="+err.Error())
@@ -411,7 +412,7 @@ func (s SqlChannelStore) GetChannelCounts(teamId string, userId string) StoreCha
result := StoreResult{} result := StoreResult{}
var data []channelIdWithCountAndUpdateAt var data []channelIdWithCountAndUpdateAt
_, err := s.GetReplica().Select(&data, "SELECT Id, TotalMsgCount, UpdateAt FROM Channels WHERE Id IN (SELECT ChannelId FROM ChannelMembers WHERE UserId = :UserId) AND TeamId = :TeamId AND DeleteAt = 0 ORDER BY DisplayName", map[string]interface{}{"TeamId": teamId, "UserId": userId}) _, err := s.GetReplica().Select(&data, "SELECT Id, TotalMsgCount, UpdateAt FROM Channels WHERE Id IN (SELECT ChannelId FROM ChannelMembers WHERE UserId = :UserId) AND (TeamId = :TeamId OR TeamId = '') AND DeleteAt = 0 ORDER BY DisplayName", map[string]interface{}{"TeamId": teamId, "UserId": userId})
if err != nil { if err != nil {
result.Err = model.NewLocAppError("SqlChannelStore.GetChannelCounts", "store.sql_channel.get_channel_counts.get.app_error", nil, "teamId="+teamId+", userId="+userId+", err="+err.Error()) result.Err = model.NewLocAppError("SqlChannelStore.GetChannelCounts", "store.sql_channel.get_channel_counts.get.app_error", nil, "teamId="+teamId+", userId="+userId+", err="+err.Error())
@@ -441,7 +442,7 @@ func (s SqlChannelStore) GetByName(teamId string, name string) StoreChannel {
channel := model.Channel{} channel := model.Channel{}
if err := s.GetReplica().SelectOne(&channel, "SELECT * FROM Channels WHERE TeamId = :TeamId AND Name= :Name AND DeleteAt = 0", map[string]interface{}{"TeamId": teamId, "Name": name}); err != nil { if err := s.GetReplica().SelectOne(&channel, "SELECT * FROM Channels WHERE (TeamId = :TeamId OR TeamId = '') AND Name = :Name AND DeleteAt = 0", map[string]interface{}{"TeamId": teamId, "Name": name}); err != nil {
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
result.Err = model.NewLocAppError("SqlChannelStore.GetByName", MISSING_CHANNEL_ERROR, nil, "teamId="+teamId+", "+"name="+name+", "+err.Error()) result.Err = model.NewLocAppError("SqlChannelStore.GetByName", MISSING_CHANNEL_ERROR, nil, "teamId="+teamId+", "+"name="+name+", "+err.Error())
} else { } else {
@@ -719,6 +720,37 @@ func (s SqlChannelStore) PermanentDeleteMembersByUser(userId string) StoreChanne
return storeChannel return storeChannel
} }
func (s SqlChannelStore) CheckPermissionsToNoTeam(channelId string, userId string) StoreChannel {
storeChannel := make(StoreChannel)
go func() {
result := StoreResult{}
count, err := s.GetReplica().SelectInt(
`SELECT
COUNT(0)
FROM
Channels,
ChannelMembers
WHERE
Channels.Id = ChannelMembers.ChannelId
AND Channels.DeleteAt = 0
AND ChannelMembers.ChannelId = :ChannelId
AND ChannelMembers.UserId = :UserId`,
map[string]interface{}{"ChannelId": channelId, "UserId": userId})
if err != nil {
result.Err = model.NewLocAppError("SqlChannelStore.CheckPermissionsTo", "store.sql_channel.check_permissions.app_error", nil, "channel_id="+channelId+", user_id="+userId+", "+err.Error())
} else {
result.Data = count
}
storeChannel <- result
close(storeChannel)
}()
return storeChannel
}
func (s SqlChannelStore) CheckPermissionsTo(teamId string, channelId string, userId string) StoreChannel { func (s SqlChannelStore) CheckPermissionsTo(teamId string, channelId string, userId string) StoreChannel {
storeChannel := make(StoreChannel) storeChannel := make(StoreChannel)
@@ -733,7 +765,7 @@ func (s SqlChannelStore) CheckPermissionsTo(teamId string, channelId string, use
ChannelMembers ChannelMembers
WHERE WHERE
Channels.Id = ChannelMembers.ChannelId Channels.Id = ChannelMembers.ChannelId
AND Channels.TeamId = :TeamId AND (Channels.TeamId = :TeamId OR Channels.TeamId = '')
AND Channels.DeleteAt = 0 AND Channels.DeleteAt = 0
AND ChannelMembers.ChannelId = :ChannelId AND ChannelMembers.ChannelId = :ChannelId
AND ChannelMembers.UserId = :UserId`, AND ChannelMembers.UserId = :UserId`,
@@ -765,7 +797,7 @@ func (s SqlChannelStore) CheckPermissionsToByName(teamId string, channelName str
ChannelMembers ChannelMembers
WHERE WHERE
Channels.Id = ChannelMembers.ChannelId Channels.Id = ChannelMembers.ChannelId
AND Channels.TeamId = :TeamId AND (Channels.TeamId = :TeamId OR Channels.TeamId = '')
AND Channels.Name = :Name AND Channels.Name = :Name
AND Channels.DeleteAt = 0 AND Channels.DeleteAt = 0
AND ChannelMembers.UserId = :UserId`, AND ChannelMembers.UserId = :UserId`,

Просмотреть файл

@@ -67,17 +67,17 @@ func TestChannelStoreSaveDirectChannel(t *testing.T) {
o1.Name = "a" + model.NewId() + "b" o1.Name = "a" + model.NewId() + "b"
o1.Type = model.CHANNEL_DIRECT o1.Type = model.CHANNEL_DIRECT
u1 := model.User{} u1 := &model.User{}
u1.TeamId = model.NewId()
u1.Email = model.NewId() u1.Email = model.NewId()
u1.Nickname = model.NewId() u1.Nickname = model.NewId()
Must(store.User().Save(&u1)) Must(store.User().Save(u1))
Must(store.Team().SaveMember(&model.TeamMember{TeamId: model.NewId(), UserId: u1.Id}))
u2 := model.User{} u2 := &model.User{}
u2.TeamId = model.NewId()
u2.Email = model.NewId() u2.Email = model.NewId()
u2.Nickname = model.NewId() u2.Nickname = model.NewId()
Must(store.User().Save(&u2)) Must(store.User().Save(u2))
Must(store.Team().SaveMember(&model.TeamMember{TeamId: model.NewId(), UserId: u2.Id}))
m1 := model.ChannelMember{} m1 := model.ChannelMember{}
m1.ChannelId = o1.Id m1.ChannelId = o1.Id
@@ -163,17 +163,17 @@ func TestChannelStoreGet(t *testing.T) {
t.Fatal("Missing id should have failed") t.Fatal("Missing id should have failed")
} }
u1 := model.User{} u1 := &model.User{}
u1.TeamId = model.NewId()
u1.Email = model.NewId() u1.Email = model.NewId()
u1.Nickname = model.NewId() u1.Nickname = model.NewId()
Must(store.User().Save(&u1)) Must(store.User().Save(u1))
Must(store.Team().SaveMember(&model.TeamMember{TeamId: model.NewId(), UserId: u1.Id}))
u2 := model.User{} u2 := model.User{}
u2.TeamId = model.NewId()
u2.Email = model.NewId() u2.Email = model.NewId()
u2.Nickname = model.NewId() u2.Nickname = model.NewId()
Must(store.User().Save(&u2)) Must(store.User().Save(&u2))
Must(store.Team().SaveMember(&model.TeamMember{TeamId: model.NewId(), UserId: u2.Id}))
o2 := model.Channel{} o2 := model.Channel{}
o2.TeamId = model.NewId() o2.TeamId = model.NewId()
@@ -309,16 +309,16 @@ func TestChannelMemberStore(t *testing.T) {
t1 := c1t1.ExtraUpdateAt t1 := c1t1.ExtraUpdateAt
u1 := model.User{} u1 := model.User{}
u1.TeamId = model.NewId()
u1.Email = model.NewId() u1.Email = model.NewId()
u1.Nickname = model.NewId() u1.Nickname = model.NewId()
Must(store.User().Save(&u1)) Must(store.User().Save(&u1))
Must(store.Team().SaveMember(&model.TeamMember{TeamId: model.NewId(), UserId: u1.Id}))
u2 := model.User{} u2 := model.User{}
u2.TeamId = model.NewId()
u2.Email = model.NewId() u2.Email = model.NewId()
u2.Nickname = model.NewId() u2.Nickname = model.NewId()
Must(store.User().Save(&u2)) Must(store.User().Save(&u2))
Must(store.Team().SaveMember(&model.TeamMember{TeamId: model.NewId(), UserId: u2.Id}))
o1 := model.ChannelMember{} o1 := model.ChannelMember{}
o1.ChannelId = c1.Id o1.ChannelId = c1.Id
@@ -405,16 +405,16 @@ func TestChannelDeleteMemberStore(t *testing.T) {
t1 := c1t1.ExtraUpdateAt t1 := c1t1.ExtraUpdateAt
u1 := model.User{} u1 := model.User{}
u1.TeamId = model.NewId()
u1.Email = model.NewId() u1.Email = model.NewId()
u1.Nickname = model.NewId() u1.Nickname = model.NewId()
Must(store.User().Save(&u1)) Must(store.User().Save(&u1))
Must(store.Team().SaveMember(&model.TeamMember{TeamId: model.NewId(), UserId: u1.Id}))
u2 := model.User{} u2 := model.User{}
u2.TeamId = model.NewId()
u2.Email = model.NewId() u2.Email = model.NewId()
u2.Nickname = model.NewId() u2.Nickname = model.NewId()
Must(store.User().Save(&u2)) Must(store.User().Save(&u2))
Must(store.Team().SaveMember(&model.TeamMember{TeamId: model.NewId(), UserId: u2.Id}))
o1 := model.ChannelMember{} o1 := model.ChannelMember{}
o1.ChannelId = c1.Id o1.ChannelId = c1.Id
@@ -469,6 +469,11 @@ func TestChannelStorePermissionsTo(t *testing.T) {
t.Fatal("should have permissions") t.Fatal("should have permissions")
} }
count = (<-store.Channel().CheckPermissionsToNoTeam(o1.Id, m1.UserId)).Data.(int64)
if count != 1 {
t.Fatal("should have permissions")
}
count = (<-store.Channel().CheckPermissionsTo("junk", o1.Id, m1.UserId)).Data.(int64) count = (<-store.Channel().CheckPermissionsTo("junk", o1.Id, m1.UserId)).Data.(int64)
if count != 0 { if count != 0 {
t.Fatal("shouldn't have permissions") t.Fatal("shouldn't have permissions")
@@ -479,11 +484,21 @@ func TestChannelStorePermissionsTo(t *testing.T) {
t.Fatal("shouldn't have permissions") t.Fatal("shouldn't have permissions")
} }
count = (<-store.Channel().CheckPermissionsToNoTeam("junk", m1.UserId)).Data.(int64)
if count != 0 {
t.Fatal("shouldn't have permissions")
}
count = (<-store.Channel().CheckPermissionsTo(o1.TeamId, o1.Id, "junk")).Data.(int64) count = (<-store.Channel().CheckPermissionsTo(o1.TeamId, o1.Id, "junk")).Data.(int64)
if count != 0 { if count != 0 {
t.Fatal("shouldn't have permissions") t.Fatal("shouldn't have permissions")
} }
count = (<-store.Channel().CheckPermissionsToNoTeam(o1.Id, "junk")).Data.(int64)
if count != 0 {
t.Fatal("shouldn't have permissions")
}
channelId := (<-store.Channel().CheckPermissionsToByName(o1.TeamId, o1.Name, m1.UserId)).Data.(string) channelId := (<-store.Channel().CheckPermissionsToByName(o1.TeamId, o1.Name, m1.UserId)).Data.(string)
if channelId != o1.Id { if channelId != o1.Id {
t.Fatal("should have permissions") t.Fatal("should have permissions")
@@ -786,12 +801,12 @@ func TestGetMemberCount(t *testing.T) {
t.Logf("c1.Id = %v", c1.Id) t.Logf("c1.Id = %v", c1.Id)
u1 := model.User{ u1 := &model.User{
TeamId: teamId,
Email: model.NewId(), Email: model.NewId(),
DeleteAt: 0, DeleteAt: 0,
} }
Must(store.User().Save(&u1)) Must(store.User().Save(u1))
Must(store.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u1.Id}))
m1 := model.ChannelMember{ m1 := model.ChannelMember{
ChannelId: c1.Id, ChannelId: c1.Id,
@@ -807,11 +822,11 @@ func TestGetMemberCount(t *testing.T) {
} }
u2 := model.User{ u2 := model.User{
TeamId: teamId,
Email: model.NewId(), Email: model.NewId(),
DeleteAt: 0, DeleteAt: 0,
} }
Must(store.User().Save(&u2)) Must(store.User().Save(&u2))
Must(store.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u2.Id}))
m2 := model.ChannelMember{ m2 := model.ChannelMember{
ChannelId: c1.Id, ChannelId: c1.Id,
@@ -828,11 +843,11 @@ func TestGetMemberCount(t *testing.T) {
// make sure members of other channels aren't counted // make sure members of other channels aren't counted
u3 := model.User{ u3 := model.User{
TeamId: teamId,
Email: model.NewId(), Email: model.NewId(),
DeleteAt: 0, DeleteAt: 0,
} }
Must(store.User().Save(&u3)) Must(store.User().Save(&u3))
Must(store.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u3.Id}))
m3 := model.ChannelMember{ m3 := model.ChannelMember{
ChannelId: c2.Id, ChannelId: c2.Id,
@@ -848,12 +863,12 @@ func TestGetMemberCount(t *testing.T) {
} }
// make sure inactive users aren't counted // make sure inactive users aren't counted
u4 := model.User{ u4 := &model.User{
TeamId: teamId,
Email: model.NewId(), Email: model.NewId(),
DeleteAt: 10000, DeleteAt: 10000,
} }
Must(store.User().Save(&u4)) Must(store.User().Save(u4))
Must(store.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u4.Id}))
m4 := model.ChannelMember{ m4 := model.ChannelMember{
ChannelId: c1.Id, ChannelId: c1.Id,
@@ -892,12 +907,12 @@ func TestUpdateExtrasByUser(t *testing.T) {
t.Logf("c1.Id = %v", c1.Id) t.Logf("c1.Id = %v", c1.Id)
u1 := model.User{ u1 := &model.User{
TeamId: teamId,
Email: model.NewId(), Email: model.NewId(),
DeleteAt: 0, DeleteAt: 0,
} }
Must(store.User().Save(&u1)) Must(store.User().Save(u1))
Must(store.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u1.Id}))
m1 := model.ChannelMember{ m1 := model.ChannelMember{
ChannelId: c1.Id, ChannelId: c1.Id,
@@ -907,7 +922,7 @@ func TestUpdateExtrasByUser(t *testing.T) {
Must(store.Channel().SaveMember(&m1)) Must(store.Channel().SaveMember(&m1))
u1.DeleteAt = model.GetMillis() u1.DeleteAt = model.GetMillis()
Must(store.User().Update(&u1, true)) Must(store.User().Update(u1, true))
if result := <-store.Channel().ExtraUpdateByUser(u1.Id, u1.DeleteAt); result.Err != nil { if result := <-store.Channel().ExtraUpdateByUser(u1.Id, u1.DeleteAt); result.Err != nil {
t.Fatal("failed to update extras by user: %v", result.Err) t.Fatal("failed to update extras by user: %v", result.Err)
@@ -920,7 +935,7 @@ func TestUpdateExtrasByUser(t *testing.T) {
} }
u1.DeleteAt = 0 u1.DeleteAt = 0
Must(store.User().Update(&u1, true)) Must(store.User().Update(u1, true))
if result := <-store.Channel().ExtraUpdateByUser(u1.Id, u1.DeleteAt); result.Err != nil { if result := <-store.Channel().ExtraUpdateByUser(u1.Id, u1.DeleteAt); result.Err != nil {
t.Fatal("failed to update extras by user: %v", result.Err) t.Fatal("failed to update extras by user: %v", result.Err)

Просмотреть файл

@@ -16,6 +16,7 @@ func TestCommandStoreSave(t *testing.T) {
o1.Method = model.COMMAND_METHOD_POST o1.Method = model.COMMAND_METHOD_POST
o1.TeamId = model.NewId() o1.TeamId = model.NewId()
o1.URL = "http://nowhere.com/" o1.URL = "http://nowhere.com/"
o1.Trigger = "trigger"
if err := (<-store.Command().Save(&o1)).Err; err != nil { if err := (<-store.Command().Save(&o1)).Err; err != nil {
t.Fatal("couldn't save item", err) t.Fatal("couldn't save item", err)
@@ -34,6 +35,7 @@ func TestCommandStoreGet(t *testing.T) {
o1.Method = model.COMMAND_METHOD_POST o1.Method = model.COMMAND_METHOD_POST
o1.TeamId = model.NewId() o1.TeamId = model.NewId()
o1.URL = "http://nowhere.com/" o1.URL = "http://nowhere.com/"
o1.Trigger = "trigger"
o1 = (<-store.Command().Save(o1)).Data.(*model.Command) o1 = (<-store.Command().Save(o1)).Data.(*model.Command)
@@ -58,6 +60,7 @@ func TestCommandStoreGetByTeam(t *testing.T) {
o1.Method = model.COMMAND_METHOD_POST o1.Method = model.COMMAND_METHOD_POST
o1.TeamId = model.NewId() o1.TeamId = model.NewId()
o1.URL = "http://nowhere.com/" o1.URL = "http://nowhere.com/"
o1.Trigger = "trigger"
o1 = (<-store.Command().Save(o1)).Data.(*model.Command) o1 = (<-store.Command().Save(o1)).Data.(*model.Command)
@@ -86,6 +89,7 @@ func TestCommandStoreDelete(t *testing.T) {
o1.Method = model.COMMAND_METHOD_POST o1.Method = model.COMMAND_METHOD_POST
o1.TeamId = model.NewId() o1.TeamId = model.NewId()
o1.URL = "http://nowhere.com/" o1.URL = "http://nowhere.com/"
o1.Trigger = "trigger"
o1 = (<-store.Command().Save(o1)).Data.(*model.Command) o1 = (<-store.Command().Save(o1)).Data.(*model.Command)
@@ -115,6 +119,7 @@ func TestCommandStoreDeleteByUser(t *testing.T) {
o1.Method = model.COMMAND_METHOD_POST o1.Method = model.COMMAND_METHOD_POST
o1.TeamId = model.NewId() o1.TeamId = model.NewId()
o1.URL = "http://nowhere.com/" o1.URL = "http://nowhere.com/"
o1.Trigger = "trigger"
o1 = (<-store.Command().Save(o1)).Data.(*model.Command) o1 = (<-store.Command().Save(o1)).Data.(*model.Command)
@@ -144,6 +149,7 @@ func TestCommandStoreUpdate(t *testing.T) {
o1.Method = model.COMMAND_METHOD_POST o1.Method = model.COMMAND_METHOD_POST
o1.TeamId = model.NewId() o1.TeamId = model.NewId()
o1.URL = "http://nowhere.com/" o1.URL = "http://nowhere.com/"
o1.Trigger = "trigger"
o1 = (<-store.Command().Save(o1)).Data.(*model.Command) o1 = (<-store.Command().Save(o1)).Data.(*model.Command)
@@ -162,6 +168,7 @@ func TestCommandCount(t *testing.T) {
o1.Method = model.COMMAND_METHOD_POST o1.Method = model.COMMAND_METHOD_POST
o1.TeamId = model.NewId() o1.TeamId = model.NewId()
o1.URL = "http://nowhere.com/" o1.URL = "http://nowhere.com/"
o1.Trigger = "trigger"
o1 = (<-store.Command().Save(o1)).Data.(*model.Command) o1 = (<-store.Command().Save(o1)).Data.(*model.Command)

Просмотреть файл

@@ -58,16 +58,16 @@ func TestComplianceExport(t *testing.T) {
t1 = Must(store.Team().Save(t1)).(*model.Team) t1 = Must(store.Team().Save(t1)).(*model.Team)
u1 := &model.User{} u1 := &model.User{}
u1.TeamId = t1.Id
u1.Email = model.NewId() u1.Email = model.NewId()
u1.Username = model.NewId() u1.Username = model.NewId()
u1 = Must(store.User().Save(u1)).(*model.User) u1 = Must(store.User().Save(u1)).(*model.User)
Must(store.Team().SaveMember(&model.TeamMember{TeamId: t1.Id, UserId: u1.Id}))
u2 := &model.User{} u2 := &model.User{}
u2.TeamId = t1.Id
u2.Email = model.NewId() u2.Email = model.NewId()
u2.Username = model.NewId() u2.Username = model.NewId()
u2 = Must(store.User().Save(u2)).(*model.User) u2 = Must(store.User().Save(u2)).(*model.User)
Must(store.Team().SaveMember(&model.TeamMember{TeamId: t1.Id, UserId: u2.Id}))
c1 := &model.Channel{} c1 := &model.Channel{}
c1.TeamId = t1.Id c1.TeamId = t1.Id

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше