diff --git a/CHANGELOG.md b/CHANGELOG.md index 99d09dfc78..a5c4c9dfd5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,8 +4,12 @@ ### Bug Fixes ## v1.4.0.0-rc2 [unreleased] +### UI Improvements +1. [#2632](https://github.com/influxdata/chronograf/pull/2632): Tell user which organization they switched into and what role they have whenever they switch, including on Source Page + ### Bug Fixes 1. [#2639](https://github.com/influxdata/chronograf/pull/2639): Prevent SuperAdmin from modifying their own status +1. [#2632](https://github.com/influxdata/chronograf/pull/2632): Give SuperAdmin DefaultRole when switching to organization where they have no role ## v1.4.0.0-rc1 [2017-12-19] ### Features diff --git a/integrations/server_test.go b/integrations/server_test.go index c28943324a..1cc0fe2efc 100644 --- a/integrations/server_test.go +++ b/integrations/server_test.go @@ -1354,7 +1354,7 @@ func TestServer(t *testing.T) { "organization": "default" }, { - "name": "admin", + "name": "viewer", "organization": "1" } ], diff --git a/server/me.go b/server/me.go index 708a7b9dc4..52a36c6ff0 100644 --- a/server/me.go +++ b/server/me.go @@ -11,7 +11,6 @@ import ( "github.com/influxdata/chronograf" "github.com/influxdata/chronograf/oauth2" "github.com/influxdata/chronograf/organizations" - "github.com/influxdata/chronograf/roles" ) type meLinks struct { @@ -96,7 +95,7 @@ func (s *Service) UpdateMe(auth oauth2.Authenticator) func(http.ResponseWriter, } // validate that the organization exists - _, err = s.Store.Organizations(serverCtx).Get(serverCtx, chronograf.OrganizationQuery{ID: &req.Organization}) + org, err := s.Store.Organizations(serverCtx).Get(serverCtx, chronograf.OrganizationQuery{ID: &req.Organization}) if err != nil { Error(w, http.StatusBadRequest, err.Error(), s.Logger) return @@ -151,8 +150,8 @@ func (s *Service) UpdateMe(auth oauth2.Authenticator) func(http.ResponseWriter, // If the user is a super admin give them an admin role in the // requested organization. u.Roles = append(u.Roles, chronograf.Role{ - Organization: req.Organization, - Name: roles.AdminRoleName, + Organization: org.ID, + Name: org.DefaultRole, }) if err := s.Store.Users(serverCtx).Update(serverCtx, u); err != nil { unknownErrorWithMessage(w, err, s.Logger) diff --git a/ui/src/admin/components/chronograf/OrganizationsTable.js b/ui/src/admin/components/chronograf/OrganizationsTable.js index e633af7c5c..272d574878 100644 --- a/ui/src/admin/components/chronograf/OrganizationsTable.js +++ b/ui/src/admin/components/chronograf/OrganizationsTable.js @@ -44,7 +44,6 @@ class OrganizationsTable extends Component { currentOrganization, authConfig: {superAdminNewUsers}, onChangeAuthConfig, - me, } = this.props const {isCreatingOrganization} = this.state @@ -93,7 +92,6 @@ class OrganizationsTable extends Component { onRename={onRenameOrg} onChooseDefaultRole={onChooseDefaultRole} currentOrganization={currentOrganization} - userHasRoleInOrg={!!me.organizations.find(o => org.id === o.id)} /> )} @@ -146,14 +144,5 @@ OrganizationsTable.propTypes = { authConfig: shape({ superAdminNewUsers: bool, }), - me: shape({ - organizations: arrayOf( - shape({ - id: string.isRequired, - name: string.isRequired, - defaultRole: string.isRequired, - }) - ), - }), } export default OrganizationsTable diff --git a/ui/src/admin/components/chronograf/OrganizationsTableRow.js b/ui/src/admin/components/chronograf/OrganizationsTableRow.js index 2f20bb9f3a..93690854a2 100644 --- a/ui/src/admin/components/chronograf/OrganizationsTableRow.js +++ b/ui/src/admin/components/chronograf/OrganizationsTableRow.js @@ -39,19 +39,9 @@ class OrganizationsTableRow extends Component { } handleChangeCurrentOrganization = async () => { - const { - router, - links, - meChangeOrganization, - organization, - userHasRoleInOrg, - } = this.props - - await meChangeOrganization( - links.me, - {organization: organization.id}, - {userHasRoleInOrg} - ) + const {router, links, meChangeOrganization, organization} = this.props + + await meChangeOrganization(links.me, {organization: organization.id}) router.push('') } @@ -204,7 +194,7 @@ class OrganizationsTableRow extends Component { } } -const {arrayOf, bool, func, shape, string} = PropTypes +const {arrayOf, func, shape, string} = PropTypes OrganizationsTableRow.propTypes = { organization: shape({ @@ -235,7 +225,6 @@ OrganizationsTableRow.propTypes = { }), }), meChangeOrganization: func.isRequired, - userHasRoleInOrg: bool.isRequired, } OrganizationsTableRowDeleteButton.propTypes = { diff --git a/ui/src/shared/actions/auth.js b/ui/src/shared/actions/auth.js index 06b480f5e0..79aeaa510c 100644 --- a/ui/src/shared/actions/auth.js +++ b/ui/src/shared/actions/auth.js @@ -5,6 +5,8 @@ import {linksReceived} from 'shared/actions/links' import {publishAutoDismissingNotification} from 'shared/dispatchers' import {errorThrown} from 'shared/actions/errors' +import {LONG_NOTIFICATION_DISMISS_DELAY} from 'shared/constants' + export const authExpired = auth => ({ type: 'AUTH_EXPIRED', payload: { @@ -84,18 +86,20 @@ export const getMeAsync = ({shouldResetMe = false} = {}) => async dispatch => { export const meChangeOrganizationAsync = ( url, - organization, - {userHasRoleInOrg = true} = {} + organization ) => async dispatch => { dispatch(meChangeOrganizationRequested()) try { const {data: me, auth, logoutLink} = await updateMeAJAX(url, organization) + const currentRole = me.roles.find( + r => r.organization === me.currentOrganization.id + ) dispatch( publishAutoDismissingNotification( 'success', - `Now signed in to ${me.currentOrganization.name}${userHasRoleInOrg - ? '' - : ' with Admin role.'}` + `Now logged in to '${me.currentOrganization + .name}' as '${currentRole.name}'`, + LONG_NOTIFICATION_DISMISS_DELAY ) ) dispatch(meChangeOrganizationCompleted()) diff --git a/ui/src/shared/constants/index.js b/ui/src/shared/constants/index.js index 1c095d4202..0bc9e48ac2 100644 --- a/ui/src/shared/constants/index.js +++ b/ui/src/shared/constants/index.js @@ -387,6 +387,7 @@ export const PRESENTATION_MODE_ANIMATION_DELAY = 0 // In milliseconds. export const PRESENTATION_MODE_NOTIFICATION_DELAY = 2000 // In milliseconds. export const SHORT_NOTIFICATION_DISMISS_DELAY = 2000 // in milliseconds +export const LONG_NOTIFICATION_DISMISS_DELAY = 4000 // in milliseconds export const REVERT_STATE_DELAY = 1500 // ms diff --git a/ui/src/sources/containers/SourcePage.js b/ui/src/sources/containers/SourcePage.js index d6b470a073..7d0d792e00 100644 --- a/ui/src/sources/containers/SourcePage.js +++ b/ui/src/sources/containers/SourcePage.js @@ -10,6 +10,7 @@ import { import {publishNotification} from 'shared/actions/notifications' import {connect} from 'react-redux' +import Notifications from 'shared/components/Notifications' import SourceForm from 'src/sources/components/SourceForm' import FancyScrollbar from 'shared/components/FancyScrollbar' import SourceIndicator from 'shared/components/SourceIndicator' @@ -200,42 +201,45 @@ class SourcePage extends Component { } return ( -
- {isInitialSource - ? null - :
-
-
-
-

- {editMode ? 'Edit Source' : 'Add a New Source'} -

-
-
- +
+ +
+ {isInitialSource + ? null + :
+
+
+
+

+ {editMode ? 'Edit Source' : 'Add a New Source'} +

+
+
+ +
-
-
} - -
-
-
-
- +
} + +
+
+
+
+ +
-
- + +
) }