From dc442e99f914ab516eafab55486281c5970acba7 Mon Sep 17 00:00:00 2001 From: Hannu Lyytikainen Date: Fri, 14 Feb 2020 11:17:41 +0200 Subject: [PATCH 1/2] Add token scopes to Auth store Add `authScopes` attribute to the Auth store. It stores an array of scopes associated with the currently stored token. --- src/ducks/Auth.duck.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/ducks/Auth.duck.js b/src/ducks/Auth.duck.js index f953b25908..173b5fec17 100644 --- a/src/ducks/Auth.duck.js +++ b/src/ducks/Auth.duck.js @@ -31,6 +31,9 @@ export const USER_LOGOUT = 'app/USER_LOGOUT'; const initialState = { isAuthenticated: false, + // scopes associated with current token + authScopes: [], + // auth info authInfoLoaded: false, @@ -53,7 +56,12 @@ export default function reducer(state = initialState, action = {}) { case AUTH_INFO_REQUEST: return state; case AUTH_INFO_SUCCESS: - return { ...state, authInfoLoaded: true, isAuthenticated: authenticated(payload) }; + return { + ...state, + authInfoLoaded: true, + isAuthenticated: authenticated(payload), + authScopes: payload.scopes, + }; case LOGIN_REQUEST: return { @@ -71,7 +79,7 @@ export default function reducer(state = initialState, action = {}) { case LOGOUT_REQUEST: return { ...state, logoutInProgress: true, loginError: null, logoutError: null }; case LOGOUT_SUCCESS: - return { ...state, logoutInProgress: false, isAuthenticated: false }; + return { ...state, logoutInProgress: false, isAuthenticated: false, authScopes: [] }; case LOGOUT_ERROR: return { ...state, logoutInProgress: false, logoutError: payload }; From 650dfcf4d7c6e80dc51c866a93585604699d16d6 Mon Sep 17 00:00:00 2001 From: Hannu Lyytikainen Date: Fri, 14 Feb 2020 14:29:00 +0200 Subject: [PATCH 2/2] Add a banner indicating limited access login Show a banner if a user is logged in with an access token that has `user:limited` scope. --- CHANGELOG.md | 5 +- .../LimitedAccessBanner.css | 31 +++++++++ .../LimitedAccessBanner.js | 68 +++++++++++++++++++ src/components/Topbar/Topbar.js | 13 +++- src/components/index.js | 1 + .../TopbarContainer/TopbarContainer.js | 9 ++- src/translations/en.json | 2 + 7 files changed, 125 insertions(+), 4 deletions(-) create mode 100644 src/components/LimitedAccessBanner/LimitedAccessBanner.css create mode 100644 src/components/LimitedAccessBanner/LimitedAccessBanner.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 98da611303..5053e9c571 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,7 +14,10 @@ way to update this template, but currently, we follow a pattern: ## Upcoming version 2020-XX-XX -- [add] Support for logging in as a user from Console. [#1254](https://github.com/sharetribe/ftw-daily/pull/1254) +- [add] Show a banner when a user is logged in with limited access. + [#1259](https://github.com/sharetribe/ftw-daily/pull/1259) +- [add] Support for logging in as a user from Console. + [#1254](https://github.com/sharetribe/ftw-daily/pull/1254) - [change] Add `handlebars` 4.5.3 and `serialize-javascript` 2.1.1 to resolutions in `package.json`. [#1251](https://github.com/sharetribe/ftw-daily/pull/1251) diff --git a/src/components/LimitedAccessBanner/LimitedAccessBanner.css b/src/components/LimitedAccessBanner/LimitedAccessBanner.css new file mode 100644 index 0000000000..3edc8658a7 --- /dev/null +++ b/src/components/LimitedAccessBanner/LimitedAccessBanner.css @@ -0,0 +1,31 @@ +@import '../../marketplace.css'; + +.root { + background-color: #df492a; + text-align: center; + padding: 10px 20px 9px; +} + +.text { + margin: 0; + display: inline-block; + color: #fff; + font-size: 16px; + margin-bottom: 16px; + line-height: 20px; +} + +.button { + background: #2a3d4b; + margin: 0 16px; + padding: 8px 16px; + border-radius: 4px; + font-size: 14px; + color: #fff; + border: 0; + + &:hover { + text-decoration: none; + background: #364f61; + } +} diff --git a/src/components/LimitedAccessBanner/LimitedAccessBanner.js b/src/components/LimitedAccessBanner/LimitedAccessBanner.js new file mode 100644 index 0000000000..8057cf1b22 --- /dev/null +++ b/src/components/LimitedAccessBanner/LimitedAccessBanner.js @@ -0,0 +1,68 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import classNames from 'classnames'; +import { FormattedMessage } from '../../util/reactIntl'; +import { propTypes } from '../../util/types'; +import { Button } from '../../components'; +import { ensureCurrentUser } from '../../util/data'; + +import css from './LimitedAccessBanner.css'; + +// Due to the layout structure, do not render the banner on the following pages +const disabledPages = ['SearchPage']; + +const LimitedAccessBanner = props => { + const { + rootClassName, + className, + isAuthenticated, + authScopes, + currentUser, + onLogout, + currentPage, + } = props; + const classes = classNames(rootClassName || css.root, className); + const user = ensureCurrentUser(currentUser); + + const showBanner = + user.id && + isAuthenticated && + authScopes.length === 1 && + authScopes[0] === 'user:limited' && + !disabledPages.includes(currentPage); + + const { firstName, lastName } = user.attributes.profile; + + return showBanner ? ( +
+

+ +

+ +
+ ) : null; +}; + +LimitedAccessBanner.defaultProps = { + rootClassName: null, + className: null, + currentUser: null, + authScopes: [], + currentPage: null, +}; + +const { array, bool, func, string } = PropTypes; + +LimitedAccessBanner.propTypes = { + rootClassName: string, + className: string, + isAuthenticated: bool.isRequired, + authScopes: array, + currentUser: propTypes.currentUser, + onLogout: func.isRequired, + currentPage: string, +}; + +export default LimitedAccessBanner; diff --git a/src/components/Topbar/Topbar.js b/src/components/Topbar/Topbar.js index 9c5f09aad5..786b69ea19 100644 --- a/src/components/Topbar/Topbar.js +++ b/src/components/Topbar/Topbar.js @@ -12,6 +12,7 @@ import { createResourceLocatorString, pathByRouteName } from '../../util/routes' import { propTypes } from '../../util/types'; import { Button, + LimitedAccessBanner, Logo, Modal, ModalMissingInformation, @@ -134,6 +135,7 @@ class TopbarComponent extends Component { mobileRootClassName, mobileClassName, isAuthenticated, + authScopes, authInProgress, currentUser, currentUserHasListings, @@ -189,6 +191,13 @@ class TopbarComponent extends Component { return (
+