summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/context.go10
-rw-r--r--api/post.go11
-rw-r--r--api/post_test.go14
-rw-r--r--web/react/components/post_info.jsx3
-rw-r--r--web/react/components/search_bar.jsx2
-rw-r--r--web/sass-files/sass/partials/_headers.scss7
-rw-r--r--web/sass-files/sass/partials/_modal.scss2
-rw-r--r--web/sass-files/sass/partials/_responsive.scss9
-rw-r--r--web/sass-files/sass/partials/_search.scss13
9 files changed, 51 insertions, 20 deletions
diff --git a/api/context.go b/api/context.go
index bea0fbeff..054e42e2e 100644
--- a/api/context.go
+++ b/api/context.go
@@ -265,6 +265,16 @@ func (c *Context) IsSystemAdmin() bool {
return false
}
+func (c *Context) IsTeamAdmin(userId string) bool {
+ if uresult := <-Srv.Store.User().Get(userId); uresult.Err != nil {
+ c.Err = uresult.Err
+ return false
+ } else {
+ user := uresult.Data.(*model.User)
+ return strings.Contains(c.Session.Roles, model.ROLE_ADMIN) && user.TeamId == c.Session.TeamId
+ }
+}
+
func (c *Context) RemoveSessionCookie(w http.ResponseWriter) {
sessionCache.Remove(c.Session.Id)
diff --git a/api/post.go b/api/post.go
index 02f997166..efca2f570 100644
--- a/api/post.go
+++ b/api/post.go
@@ -634,16 +634,17 @@ func deletePost(c *Context, w http.ResponseWriter, r *http.Request) {
cchan := Srv.Store.Channel().CheckPermissionsTo(c.Session.TeamId, channelId, c.Session.UserId)
pchan := Srv.Store.Post().Get(postId)
- if !c.HasPermissionsToChannel(cchan, "deletePost") {
- return
- }
-
if result := <-pchan; result.Err != nil {
c.Err = result.Err
return
} else {
+
post := result.Data.(*model.PostList).Posts[postId]
+ if !c.HasPermissionsToChannel(cchan, "deletePost") && !c.IsTeamAdmin(post.UserId){
+ return
+ }
+
if post == nil {
c.SetInvalidParam("deletePost", "postId")
return
@@ -655,7 +656,7 @@ func deletePost(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if post.UserId != c.Session.UserId {
+ if post.UserId != c.Session.UserId && !strings.Contains(c.Session.Roles,model.ROLE_ADMIN) {
c.Err = model.NewAppError("deletePost", "You do not have the appropriate permissions", "")
c.Err.StatusCode = http.StatusForbidden
return
diff --git a/api/post_test.go b/api/post_test.go
index 970307759..5009ff54d 100644
--- a/api/post_test.go
+++ b/api/post_test.go
@@ -483,6 +483,10 @@ func TestDeletePosts(t *testing.T) {
team := &model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN}
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
+ userAdmin := &model.User{TeamId: team.Id, Email: team.Email, FullName: "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() + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user1.Id))
@@ -521,8 +525,16 @@ func TestDeletePosts(t *testing.T) {
r2 := Client.Must(Client.GetPosts(channel1.Id, 0, 10, "")).Data.(*model.PostList)
if len(r2.Posts) != 4 {
- t.Fatal("should have returned 5 items")
+ t.Fatal("should have returned 4 items")
}
+
+ time.Sleep(10 * time.Millisecond)
+ post4 := &model.Post{ChannelId: channel1.Id, Message: "a" + model.NewId() + "a"}
+ post4 = Client.Must(Client.CreatePost(post4)).Data.(*model.Post)
+
+ Client.LoginByEmail(team.Domain, userAdmin.Email, "pwd")
+
+ Client.Must(Client.DeletePost(channel1.Id, post4.Id))
}
func TestEmailMention(t *testing.T) {
diff --git a/web/react/components/post_info.jsx b/web/react/components/post_info.jsx
index cf01747f0..48efa95ba 100644
--- a/web/react/components/post_info.jsx
+++ b/web/react/components/post_info.jsx
@@ -11,6 +11,7 @@ module.exports = React.createClass({
render: function() {
var post = this.props.post;
var isOwner = UserStore.getCurrentId() == post.user_id;
+ var isAdmin = UserStore.getCurrentUser().roles.indexOf("admin") > -1
var type = "Post"
if (post.root_id.length > 0) {
@@ -36,7 +37,7 @@ module.exports = React.createClass({
<ul className="dropdown-menu" role="menu">
{ isOwner ? <li role="presentation"><a href="#" role="menuitem" data-toggle="modal" data-target="#edit_post" data-title={type} data-message={post.message} data-postid={post.id} data-channelid={post.channel_id} data-comments={type === "Post" ? this.props.commentCount : 0}>Edit</a></li>
: "" }
- { isOwner ? <li role="presentation"><a href="#" role="menuitem" data-toggle="modal" data-target="#delete_post" data-title={type} data-postid={post.id} data-channelid={post.channel_id} data-comments={type === "Post" ? this.props.commentCount : 0}>Delete</a></li>
+ { isOwner || isAdmin ? <li role="presentation"><a href="#" role="menuitem" data-toggle="modal" data-target="#delete_post" data-title={type} data-postid={post.id} data-channelid={post.channel_id} data-comments={type === "Post" ? this.props.commentCount : 0}>Delete</a></li>
: "" }
{ this.props.allowReply === "true" ? <li role="presentation"><a className="reply-link theme" href="#" onClick={this.props.handleCommentClick}>Reply</a></li>
: "" }
diff --git a/web/react/components/search_bar.jsx b/web/react/components/search_bar.jsx
index ab7e99d60..f21f0cd58 100644
--- a/web/react/components/search_bar.jsx
+++ b/web/react/components/search_bar.jsx
@@ -92,7 +92,7 @@ module.exports = React.createClass({
render: function() {
return (
<div>
- <div className="sidebar__collapse" onClick={this.handleClose}></div>
+ <div className="sidebar__collapse" onClick={this.handleClose}>Cancel</div>
<span className="glyphicon glyphicon-search sidebar__search-icon"></span>
<form role="form" className="search__form relative-div" onSubmit={this.handleSubmit}>
<input
diff --git a/web/sass-files/sass/partials/_headers.scss b/web/sass-files/sass/partials/_headers.scss
index d876d8b37..c2740891a 100644
--- a/web/sass-files/sass/partials/_headers.scss
+++ b/web/sass-files/sass/partials/_headers.scss
@@ -157,6 +157,7 @@
font-size: 14px;
line-height: 50px;
#member_popover {
+ margin-right: 5px;
width: 45px;
color: #999;
cursor: pointer;
@@ -232,12 +233,16 @@
vertical-align: top;
display: inline-block;
width: 15px;
- margin: 9px 3px 3px 0;
+ margin: 9px 4px 3px 0;
&:hover {
svg {
fill: #888;
}
}
+ a {
+ height: 100%;
+ display: block;
+ }
svg {
vertical-align: top;
margin-top: 8px;
diff --git a/web/sass-files/sass/partials/_modal.scss b/web/sass-files/sass/partials/_modal.scss
index 1b0338884..f359037c5 100644
--- a/web/sass-files/sass/partials/_modal.scss
+++ b/web/sass-files/sass/partials/_modal.scss
@@ -155,7 +155,7 @@
position: relative;
max-width: 90%;
min-height: 50px;
- min-width: 280px;
+ min-width: 320px;
@include border-radius(3px);
display: table;
margin: 0 auto;
diff --git a/web/sass-files/sass/partials/_responsive.scss b/web/sass-files/sass/partials/_responsive.scss
index 1f9643175..a33d69378 100644
--- a/web/sass-files/sass/partials/_responsive.scss
+++ b/web/sass-files/sass/partials/_responsive.scss
@@ -432,13 +432,16 @@
color: #fff;
.search__form {
border: none;
- padding: 0 10px 0 30px;
+ padding: 0 60px 0 25px;
.form-control {
+ line-height: 31px;
background: none;
color: #fff;
- border-bottom: 1px solid rgba(#fff, 0.7);
border-radius: 0;
- padding: 0 10px 0 23px;
+ padding: 0 10px 0;
+ @include input-placeholder {
+ color: rgba(#fff, 0.6);
+ }
}
::-webkit-input-placeholder {
color: #fff;
diff --git a/web/sass-files/sass/partials/_search.scss b/web/sass-files/sass/partials/_search.scss
index 8d51d00c0..d4a4da243 100644
--- a/web/sass-files/sass/partials/_search.scss
+++ b/web/sass-files/sass/partials/_search.scss
@@ -2,21 +2,20 @@
padding: 8px 8px 8px 0;
}
.sidebar__collapse {
- width: 20px;
- height: 30px;
+ width: auto;
+ height: auto;
position: absolute;
- top: 10px;
- left: 6px;
+ top: 17px;
+ right: 15px;
cursor: pointer;
- background: url("../images/arrow-left.png") center no-repeat;
- @include background-size(10px 15px);
z-index: 5;
display: none;
}
.sidebar__search-icon {
position: absolute;
- left: 40px;
+ left: 15px;
top: 18px;
+ font-size: 16px;
@include opacity(0.8);
display: none;
}