Этот коммит содержится в:
Jack
2015-09-22 08:16:51 -07:00
родитель a31868336f f439c82d7c
Коммит 602bed85f2
110 изменённых файлов: 9065 добавлений и 645 удалений

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

@@ -7,6 +7,7 @@ import (
"bufio"
"net/http"
"os"
"strings"
l4g "code.google.com/p/log4go"
"github.com/gorilla/mux"
@@ -20,6 +21,8 @@ func InitAdmin(r *mux.Router) {
sr := r.PathPrefix("/admin").Subrouter()
sr.Handle("/logs", ApiUserRequired(getLogs)).Methods("GET")
sr.Handle("/config", ApiUserRequired(getConfig)).Methods("GET")
sr.Handle("/save_config", ApiUserRequired(saveConfig)).Methods("POST")
sr.Handle("/client_props", ApiAppHandler(getClientProperties)).Methods("GET")
}
@@ -33,7 +36,7 @@ func getLogs(c *Context, w http.ResponseWriter, r *http.Request) {
if utils.Cfg.LogSettings.FileEnable {
file, err := os.Open(utils.Cfg.LogSettings.FileLocation)
file, err := os.Open(utils.GetLogFileLocation(utils.Cfg.LogSettings.FileLocation))
if err != nil {
c.Err = model.NewAppError("getLogs", "Error reading log file", err.Error())
}
@@ -54,3 +57,44 @@ func getLogs(c *Context, w http.ResponseWriter, r *http.Request) {
func getClientProperties(c *Context, w http.ResponseWriter, r *http.Request) {
w.Write([]byte(model.MapToJson(utils.ClientProperties)))
}
func getConfig(c *Context, w http.ResponseWriter, r *http.Request) {
if !c.HasSystemAdminPermissions("getConfig") {
return
}
json := utils.Cfg.ToJson()
cfg := model.ConfigFromJson(strings.NewReader(json))
json = cfg.ToJson()
w.Write([]byte(json))
}
func saveConfig(c *Context, w http.ResponseWriter, r *http.Request) {
if !c.HasSystemAdminPermissions("getConfig") {
return
}
cfg := model.ConfigFromJson(r.Body)
if cfg == nil {
c.SetInvalidParam("saveConfig", "config")
return
}
if len(cfg.ServiceSettings.Port) == 0 {
c.SetInvalidParam("saveConfig", "config")
return
}
if cfg.TeamSettings.MaxUsersPerTeam == 0 {
c.SetInvalidParam("saveConfig", "config")
return
}
// TODO run some cleanup validators
utils.SaveConfig(utils.CfgFileName, cfg)
utils.LoadConfig(utils.CfgFileName)
json := utils.Cfg.ToJson()
w.Write([]byte(json))
}

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

@@ -8,6 +8,7 @@ import (
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/store"
"github.com/mattermost/platform/utils"
)
func TestGetLogs(t *testing.T) {
@@ -20,6 +21,12 @@ func TestGetLogs(t *testing.T) {
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")
}
c := &Context{}
c.RequestId = model.NewId()
c.IpAddress = "cmd_line"
@@ -37,8 +44,81 @@ func TestGetLogs(t *testing.T) {
func TestGetClientProperties(t *testing.T) {
Setup()
if _, err := Client.GetClientProperties(); err != nil {
if result, err := Client.GetClientProperties(); err != nil {
t.Fatal(err)
} else {
props := result.Data.(map[string]string)
if len(props["Version"]) == 0 {
t.Fatal()
}
}
}
func TestGetConfig(t *testing.T) {
Setup()
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() + "corey@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")
if _, err := Client.GetConfig(); err == nil {
t.Fatal("Shouldn't have permissions")
}
c := &Context{}
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)
} else {
cfg := result.Data.(*model.Config)
if len(cfg.ServiceSettings.SiteName) == 0 {
t.Fatal()
}
}
}
func TestSaveConfig(t *testing.T) {
Setup()
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() + "corey@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")
if _, err := Client.SaveConfig(utils.Cfg); err == nil {
t.Fatal("Shouldn't have permissions")
}
c := &Context{}
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.SaveConfig(utils.Cfg); err != nil {
t.Fatal(err)
} else {
cfg := result.Data.(*model.Config)
if len(cfg.ServiceSettings.SiteName) == 0 {
t.Fatal()
}
}
}

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

@@ -57,7 +57,7 @@ func TestCreateChannel(t *testing.T) {
rchannel.Data.(*model.Channel).Id = ""
if _, err := Client.CreateChannel(rchannel.Data.(*model.Channel)); err != nil {
if err.Message != "A channel with that handle already exists" {
if err.Message != "A channel with that URL already exists" {
t.Fatal(err)
}
}
@@ -68,7 +68,7 @@ func TestCreateChannel(t *testing.T) {
Client.DeleteChannel(savedId)
if _, err := Client.CreateChannel(rchannel.Data.(*model.Channel)); err != nil {
if err.Message != "A channel with that handle was previously created" {
if err.Message != "A channel with that URL was previously created" {
t.Fatal(err)
}
}

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

@@ -341,7 +341,7 @@ func loadTestSetupCommand(c *Context, command *model.Command) bool {
}
}
} else {
client.MockSession(c.Session.Id)
client.MockSession(c.Session.Token)
CreateTestEnviromentInTeam(
client,
c.Session.TeamId,
@@ -406,7 +406,7 @@ func loadTestChannelsCommand(c *Context, command *model.Command) bool {
channelsr = utils.Range{20, 30}
}
client := model.NewClient(c.GetSiteURL())
client.MockSession(c.Session.Id)
client.MockSession(c.Session.Token)
channelCreator := NewAutoChannelCreator(client, c.Session.TeamId)
channelCreator.Fuzzy = doFuzz
channelCreator.CreateTestChannels(channelsr)
@@ -458,7 +458,7 @@ func loadTestPostsCommand(c *Context, command *model.Command) bool {
}
client := model.NewClient(c.GetSiteURL())
client.MockSession(c.Session.Id)
client.MockSession(c.Session.Token)
testPoster := NewAutoPostCreator(client, command.ChannelId)
testPoster.Fuzzy = doFuzz
testPoster.Users = usernames

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

@@ -125,7 +125,7 @@ func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
c.setSiteURL(protocol + "://" + r.Host)
w.Header().Set(model.HEADER_REQUEST_ID, c.RequestId)
w.Header().Set(model.HEADER_VERSION_ID, utils.Cfg.ServiceSettings.Version+fmt.Sprintf(".%v", utils.CfgLastModified))
w.Header().Set(model.HEADER_VERSION_ID, fmt.Sprintf("%v.%v", model.CurrentVersion, utils.CfgLastModified))
// Instruct the browser not to display us in an iframe for anti-clickjacking
if !h.isApi {

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

@@ -5,6 +5,7 @@ package api
import (
"bytes"
"code.google.com/p/graphics-go/graphics"
l4g "code.google.com/p/log4go"
"fmt"
"github.com/goamz/goamz/aws"
@@ -13,6 +14,7 @@ import (
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/utils"
"github.com/nfnt/resize"
"github.com/rwcarlsen/goexif/exif"
_ "golang.org/x/image/bmp"
"image"
"image/color"
@@ -21,6 +23,7 @@ import (
"image/jpeg"
"io"
"io/ioutil"
"math"
"mime"
"net/http"
"net/url"
@@ -31,6 +34,27 @@ import (
"time"
)
const (
/*
EXIF Image Orientations
1 2 3 4 5 6 7 8
888888 888888 88 88 8888888888 88 88 8888888888
88 88 88 88 88 88 88 88 88 88 88 88
8888 8888 8888 8888 88 8888888888 8888888888 88
88 88 88 88
88 88 888888 888888
*/
Upright = 1
UprightMirrored = 2
UpsideDown = 3
UpsideDownMirrored = 4
RotatedCWMirrored = 5
RotatedCCW = 6
RotatedCCWMirrored = 7
RotatedCW = 8
)
var fileInfoCache *utils.Cache = utils.NewLru(1000)
func InitFile(r *mux.Router) {
@@ -144,25 +168,59 @@ func fireAndForgetHandleImages(filenames []string, fileData [][]byte, teamId, ch
return
}
// Decode image config
imgConfig, _, err := image.DecodeConfig(bytes.NewReader(fileData[i]))
if err != nil {
l4g.Error("Unable to decode image config channelId=%v userId=%v filename=%v err=%v", channelId, userId, filename, err)
return
width := img.Bounds().Dx()
height := img.Bounds().Dy()
// Get the image's orientation and ignore any errors since not all images will have orientation data
orientation, _ := getImageOrientation(fileData[i])
// Create a temporary image that will be manipulated and then used to make the thumbnail and preview image
var temp *image.RGBA
switch orientation {
case Upright, UprightMirrored, UpsideDown, UpsideDownMirrored:
temp = image.NewRGBA(img.Bounds())
case RotatedCCW, RotatedCCWMirrored, RotatedCW, RotatedCWMirrored:
bounds := img.Bounds()
temp = image.NewRGBA(image.Rect(bounds.Min.Y, bounds.Min.X, bounds.Max.Y, bounds.Max.X))
width, height = height, width
}
// Remove transparency due to JPEG's lack of support of it
temp := image.NewRGBA(img.Bounds())
// Draw a white background since JPEGs lack transparency
draw.Draw(temp, temp.Bounds(), image.NewUniform(color.White), image.Point{}, draw.Src)
draw.Draw(temp, temp.Bounds(), img, img.Bounds().Min, draw.Over)
// Copy the original image onto the temporary one while rotating it as necessary
switch orientation {
case UpsideDown, UpsideDownMirrored:
// rotate 180 degrees
err := graphics.Rotate(temp, img, &graphics.RotateOptions{Angle: math.Pi})
if err != nil {
l4g.Error("Unable to rotate image")
}
case RotatedCW, RotatedCWMirrored:
// rotate 90 degrees CCW
graphics.Rotate(temp, img, &graphics.RotateOptions{Angle: 3 * math.Pi / 2})
if err != nil {
l4g.Error("Unable to rotate image")
}
case RotatedCCW, RotatedCCWMirrored:
// rotate 90 degrees CW
graphics.Rotate(temp, img, &graphics.RotateOptions{Angle: math.Pi / 2})
if err != nil {
l4g.Error("Unable to rotate image")
}
case Upright, UprightMirrored:
draw.Draw(temp, temp.Bounds(), img, img.Bounds().Min, draw.Over)
}
img = temp
// Create thumbnail
go func() {
thumbWidth := float64(utils.Cfg.ImageSettings.ThumbnailWidth)
thumbHeight := float64(utils.Cfg.ImageSettings.ThumbnailHeight)
imgWidth := float64(imgConfig.Width)
imgHeight := float64(imgConfig.Height)
imgWidth := float64(width)
imgHeight := float64(height)
var thumbnail image.Image
if imgHeight < thumbHeight && imgWidth < thumbWidth {
@@ -189,7 +247,7 @@ func fireAndForgetHandleImages(filenames []string, fileData [][]byte, teamId, ch
// Create preview
go func() {
var preview image.Image
if imgConfig.Width > int(utils.Cfg.ImageSettings.PreviewWidth) {
if width > int(utils.Cfg.ImageSettings.PreviewWidth) {
preview = resize.Resize(utils.Cfg.ImageSettings.PreviewWidth, utils.Cfg.ImageSettings.PreviewHeight, img, resize.Lanczos3)
} else {
preview = img
@@ -213,6 +271,23 @@ func fireAndForgetHandleImages(filenames []string, fileData [][]byte, teamId, ch
}()
}
func getImageOrientation(imageData []byte) (int, error) {
if exifData, err := exif.Decode(bytes.NewReader(imageData)); err != nil {
return Upright, err
} else {
if tag, err := exifData.Get("Orientation"); err != nil {
return Upright, err
} else {
orientation, err := tag.Int(0)
if err != nil {
return Upright, err
} else {
return orientation, nil
}
}
}
}
type ImageGetResult struct {
Error error
ImageData []byte