diff options
author | Jack <jackdeng@gmail.com> | 2015-09-22 08:16:51 -0700 |
---|---|---|
committer | Jack <jackdeng@gmail.com> | 2015-09-22 08:16:51 -0700 |
commit | 602bed85f2b32733f73e2edddb542fa36baac462 (patch) | |
tree | 06a6ee9b609a9122bc2f0e6f6e6300f9ba79a3aa /api | |
parent | a31868336f97a91bfd5a7e91e99a9b294d131f90 (diff) | |
parent | f439c82d7c885b4c530ba9da0a41b17910743b55 (diff) | |
download | chat-602bed85f2b32733f73e2edddb542fa36baac462.tar.gz chat-602bed85f2b32733f73e2edddb542fa36baac462.tar.bz2 chat-602bed85f2b32733f73e2edddb542fa36baac462.zip |
fix conflict
Diffstat (limited to 'api')
-rw-r--r-- | api/admin.go | 46 | ||||
-rw-r--r-- | api/admin_test.go | 82 | ||||
-rw-r--r-- | api/channel_test.go | 4 | ||||
-rw-r--r-- | api/command.go | 6 | ||||
-rw-r--r-- | api/context.go | 2 | ||||
-rw-r--r-- | api/file.go | 97 |
6 files changed, 218 insertions, 19 deletions
diff --git a/api/admin.go b/api/admin.go index 6d7a9028f..646597755 100644 --- a/api/admin.go +++ b/api/admin.go @@ -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)) +} diff --git a/api/admin_test.go b/api/admin_test.go index e67077c55..e1778b5ac 100644 --- a/api/admin_test.go +++ b/api/admin_test.go @@ -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() + } } } diff --git a/api/channel_test.go b/api/channel_test.go index 7e9267192..14bfe1cf7 100644 --- a/api/channel_test.go +++ b/api/channel_test.go @@ -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) } } diff --git a/api/command.go b/api/command.go index be1d3229b..bc55f206b 100644 --- a/api/command.go +++ b/api/command.go @@ -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 diff --git a/api/context.go b/api/context.go index 5925c817f..02716bb33 100644 --- a/api/context.go +++ b/api/context.go @@ -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 { diff --git a/api/file.go b/api/file.go index f249b3d9e..3602b5ed4 100644 --- a/api/file.go +++ b/api/file.go @@ -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 |