summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCorey Hulen <corey@hulen.com>2016-05-06 11:28:22 -0700
committerChristopher Speller <crspeller@gmail.com>2016-05-06 14:28:22 -0400
commit6c75662b824491a20a757a5eec59556a866374b5 (patch)
tree2f531a680aaa45bc915d51764eb846bc1b80fa68
parent4f799b980fd457e5dc97d2427a154576d7a5eded (diff)
downloadchat-6c75662b824491a20a757a5eec59556a866374b5.tar.gz
chat-6c75662b824491a20a757a5eec59556a866374b5.tar.bz2
chat-6c75662b824491a20a757a5eec59556a866374b5.zip
PLT-2697 Fixing team admins (#2900)
* PLT-2697 Fixing team admins * Fixing eslint error * Fixing loc issues * Fixing func * Fixing func
-rw-r--r--api/apitestlib.go2
-rw-r--r--api/context.go6
-rw-r--r--api/team_test.go4
-rw-r--r--api/user.go95
-rw-r--r--api/user_test.go132
-rw-r--r--config/config.json2
-rw-r--r--i18n/en.json12
-rw-r--r--i18n/es.json4
-rw-r--r--i18n/fr.json4
-rw-r--r--i18n/ja.json4
-rw-r--r--i18n/pt.json4
-rw-r--r--mattermost.go2
-rw-r--r--model/client.go4
-rw-r--r--model/team_member.go42
-rw-r--r--web/web_test.go2
-rw-r--r--webapp/client/client.jsx3
-rw-r--r--webapp/components/admin_console/team_users.jsx39
-rw-r--r--webapp/components/admin_console/user_item.jsx51
-rw-r--r--webapp/components/audit_table.jsx2
-rw-r--r--webapp/components/channel_header.jsx3
-rw-r--r--webapp/components/navbar.jsx3
-rw-r--r--webapp/components/navbar_dropdown.jsx5
-rw-r--r--webapp/components/post_info.jsx4
-rw-r--r--webapp/components/rhs_comment.jsx4
-rw-r--r--webapp/components/rhs_root_post.jsx3
-rw-r--r--webapp/components/sidebar_right_menu.jsx5
-rw-r--r--webapp/components/team_members_dropdown.jsx104
-rw-r--r--webapp/stores/team_store.jsx17
-rw-r--r--webapp/stores/user_store.jsx16
-rw-r--r--webapp/tests/client_user.test.jsx4
30 files changed, 441 insertions, 141 deletions
diff --git a/api/apitestlib.go b/api/apitestlib.go
index a7c2a9406..6372ea6b1 100644
--- a/api/apitestlib.go
+++ b/api/apitestlib.go
@@ -89,7 +89,7 @@ func (me *TestHelper) InitSystemAdmin() *TestHelper {
c := &Context{}
c.RequestId = model.NewId()
c.IpAddress = "cmd_line"
- UpdateRoles(c, me.SystemAdminUser, model.ROLE_SYSTEM_ADMIN)
+ UpdateUserRoles(c, me.SystemAdminUser, model.ROLE_SYSTEM_ADMIN)
me.SystemAdminUser.Password = "Password1"
me.LoginSystemAdmin()
me.SystemAdminChannel = me.CreateChannel(me.SystemAdminClient, me.SystemAdminTeam)
diff --git a/api/context.go b/api/context.go
index 03d0046be..67b04c391 100644
--- a/api/context.go
+++ b/api/context.go
@@ -372,12 +372,12 @@ func (c *Context) IsTeamAdmin() bool {
return true
}
- team := c.Session.GetTeamByTeamId(c.TeamId)
- if team == nil {
+ teamMember := c.Session.GetTeamByTeamId(c.TeamId)
+ if teamMember == nil {
return false
}
- return model.IsInRole(team.Roles, model.ROLE_TEAM_ADMIN)
+ return teamMember.IsTeamAdmin()
}
func (c *Context) RemoveSessionCookie(w http.ResponseWriter, r *http.Request) {
diff --git a/api/team_test.go b/api/team_test.go
index a58260fd2..30952b4d8 100644
--- a/api/team_test.go
+++ b/api/team_test.go
@@ -252,7 +252,7 @@ func TestGetAllTeams(t *testing.T) {
c := &Context{}
c.RequestId = model.NewId()
c.IpAddress = "cmd_line"
- UpdateRoles(c, user, model.ROLE_SYSTEM_ADMIN)
+ UpdateUserRoles(c, user, model.ROLE_SYSTEM_ADMIN)
Client.Login(user.Email, "pwd")
Client.SetTeamId(team.Id)
@@ -301,7 +301,7 @@ func TestGetAllTeamListings(t *testing.T) {
c := &Context{}
c.RequestId = model.NewId()
c.IpAddress = "cmd_line"
- UpdateRoles(c, user, model.ROLE_SYSTEM_ADMIN)
+ UpdateUserRoles(c, user, model.ROLE_SYSTEM_ADMIN)
Client.Login(user.Email, "pwd")
Client.SetTeamId(team.Id)
diff --git a/api/user.go b/api/user.go
index de4242f24..60162d8f1 100644
--- a/api/user.go
+++ b/api/user.go
@@ -1372,16 +1372,23 @@ func updateRoles(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
+ team_id := props["team_id"]
+ if !(len(user_id) == 26 || len(user_id) == 0) {
+ c.SetInvalidParam("updateRoles", "team_id")
+ return
+ }
+
new_roles := props["new_roles"]
- if !model.IsValidUserRoles(new_roles) {
+ if !(model.IsValidUserRoles(new_roles) || model.IsValidTeamRoles(new_roles)) {
c.SetInvalidParam("updateRoles", "new_roles")
return
}
// If you are not the system admin then you can only demote yourself
if !c.IsSystemAdmin() && user_id != c.Session.UserId {
- c.Err = model.NewLocAppError("updateRoles", "api.user.update_roles.system_admin_set.app_error", nil, "")
+ c.Err = model.NewLocAppError("updateRoles", "api.user.update_roles.system_admin_needed.app_error", nil, "")
c.Err.StatusCode = http.StatusForbidden
+ return
}
// Only another system admin can add the system admin role
@@ -1399,36 +1406,78 @@ func updateRoles(c *Context, w http.ResponseWriter, r *http.Request) {
user = result.Data.(*model.User)
}
- ruser := UpdateRoles(c, user, new_roles)
- if c.Err != nil {
- return
- }
+ // if the team role has changed then lets update team members
+ if model.IsValidTeamRoles(new_roles) && len(team_id) > 0 {
+
+ var members []*model.TeamMember
+ if result := <-Srv.Store.Team().GetTeamsForUser(user_id); result.Err != nil {
+ c.Err = result.Err
+ return
+ } else {
+ members = result.Data.([]*model.TeamMember)
+ }
+
+ var member *model.TeamMember
+ for _, m := range members {
+ if m.TeamId == team_id {
+ member = m
+ }
+ }
- uchan := Srv.Store.Session().UpdateRoles(user.Id, new_roles)
- gchan := Srv.Store.Session().GetSessions(user.Id)
+ if member == nil {
+ c.SetInvalidParam("updateRoles", "team_id")
+ return
+ }
- if result := <-uchan; result.Err != nil {
- // soft error since the user roles were still updated
- l4g.Error(result.Err)
+ if !c.IsSystemAdmin() {
+ currentUserTeamMember := c.Session.GetTeamByTeamId(team_id)
+
+ // Only the system admin can modify other team
+ if currentUserTeamMember == nil {
+ c.Err = model.NewLocAppError("updateRoles", "api.user.update_roles.system_admin_needed.app_error", nil, "")
+ c.Err.StatusCode = http.StatusForbidden
+ return
+ }
+
+ // Only another team admin can make a team admin
+ if !currentUserTeamMember.IsTeamAdmin() && model.IsInRole(new_roles, model.ROLE_TEAM_ADMIN) {
+ c.Err = model.NewLocAppError("updateRoles", "api.user.update_roles.team_admin_needed.app_error", nil, "")
+ c.Err.StatusCode = http.StatusForbidden
+ return
+ }
+ }
+
+ member.Roles = new_roles
+
+ if result := <-Srv.Store.Team().UpdateMember(member); result.Err != nil {
+ c.Err = result.Err
+ return
+ }
}
- if result := <-gchan; result.Err != nil {
- // soft error since the user roles were still updated
- l4g.Error(result.Err)
- } else {
- sessions := result.Data.([]*model.Session)
- for _, s := range sessions {
- sessionCache.Remove(s.Token)
+ // If the users role has changed then lets update the user
+ if model.IsValidUserRoles(new_roles) {
+ UpdateUserRoles(c, user, new_roles)
+ if c.Err != nil {
+ return
+ }
+
+ uchan := Srv.Store.Session().UpdateRoles(user.Id, new_roles)
+
+ if result := <-uchan; result.Err != nil {
+ // soft error since the user roles were still updated
+ l4g.Error(result.Err)
}
}
- options := utils.Cfg.GetSanitizeOptions()
- options["passwordupdate"] = false
- ruser.Sanitize(options)
- w.Write([]byte(ruser.ToJson()))
+ RemoveAllSessionsForUserId(user_id)
+
+ data := make(map[string]string)
+ data["user_id"] = user_id
+ w.Write([]byte(model.MapToJson(data)))
}
-func UpdateRoles(c *Context, user *model.User, roles string) *model.User {
+func UpdateUserRoles(c *Context, user *model.User, roles string) *model.User {
user.Roles = roles
diff --git a/api/user_test.go b/api/user_test.go
index 629f7d257..1a3b36d4b 100644
--- a/api/user_test.go
+++ b/api/user_test.go
@@ -366,7 +366,7 @@ func TestGetUser(t *testing.T) {
c := &Context{}
c.RequestId = model.NewId()
c.IpAddress = "cmd_line"
- UpdateRoles(c, ruser.Data.(*model.User), model.ROLE_SYSTEM_ADMIN)
+ UpdateUserRoles(c, ruser.Data.(*model.User), model.ROLE_SYSTEM_ADMIN)
Client.Login(user.Email, "pwd")
@@ -791,7 +791,6 @@ func TestUserUpdateRoles(t *testing.T) {
Client.Login(user.Email, "pwd")
data["user_id"] = "junk"
- data["new_roles"] = "admin"
if _, err := Client.UpdateUserRoles(data); err == nil {
t.Fatal("Should have errored, bad id")
@@ -804,12 +803,141 @@ func TestUserUpdateRoles(t *testing.T) {
}
data["user_id"] = user2.Id
+ data["new_roles"] = "junk"
if _, err := Client.UpdateUserRoles(data); err == nil {
t.Fatal("Should have errored, bad role")
}
}
+func TestUserUpdateRolesMoreCases(t *testing.T) {
+ th := Setup().InitSystemAdmin().InitBasic()
+
+ data := make(map[string]string)
+
+ // invalid team Id
+ data["user_id"] = th.BasicUser2.Id
+ data["new_roles"] = ""
+ data["team_id"] = model.NewId()
+ if _, err := th.BasicClient.UpdateUserRoles(data); err == nil {
+ t.Fatal("Should have errored")
+ }
+
+ // user 1 is trying to change user 2
+ data["user_id"] = th.BasicUser2.Id
+ data["new_roles"] = ""
+ data["team_id"] = th.BasicTeam.Id
+ if _, err := th.BasicClient.UpdateUserRoles(data); err == nil {
+ t.Fatal("Should have errored, you can only demote yourself")
+ }
+
+ // user 1 is trying to promote user 2
+ data["user_id"] = th.BasicUser2.Id
+ data["new_roles"] = model.ROLE_TEAM_ADMIN
+ data["team_id"] = th.BasicTeam.Id
+ if _, err := th.BasicClient.UpdateUserRoles(data); err == nil {
+ t.Fatal("Should have errored, you can only demote yourself")
+ }
+
+ // user 1 is trying to promote user 2
+ data["user_id"] = th.BasicUser2.Id
+ data["new_roles"] = model.ROLE_SYSTEM_ADMIN
+ data["team_id"] = th.BasicTeam.Id
+ if _, err := th.BasicClient.UpdateUserRoles(data); err == nil {
+ t.Fatal("Should have errored, you can only demote yourself")
+ }
+
+ // user 1 is trying to promote himself
+ data["user_id"] = th.BasicUser.Id
+ data["new_roles"] = model.ROLE_TEAM_ADMIN
+ data["team_id"] = th.BasicTeam.Id
+ if _, err := th.BasicClient.UpdateUserRoles(data); err == nil {
+ t.Fatal("Should have errored, you cannot elevate your permissions")
+ }
+
+ // user 1 is trying to promote himself
+ data["user_id"] = th.BasicUser.Id
+ data["new_roles"] = model.ROLE_SYSTEM_ADMIN
+ data["team_id"] = th.BasicTeam.Id
+ if _, err := th.BasicClient.UpdateUserRoles(data); err == nil {
+ t.Fatal("Should have errored, you cannot elevate your permissions")
+ }
+
+ th.LoginSystemAdmin()
+
+ // promote user to team admin
+ data["user_id"] = th.BasicUser.Id
+ data["new_roles"] = model.ROLE_TEAM_ADMIN
+ data["team_id"] = th.BasicTeam.Id
+ if _, err := th.SystemAdminClient.UpdateUserRoles(data); err != nil {
+ t.Fatal("Should have succeeded since they are system admin")
+ }
+
+ // demote team admin to basic member
+ data["user_id"] = th.BasicUser.Id
+ data["new_roles"] = ""
+ data["team_id"] = th.BasicTeam.Id
+ if _, err := th.SystemAdminClient.UpdateUserRoles(data); err != nil {
+ t.Fatal("Should have succeeded since they are system admin")
+ }
+
+ // re-promote user to team admin
+ data["user_id"] = th.BasicUser.Id
+ data["new_roles"] = model.ROLE_TEAM_ADMIN
+ data["team_id"] = th.BasicTeam.Id
+ if _, err := th.SystemAdminClient.UpdateUserRoles(data); err != nil {
+ t.Fatal("Should have succeeded since they are system admin")
+ }
+
+ // user 1 is promoting user 2 to team admin
+ data["user_id"] = th.BasicUser2.Id
+ data["new_roles"] = model.ROLE_TEAM_ADMIN
+ data["team_id"] = th.BasicTeam.Id
+ if _, err := th.BasicClient.UpdateUserRoles(data); err == nil {
+ t.Fatal("Should have succeeded since they are team admin")
+ }
+
+ // user 1 is trying to promote user 2 from team admin to system admin
+ data["user_id"] = th.BasicUser2.Id
+ data["new_roles"] = model.ROLE_SYSTEM_ADMIN
+ data["team_id"] = th.BasicTeam.Id
+ if _, err := th.BasicClient.UpdateUserRoles(data); err == nil {
+ t.Fatal("Should have errored, can only be system admin")
+ }
+
+ // user 1 is demoting user 2 to a regular member
+ data["user_id"] = th.BasicUser2.Id
+ data["new_roles"] = ""
+ data["team_id"] = th.BasicTeam.Id
+ if _, err := th.BasicClient.UpdateUserRoles(data); err == nil {
+ t.Fatal("Should have succeeded since they are team admin")
+ }
+
+ // user 1 is trying to demote system admin
+ data["user_id"] = th.SystemAdminUser.Id
+ data["new_roles"] = ""
+ data["team_id"] = th.BasicTeam.Id
+ if _, err := th.BasicClient.UpdateUserRoles(data); err == nil {
+ t.Fatal("Should have errored, can only be system admin")
+ }
+
+ // user 1 as team admin is demoting himself
+ data["user_id"] = th.BasicUser.Id
+ data["new_roles"] = ""
+ data["team_id"] = th.BasicTeam.Id
+ if _, err := th.BasicClient.UpdateUserRoles(data); err != nil {
+ t.Fatal("Should have succeeded")
+ }
+
+ // system admin demoting himself
+ data["user_id"] = th.SystemAdminUser.Id
+ data["new_roles"] = ""
+ data["team_id"] = ""
+ if _, err := th.SystemAdminClient.UpdateUserRoles(data); err != nil {
+ t.Fatal("Should have succeeded since they are system admin")
+ }
+}
+
func TestUserUpdateDeviceId(t *testing.T) {
th := Setup()
Client := th.CreateClient()
diff --git a/config/config.json b/config/config.json
index 45da5770b..7eff8ad37 100644
--- a/config/config.json
+++ b/config/config.json
@@ -156,4 +156,4 @@
"Directory": "./data/",
"EnableDaily": false
}
-}
+} \ No newline at end of file
diff --git a/i18n/en.json b/i18n/en.json
index 9013dbea9..b888beba0 100644
--- a/i18n/en.json
+++ b/i18n/en.json
@@ -1704,14 +1704,18 @@
"translation": "You do not have the appropriate permissions"
},
{
- "id": "api.user.update_roles.system_admin_mod.app_error",
- "translation": "The system admin role can only by modified by another system admin"
- },
- {
"id": "api.user.update_roles.system_admin_set.app_error",
"translation": "The system admin role can only be set by another system admin"
},
{
+ "id": "api.user.update_roles.system_admin_needed.app_error",
+ "translation": "The system admin role is needed for this action"
+ },
+ {
+ "id": "api.user.update_roles.team_admin_needed.app_error",
+ "translation": "The team admin role is needed for this action"
+ },
+ {
"id": "api.user.upload_profile_user.array.app_error",
"translation": "Empty array under 'image' in request"
},
diff --git a/i18n/es.json b/i18n/es.json
index 54438b879..08d14fd7e 100644
--- a/i18n/es.json
+++ b/i18n/es.json
@@ -1704,10 +1704,6 @@
"translation": "No tienes los permisos apropiados"
},
{
- "id": "api.user.update_roles.system_admin_mod.app_error",
- "translation": "El rol de administrador de sistema sólo puede ser modificado por otro administrador de sistema"
- },
- {
"id": "api.user.update_roles.system_admin_set.app_error",
"translation": "El rol de adminsitrador de sistema sólo puede ser asignado por otro administrador de sistema"
},
diff --git a/i18n/fr.json b/i18n/fr.json
index d2290685c..bddbf85ce 100644
--- a/i18n/fr.json
+++ b/i18n/fr.json
@@ -1564,10 +1564,6 @@
"translation": "Vous n'avez pas les permissions appropriées"
},
{
- "id": "api.user.update_roles.system_admin_mod.app_error",
- "translation": "Le rôle d'administrateur système ne peut être modifié que par un autre administrateur système"
- },
- {
"id": "api.user.update_roles.system_admin_set.app_error",
"translation": "Le rôle d'administrateur système ne peut être donné que par un autre administrateur système"
},
diff --git a/i18n/ja.json b/i18n/ja.json
index 290fc74f7..7fbd65254 100644
--- a/i18n/ja.json
+++ b/i18n/ja.json
@@ -1676,10 +1676,6 @@
"translation": "あなたには必要な権限が付与されていません"
},
{
- "id": "api.user.update_roles.system_admin_mod.app_error",
- "translation": "システム管理者の役割は、他のシステム管理者だけが設定変更できます"
- },
- {
"id": "api.user.update_roles.system_admin_set.app_error",
"translation": "システム管理者の役割は、他のシステム管理者だけが設定できます"
},
diff --git a/i18n/pt.json b/i18n/pt.json
index f51513f48..573c75f19 100644
--- a/i18n/pt.json
+++ b/i18n/pt.json
@@ -1700,10 +1700,6 @@
"translation": "Você não tem a permissão apropriada"
},
{
- "id": "api.user.update_roles.system_admin_mod.app_error",
- "translation": "A função de administrador do sistema só pode ser modificado por outro administrador do sistema"
- },
- {
"id": "api.user.update_roles.system_admin_set.app_error",
"translation": "A função de administrador do sistema só pode ser definida por um outro administrador do sistema"
},
diff --git a/mattermost.go b/mattermost.go
index 172c42aa1..be9b08a95 100644
--- a/mattermost.go
+++ b/mattermost.go
@@ -721,7 +721,7 @@ func cmdAssignRole() {
}
if !user.IsInRole(flagRole) {
- api.UpdateRoles(c, user, flagRole)
+ api.UpdateUserRoles(c, user, flagRole)
}
os.Exit(0)
diff --git a/model/client.go b/model/client.go
index 54f143cfe..a74adcd7a 100644
--- a/model/client.go
+++ b/model/client.go
@@ -1023,7 +1023,7 @@ func (c *Client) UpdateUserRoles(data map[string]string) (*Result, *AppError) {
return nil, err
} else {
return &Result{r.Header.Get(HEADER_REQUEST_ID),
- r.Header.Get(HEADER_ETAG_SERVER), UserFromJson(r.Body)}, nil
+ r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil
}
}
@@ -1069,7 +1069,7 @@ func (c *Client) UpdateUserPassword(userId, currentPassword, newPassword string)
return nil, err
} else {
return &Result{r.Header.Get(HEADER_REQUEST_ID),
- r.Header.Get(HEADER_ETAG_SERVER), UserFromJson(r.Body)}, nil
+ r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil
}
}
diff --git a/model/team_member.go b/model/team_member.go
index 80ca9f2a3..ae687c109 100644
--- a/model/team_member.go
+++ b/model/team_member.go
@@ -58,6 +58,48 @@ func TeamMembersFromJson(data io.Reader) []*TeamMember {
}
}
+func IsValidTeamRoles(teamRoles string) bool {
+
+ roles := strings.Split(teamRoles, " ")
+
+ for _, r := range roles {
+ if !isValidTeamRole(r) {
+ return false
+ }
+ }
+
+ return true
+}
+
+func isValidTeamRole(role string) bool {
+ if role == "" {
+ return true
+ }
+
+ if role == ROLE_TEAM_ADMIN {
+ return true
+ }
+
+ return false
+}
+
+func IsInTeamRole(teamRoles string, inRole string) bool {
+ roles := strings.Split(teamRoles, " ")
+
+ for _, r := range roles {
+ if r == inRole {
+ return true
+ }
+
+ }
+
+ return false
+}
+
+func (o *TeamMember) IsTeamAdmin() bool {
+ return IsInTeamRole(o.Roles, ROLE_TEAM_ADMIN)
+}
+
func (o *TeamMember) IsValid() *AppError {
if len(o.TeamId) != 26 {
diff --git a/web/web_test.go b/web/web_test.go
index 7a0485215..d4d9a5f26 100644
--- a/web/web_test.go
+++ b/web/web_test.go
@@ -203,7 +203,7 @@ func TestIncomingWebhook(t *testing.T) {
c := &api.Context{}
c.RequestId = model.NewId()
c.IpAddress = "cmd_line"
- api.UpdateRoles(c, user, model.ROLE_SYSTEM_ADMIN)
+ api.UpdateUserRoles(c, user, model.ROLE_SYSTEM_ADMIN)
ApiClient.Login(user.Email, "pwd")
ApiClient.SetTeamId(team.Id)
diff --git a/webapp/client/client.jsx b/webapp/client/client.jsx
index 56eb4a137..d1e250e12 100644
--- a/webapp/client/client.jsx
+++ b/webapp/client/client.jsx
@@ -596,8 +596,9 @@ export default class Client {
end(this.handleResponse.bind(this, 'updateUserNotifyProps', success, error));
}
- updateRoles = (userId, newRoles, success, error) => {
+ updateRoles = (teamId, userId, newRoles, success, error) => {
var data = {
+ team_id: teamId,
user_id: userId,
new_roles: newRoles
};
diff --git a/webapp/components/admin_console/team_users.jsx b/webapp/components/admin_console/team_users.jsx
index 2b0e6af0a..e41747737 100644
--- a/webapp/components/admin_console/team_users.jsx
+++ b/webapp/components/admin_console/team_users.jsx
@@ -19,10 +19,12 @@ export default class UserList extends React.Component {
this.doPasswordReset = this.doPasswordReset.bind(this);
this.doPasswordResetDismiss = this.doPasswordResetDismiss.bind(this);
this.doPasswordResetSubmit = this.doPasswordResetSubmit.bind(this);
+ this.getTeamMemberForUser = this.getTeamMemberForUser.bind(this);
this.state = {
teamId: props.team.id,
users: null,
+ teamMembers: null,
serverError: null,
showPasswordModal: false,
user: null
@@ -38,6 +40,21 @@ export default class UserList extends React.Component {
}
getTeamProfiles(teamId) {
+ Client.getTeamMembers(
+ teamId,
+ (data) => {
+ this.setState({
+ teamMembers: data
+ });
+ },
+ (err) => {
+ this.setState({
+ teamMembers: null,
+ serverError: err.message
+ });
+ }
+ );
+
Client.getProfilesForTeam(
teamId,
(users) => {
@@ -110,6 +127,22 @@ export default class UserList extends React.Component {
});
}
+ getTeamMemberForUser(userId) {
+ if (this.state.teamMembers) {
+ for (const index in this.state.teamMembers) {
+ if (this.state.teamMembers.hasOwnProperty(index)) {
+ var teamMember = this.state.teamMembers[index];
+
+ if (teamMember.user_id === userId) {
+ return teamMember;
+ }
+ }
+ }
+ }
+
+ return null;
+ }
+
componentWillReceiveProps(newProps) {
this.getTeamProfiles(newProps.team.id);
}
@@ -120,7 +153,7 @@ export default class UserList extends React.Component {
serverError = <div className='form-group has-error'><label className='control-label'>{this.state.serverError}</label></div>;
}
- if (this.state.users == null) {
+ if (this.state.users == null || this.state.teamMembers == null) {
return (
<div className='wrapper--fixed'>
<h3>
@@ -139,10 +172,14 @@ export default class UserList extends React.Component {
}
var memberList = this.state.users.map((user) => {
+ var teamMember = this.getTeamMemberForUser(user.id);
+
return (
<UserItem
+ team={this.props.team}
key={'user_' + user.id}
user={user}
+ teamMember={teamMember}
refreshProfiles={this.getCurrentTeamProfiles}
doPasswordReset={this.doPasswordReset}
/>);
diff --git a/webapp/components/admin_console/user_item.jsx b/webapp/components/admin_console/user_item.jsx
index 660f75a41..ef6bd9f45 100644
--- a/webapp/components/admin_console/user_item.jsx
+++ b/webapp/components/admin_console/user_item.jsx
@@ -42,6 +42,7 @@ export default class UserItem extends React.Component {
this.handleDemote(this.props.user, '');
} else {
Client.updateRoles(
+ this.props.team.id,
this.props.user.id,
'',
() => {
@@ -85,6 +86,7 @@ export default class UserItem extends React.Component {
this.handleDemote(this.props.user, 'admin');
} else {
Client.updateRoles(
+ this.props.team.id,
this.props.user.id,
'admin',
() => {
@@ -101,6 +103,7 @@ export default class UserItem extends React.Component {
e.preventDefault();
Client.updateRoles(
+ this.props.team.id,
this.props.user.id,
'system_admin',
() => {
@@ -150,9 +153,12 @@ export default class UserItem extends React.Component {
handleDemoteSubmit() {
Client.updateRoles(
+ this.props.team.id,
this.props.user.id,
this.state.role,
() => {
+ this.props.refreshProfiles();
+
this.setState({
serverError: null,
showDemoteModal: false,
@@ -185,6 +191,7 @@ export default class UserItem extends React.Component {
);
}
+ const teamMember = this.props.teamMember;
const user = this.props.user;
let currentRoles = (
<FormattedMessage
@@ -192,32 +199,28 @@ export default class UserItem extends React.Component {
defaultMessage='Member'
/>
);
- if (user.roles.length > 0) {
- if (Utils.isSystemAdmin(user.roles)) {
- currentRoles = (
- <FormattedMessage
- id='admin.user_item.sysAdmin'
- defaultMessage='System Admin'
- />
- );
- } else if (Utils.isAdmin(user.roles)) {
- currentRoles = (
- <FormattedMessage
- id='admin.user_item.teamAdmin'
- defaultMessage='Team Admin'
- />
- );
- } else {
- currentRoles = user.roles.charAt(0).toUpperCase() + user.roles.slice(1);
- }
- }
- const email = user.email;
- let showMakeMember = user.roles === 'admin' || user.roles === 'system_admin';
+ if (teamMember.roles.length > 0 && Utils.isAdmin(teamMember.roles)) {
+ currentRoles = (
+ <FormattedMessage
+ id='team_members_dropdown.teamAdmin'
+ defaultMessage='Team Admin'
+ />
+ );
+ }
- //let showMakeAdmin = user.roles === '' || user.roles === 'system_admin';
- let showMakeAdmin = false;
+ if (user.roles.length > 0 && Utils.isSystemAdmin(user.roles)) {
+ currentRoles = (
+ <FormattedMessage
+ id='team_members_dropdown.systemAdmin'
+ defaultMessage='System Admin'
+ />
+ );
+ }
+ const email = user.email;
+ let showMakeMember = teamMember.roles === 'admin' || user.roles === 'system_admin';
+ let showMakeAdmin = teamMember.roles === '' && user.roles !== 'system_admin';
let showMakeSystemAdmin = user.roles === '' || user.roles === 'admin';
let showMakeActive = false;
let showMakeNotActive = user.roles !== 'system_admin';
@@ -521,7 +524,9 @@ export default class UserItem extends React.Component {
}
UserItem.propTypes = {
+ team: React.PropTypes.object.isRequired,
user: React.PropTypes.object.isRequired,
+ teamMember: React.PropTypes.object.isRequired,
refreshProfiles: React.PropTypes.func.isRequired,
doPasswordReset: React.PropTypes.func.isRequired
};
diff --git a/webapp/components/audit_table.jsx b/webapp/components/audit_table.jsx
index b1f155518..58b5b9af7 100644
--- a/webapp/components/audit_table.jsx
+++ b/webapp/components/audit_table.jsx
@@ -494,7 +494,7 @@ export function formatAuditInfo(audit, formatMessage) {
if (actingUserInfo[0] === 'session_user') {
const actingUser = UserStore.getProfile(actingUserInfo[1]);
const user = UserStore.getCurrentUser();
- if (user && actingUser && (Utils.isAdmin(user.roles) || Utils.isSystemAdmin(user.roles))) {
+ if (user && actingUser && (Utils.isSystemAdmin(user.roles))) {
auditDesc += formatMessage(holders.by, {username: actingUser.username});
} else if (user && actingUser) {
auditDesc += formatMessage(holders.byAdmin);
diff --git a/webapp/components/channel_header.jsx b/webapp/components/channel_header.jsx
index de6ee20c9..992244915 100644
--- a/webapp/components/channel_header.jsx
+++ b/webapp/components/channel_header.jsx
@@ -18,6 +18,7 @@ import ToggleModalButton from './toggle_modal_button.jsx';
import ChannelStore from 'stores/channel_store.jsx';
import UserStore from 'stores/user_store.jsx';
+import TeamStore from 'stores/team_store.jsx';
import SearchStore from 'stores/search_store.jsx';
import PreferenceStore from 'stores/preference_store.jsx';
@@ -181,7 +182,7 @@ export default class ChannelHeader extends React.Component {
);
let channelTitle = channel.display_name;
const currentId = this.state.currentUser.id;
- const isAdmin = Utils.isAdmin(this.state.memberChannel.roles) || Utils.isAdmin(this.state.currentUser.roles);
+ const isAdmin = Utils.isAdmin(this.state.memberChannel.roles) || TeamStore.isTeamAdminForCurrentTeam() || UserStore.isSystemAdminForCurrentUser();
const isDirect = (this.state.channel.type === 'D');
if (isDirect) {
diff --git a/webapp/components/navbar.jsx b/webapp/components/navbar.jsx
index 919a72d0a..21ca53649 100644
--- a/webapp/components/navbar.jsx
+++ b/webapp/components/navbar.jsx
@@ -452,7 +452,8 @@ export default class Navbar extends React.Component {
/>
</Popover>
);
- isAdmin = Utils.isAdmin(this.state.member.roles);
+
+ isAdmin = Utils.isAdmin(this.state.member.roles) || TeamStore.isTeamAdminForCurrentTeam() || UserStore.isSystemAdminForCurrentUser();
if (channel.type === 'O') {
channelTitle = channel.display_name;
diff --git a/webapp/components/navbar_dropdown.jsx b/webapp/components/navbar_dropdown.jsx
index 7004a0cf3..7f1cfce7c 100644
--- a/webapp/components/navbar_dropdown.jsx
+++ b/webapp/components/navbar_dropdown.jsx
@@ -7,6 +7,7 @@ import * as Utils from 'utils/utils.jsx';
import * as GlobalActions from 'action_creators/global_actions.jsx';
import TeamStore from 'stores/team_store.jsx';
+import UserStore from 'stores/user_store.jsx';
import AboutBuildModal from './about_build_modal.jsx';
import TeamMembersModal from './team_members_modal.jsx';
import ToggleModalButton from './toggle_modal_button.jsx';
@@ -79,8 +80,8 @@ export default class NavbarDropdown extends React.Component {
let integrationsLink = null;
if (currentUser != null) {
- isAdmin = Utils.isAdmin(currentUser.roles);
- isSystemAdmin = Utils.isSystemAdmin(currentUser.roles);
+ isAdmin = TeamStore.isTeamAdminForCurrentTeam() || UserStore.isSystemAdminForCurrentUser();
+ isSystemAdmin = UserStore.isSystemAdminForCurrentUser();
inviteLink = (
<li>
diff --git a/webapp/components/post_info.jsx b/webapp/components/post_info.jsx
index 3f81672e1..50b03c0be 100644
--- a/webapp/components/post_info.jsx
+++ b/webapp/components/post_info.jsx
@@ -5,6 +5,8 @@ import $ from 'jquery';
import * as Utils from 'utils/utils.jsx';
import TimeSince from './time_since.jsx';
import * as GlobalActions from 'action_creators/global_actions.jsx';
+import TeamStore from 'stores/team_store.jsx';
+import UserStore from 'stores/user_store.jsx';
import Constants from 'utils/constants.jsx';
@@ -30,7 +32,7 @@ export default class PostInfo extends React.Component {
createDropdown() {
var post = this.props.post;
var isOwner = this.props.currentUser.id === post.user_id;
- var isAdmin = Utils.isAdmin(this.props.currentUser.roles);
+ var isAdmin = TeamStore.isTeamAdminForCurrentTeam() || UserStore.isSystemAdminForCurrentUser();
if (post.state === Constants.POST_FAILED || post.state === Constants.POST_LOADING || Utils.isPostEphemeral(post)) {
return '';
diff --git a/webapp/components/rhs_comment.jsx b/webapp/components/rhs_comment.jsx
index f21ae24e7..5097e0573 100644
--- a/webapp/components/rhs_comment.jsx
+++ b/webapp/components/rhs_comment.jsx
@@ -6,6 +6,8 @@ import FileAttachmentList from './file_attachment_list.jsx';
import PostStore from 'stores/post_store.jsx';
import ChannelStore from 'stores/channel_store.jsx';
+import TeamStore from 'stores/team_store.jsx';
+import UserStore from 'stores/user_store.jsx';
import * as GlobalActions from 'action_creators/global_actions.jsx';
import AppDispatcher from '../dispatcher/app_dispatcher.jsx';
@@ -82,7 +84,7 @@ export default class RhsComment extends React.Component {
}
const isOwner = this.props.currentUser.id === post.user_id;
- const isAdmin = Utils.isAdmin(this.props.currentUser.roles);
+ var isAdmin = TeamStore.isTeamAdminForCurrentTeam() || UserStore.isSystemAdminForCurrentUser();
var dropdownContents = [];
diff --git a/webapp/components/rhs_root_post.jsx b/webapp/components/rhs_root_post.jsx
index c771674a6..a9f6612dc 100644
--- a/webapp/components/rhs_root_post.jsx
+++ b/webapp/components/rhs_root_post.jsx
@@ -4,6 +4,7 @@
import ChannelStore from 'stores/channel_store.jsx';
import UserProfile from './user_profile.jsx';
import UserStore from 'stores/user_store.jsx';
+import TeamStore from 'stores/user_store.jsx';
import * as TextFormatting from 'utils/text_formatting.jsx';
import * as Utils from 'utils/utils.jsx';
import FileAttachmentList from './file_attachment_list.jsx';
@@ -39,7 +40,7 @@ export default class RhsRootPost extends React.Component {
const post = this.props.post;
const user = this.props.user;
var isOwner = this.props.currentUser.id === post.user_id;
- var isAdmin = Utils.isAdmin(this.props.currentUser.roles);
+ var isAdmin = TeamStore.isTeamAdminForCurrentTeam() || UserStore.isSystemAdminForCurrentUser();
var timestamp = UserStore.getProfile(post.user_id).update_at;
var channel = ChannelStore.get(post.channel_id);
diff --git a/webapp/components/sidebar_right_menu.jsx b/webapp/components/sidebar_right_menu.jsx
index a48dcade6..b36d84b79 100644
--- a/webapp/components/sidebar_right_menu.jsx
+++ b/webapp/components/sidebar_right_menu.jsx
@@ -7,6 +7,7 @@ import UserSettingsModal from './user_settings/user_settings_modal.jsx';
import AboutBuildModal from './about_build_modal.jsx';
import UserStore from 'stores/user_store.jsx';
+import TeamStore from 'stores/team_store.jsx';
import PreferenceStore from 'stores/preference_store.jsx';
import * as GlobalActions from 'action_creators/global_actions.jsx';
@@ -77,8 +78,8 @@ export default class SidebarRightMenu extends React.Component {
var isSystemAdmin = false;
if (currentUser != null) {
- isAdmin = Utils.isAdmin(currentUser.roles);
- isSystemAdmin = Utils.isSystemAdmin(currentUser.roles);
+ isAdmin = TeamStore.isTeamAdminForCurrentTeam() || UserStore.isSystemAdminForCurrentUser();
+ isSystemAdmin = UserStore.isSystemAdminForCurrentUser();
inviteLink = (
<li>
diff --git a/webapp/components/team_members_dropdown.jsx b/webapp/components/team_members_dropdown.jsx
index 251c2ce3b..b65b9e050 100644
--- a/webapp/components/team_members_dropdown.jsx
+++ b/webapp/components/team_members_dropdown.jsx
@@ -39,9 +39,11 @@ export default class TeamMembersDropdown extends React.Component {
this.handleDemote(this.props.user, '');
} else {
Client.updateRoles(
+ this.props.teamMember.team_id,
this.props.user.id,
'',
() => {
+ AsyncClient.getTeamMembers(TeamStore.getCurrentId());
AsyncClient.getProfiles();
},
(err) => {
@@ -53,6 +55,7 @@ export default class TeamMembersDropdown extends React.Component {
handleMakeActive() {
Client.updateActive(this.props.user.id, true,
() => {
+ AsyncClient.getTeamMembers(TeamStore.getCurrentId());
AsyncClient.getProfiles();
AsyncClient.getChannelExtraInfo(ChannelStore.getCurrentId());
},
@@ -64,6 +67,7 @@ export default class TeamMembersDropdown extends React.Component {
handleMakeNotActive() {
Client.updateActive(this.props.user.id, false,
() => {
+ AsyncClient.getTeamMembers(TeamStore.getCurrentId());
AsyncClient.getProfiles();
AsyncClient.getChannelExtraInfo(ChannelStore.getCurrentId());
},
@@ -78,9 +82,11 @@ export default class TeamMembersDropdown extends React.Component {
this.handleDemote(this.props.user, 'admin');
} else {
Client.updateRoles(
+ this.props.teamMember.team_id,
this.props.user.id,
'admin',
() => {
+ AsyncClient.getTeamMembers(TeamStore.getCurrentId());
AsyncClient.getProfiles();
},
(err) => {
@@ -109,9 +115,13 @@ export default class TeamMembersDropdown extends React.Component {
}
handleDemoteSubmit() {
Client.updateRoles(
+ this.props.teamMember.team_id,
this.props.user.id,
this.state.newRole,
() => {
+ AsyncClient.getTeamMembers(TeamStore.getCurrentId());
+ AsyncClient.getProfiles();
+
const teamUrl = TeamStore.getCurrentTeamUrl();
if (teamUrl) {
browserHistory.push(teamUrl);
@@ -143,30 +153,26 @@ export default class TeamMembersDropdown extends React.Component {
/>
);
- if (user.roles.length > 0) {
- if (Utils.isSystemAdmin(user.roles)) {
- currentRoles = (
- <FormattedMessage
- id='team_members_dropdown.systemAdmin'
- defaultMessage='System Admin'
- />
- );
- } else if (Utils.isAdmin(user.roles)) {
- currentRoles = (
- <FormattedMessage
- id='team_members_dropdown.teamAdmin'
- defaultMessage='Team Admin'
- />
- );
- } else {
- currentRoles = user.roles.charAt(0).toUpperCase() + user.roles.slice(1);
- }
+ if (teamMember.roles.length > 0 && Utils.isAdmin(teamMember.roles)) {
+ currentRoles = (
+ <FormattedMessage
+ id='team_members_dropdown.teamAdmin'
+ defaultMessage='Team Admin'
+ />
+ );
}
- let showMakeMember = teamMember.roles === 'admin' || user.roles === 'system_admin';
+ if (user.roles.length > 0 && Utils.isSystemAdmin(user.roles)) {
+ currentRoles = (
+ <FormattedMessage
+ id='team_members_dropdown.systemAdmin'
+ defaultMessage='System Admin'
+ />
+ );
+ }
- //let showMakeAdmin = teamMember.roles === '' && user.roles !== 'system_admin';
- let showMakeAdmin = false;
+ let showMakeMember = teamMember.roles === 'admin' || user.roles === 'system_admin';
+ let showMakeAdmin = teamMember.roles === '' && user.roles !== 'system_admin';
let showMakeActive = false;
let showMakeNotActive = user.roles !== 'system_admin';
@@ -221,38 +227,38 @@ export default class TeamMembersDropdown extends React.Component {
let makeActive = null;
if (showMakeActive) {
- makeActive = (
- <li role='presentation'>
- <a
- role='menuitem'
- href='#'
- onClick={this.handleMakeActive}
- >
- <FormattedMessage
- id='team_members_dropdown.makeActive'
- defaultMessage='Make Active'
- />
- </a>
- </li>
- );
+ // makeActive = (
+ // <li role='presentation'>
+ // <a
+ // role='menuitem'
+ // href='#'
+ // onClick={this.handleMakeActive}
+ // >
+ // <FormattedMessage
+ // id='team_members_dropdown.makeActive'
+ // defaultMessage='Make Active'
+ // />
+ // </a>
+ // </li>
+ // );
}
let makeNotActive = null;
if (showMakeNotActive) {
- makeNotActive = (
- <li role='presentation'>
- <a
- role='menuitem'
- href='#'
- onClick={this.handleMakeNotActive}
- >
- <FormattedMessage
- id='team_members_dropdown.makeInactive'
- defaultMessage='Make Inactive'
- />
- </a>
- </li>
- );
+ // makeNotActive = (
+ // <li role='presentation'>
+ // <a
+ // role='menuitem'
+ // href='#'
+ // onClick={this.handleMakeNotActive}
+ // >
+ // <FormattedMessage
+ // id='team_members_dropdown.makeInactive'
+ // defaultMessage='Make Inactive'
+ // />
+ // </a>
+ // </li>
+ // );
}
const me = UserStore.getCurrentUser();
let makeDemoteModal = null;
diff --git a/webapp/stores/team_store.jsx b/webapp/stores/team_store.jsx
index 29e832633..8eebbaca5 100644
--- a/webapp/stores/team_store.jsx
+++ b/webapp/stores/team_store.jsx
@@ -3,6 +3,7 @@
import AppDispatcher from '../dispatcher/app_dispatcher.jsx';
import EventEmitter from 'events';
+import UserStore from 'stores/user_store.jsx';
import Constants from 'utils/constants.jsx';
const ActionTypes = Constants.ActionTypes;
@@ -148,6 +149,22 @@ class TeamStoreClass extends EventEmitter {
getTeamListings() {
return this.teamListings;
}
+
+ isTeamAdminForCurrentTeam() {
+ if (!Utils) {
+ Utils = require('utils/utils.jsx'); //eslint-disable-line global-require
+ }
+
+ const userId = UserStore.getCurrentId();
+ var teamMembers = this.getTeamMembers();
+ const teamMember = teamMembers.find((m) => m.user_id === userId && m.team_id === this.getCurrentId());
+
+ if (teamMember) {
+ return Utils.isAdmin(teamMember.roles);
+ }
+
+ return false;
+ }
}
var TeamStore = new TeamStoreClass();
diff --git a/webapp/stores/user_store.jsx b/webapp/stores/user_store.jsx
index 8ae1e1404..855222d47 100644
--- a/webapp/stores/user_store.jsx
+++ b/webapp/stores/user_store.jsx
@@ -13,6 +13,8 @@ const CHANGE_EVENT_SESSIONS = 'change_sessions';
const CHANGE_EVENT_AUDITS = 'change_audits';
const CHANGE_EVENT_STATUSES = 'change_statuses';
+var Utils;
+
class UserStoreClass extends EventEmitter {
constructor() {
super();
@@ -314,6 +316,20 @@ class UserStoreClass extends EventEmitter {
setNoAccounts(noAccounts) {
this.noAccounts = noAccounts;
}
+
+ isSystemAdminForCurrentUser() {
+ if (!Utils) {
+ Utils = require('utils/utils.jsx'); //eslint-disable-line global-require
+ }
+
+ var current = this.getCurrentUser();
+
+ if (current) {
+ return Utils.isAdmin(current.roles);
+ }
+
+ return false;
+ }
}
var UserStore = new UserStoreClass();
diff --git a/webapp/tests/client_user.test.jsx b/webapp/tests/client_user.test.jsx
index 610308fa3..2b3b1b89a 100644
--- a/webapp/tests/client_user.test.jsx
+++ b/webapp/tests/client_user.test.jsx
@@ -206,12 +206,14 @@ describe('Client.User', function() {
it('updateRoles', function(done) {
TestHelper.initBasic(() => {
var user = TestHelper.basicUser();
+ var team = TestHelper.basicTeam();
TestHelper.basicClient().updateRoles(
+ team.id,
user.id,
'',
function(data) {
- assert.equal(data.roles, '');
+ assert.equal(data.user_id, user.id);
done();
},
function(err) {