diff --git a/src/redux/session.js b/src/redux/session.js index 2740ab6af..6180dcee1 100644 --- a/src/redux/session.js +++ b/src/redux/session.js @@ -140,6 +140,7 @@ module.exports.selectToken = state => get(state, ['session', 'session', 'user', module.exports.selectIsAdmin = state => get(state, ['session', 'session', 'permissions', 'admin'], false); module.exports.selectIsSocial = state => get(state, ['session', 'session', 'permissions', 'social'], false); module.exports.selectIsEducator = state => get(state, ['session', 'session', 'permissions', 'educator'], false); +module.exports.selectBannedUser = state => get(state, ['session', 'session', 'user'], false); module.exports.selectProjectCommentsGloballyEnabled = state => get(state, ['session', 'session', 'flags', 'project_comments_enabled'], false); module.exports.selectStudioCommentsGloballyEnabled = state => diff --git a/src/routes.json b/src/routes.json index 8120449db..90f7572e3 100644 --- a/src/routes.json +++ b/src/routes.json @@ -423,6 +423,13 @@ "view": "microbit/microbit", "title": "micro:bit" }, + { + "name": "Account Blocked", + "pattern": "^/accounts/banned-response/?(\\?.*)?$", + "routeAlias": "/accounts/banned-response/?$", + "view": "banned-splash/banned-splash", + "title": "Account Blocked" + }, { "name": "vernier", "pattern": "^/vernier/?(\\?.*)?$", diff --git a/src/views/banned-splash/banned-splash.jsx b/src/views/banned-splash/banned-splash.jsx new file mode 100644 index 000000000..f19f2a0f9 --- /dev/null +++ b/src/views/banned-splash/banned-splash.jsx @@ -0,0 +1,193 @@ +const injectIntl = require('react-intl').injectIntl; +const intlShape = require('react-intl').intlShape; +// const FormattedMessage = require('react-intl').FormattedMessage; +const React = require('react'); +import {connect} from 'react-redux'; +import {selectBannedUser, selectHasFetchedSession} from '../../redux/session'; +const messageActions = require('../../redux/messages.js'); +const JoinFlowStep = require('../../components/join-flow/join-flow-step.jsx'); +const FormikInput = require('../../components/formik-forms/formik-input.jsx'); +import {Formik} from 'formik'; + +const Page = require('../../components/page/www/page.jsx'); +const render = require('../../lib/render.jsx'); + +require('../../components/extension-landing/extension-landing.scss'); +require('./banned-splash.scss'); + +const validateUsernameConfirm = (username, usernameConfirm) => { + if (!usernameConfirm) { + // return 'Username is required'; + } else if (username !== usernameConfirm) { + return "Usernames don't match"; + } +}; + +const BannedSplash = ({hasSession, user, adminMessages, getAdminMessages, intl}) => { + + React.useEffect(() => { + if (user && user.username && user.token){ + getAdminMessages(user.username, user.token); + } + }, [user]); + + if (hasSession && (!user || !user.banned)){ + window.location = '/'; + } + + if (user && user.banned){ + return (
+
+
+
+

Account Blocked

+

To recover access to your account, change your username.

+

Your scratch account {user && user.username} has been temporarily blocked because your usernamed appears to contain personal information.

+

This is a serious privacy issue. When you share information like this, it is visible to everyone on the internet, so please be careful what you share

+

When creating an username, please remember to avoid using last names, school names, or other private information in your username.

+
+
+ + {props => { + const { + errors, + // handleSubmit, + // isSubmitting, + setFieldError, + setFieldTouched, + setFieldValue, + // touched, + validateField, + values + } = props; + return ( + Make sure the username you chose is aligned with Scratch's Community Guidelines} + innerClassName="change-username-inner" + outerClassName="change-username-outer" + title={'Change your Username'} + // waiting={isSubmitting} + // onSubmit={handleSubmit} + nextButton={'Change'} + > +
+ validateUsername(newUsername)} + validationClassName="validation-left validation-full-width-input" + /* eslint-disable react/jsx-no-bind */ + onBlur={() => validateField('newUsername')} + onChange={e => { + setFieldValue('newUsername', e.target.value.substring(0, 30)); + setFieldTouched('newUsername'); + setFieldError('newUsername', null); + }} + // onFocus={() => this.handleFocused('username')} + /* eslint-enable react/jsx-no-bind */ + // onSetRef={this.handleSetUsernameRef} + /> + validateUsernameConfirm(values.newUsername, newUsernameConfirm)} + validationClassName="validation-left validation-full-width-input" + onBlur={() => { + validateField('newUsernameConfirm'); + }} + onChange={e => { + setFieldValue('newUsernameConfirm', e.target.value.substring(0, 30)); + setFieldTouched('newUsernameConfirm'); + setFieldError('newUsernameConfirm', null); + }} + /* eslint-enable react/jsx-no-bind */ + // onSetRef={this.handleSetUsernameRef} + /> +
+
); + }} +
+
+
+
+
+
+ Here are your past admin notifications +
+ {adminMessages.map(message => ( +
+
+ {new Date(message.datetime_created).toDateString()} +
+
+
+ ))} +
+
+ ); + } + return
; +}; + +BannedSplash.propTypes = { + intl: intlShape.isRequired +}; + + +// LET SESSION MAKE BANNED BE A STRING THAT SAYS THE KIND OF BANNED +// THIS IS AN API CHANGE ON THE SESSION +const ConnectedBannedSplash = connect( + state => ({ + user: selectBannedUser(state), + hasSession: selectHasFetchedSession(state), + adminMessages: state.messages.messages && state.messages.messages.admin + }), + dispatch => ({ + getAdminMessages: (username, token) => { + dispatch(messageActions.getAdminMessages( + username, token, 0 + )); + } + }) +)(BannedSplash); + + +const WrappedBannedSplash = injectIntl(ConnectedBannedSplash); + +render(, document.getElementById('app'), + {messages: messageActions.messagesReducer}); diff --git a/src/views/banned-splash/banned-splash.scss b/src/views/banned-splash/banned-splash.scss new file mode 100644 index 000000000..ff030292f --- /dev/null +++ b/src/views/banned-splash/banned-splash.scss @@ -0,0 +1,103 @@ +@import "../../colors"; +@import "../../frameless"; + +.validation-left { + transform: translate(-20.5rem, 0); +} + +@media #{$intermediate-and-smaller} { + .validation-full-width-input { + box-sizing: border-box; + transform: unset; + margin-bottom: .75rem; + max-width: 100%; + } +} + +#banned-splash{ + display: flex; + flex-direction: column; + align-items: center; +} + +#force-account-rename{ + width: 100%; + display: flex; + justify-content: center; + + #force-account-rename-inner{ + max-width: 1094px; + display: flex; + flex-direction: row; + @media only screen and (max-width: 800px) { + flex-direction: column; + } + + text-align: left; + + input{ + box-sizing: border-box; + width: 100%; + } + } + background-color: #4d97ff; + .col{ + padding: 40px; + flex: 1; + } +} + + +#admin-message-list{ + display: inline-block; + padding: 25px; + max-width: 1094px; + + #admin-message-list-title{ + text-align: left; + } +} + +.admin-message{ + text-align: left; + .admin-message-date{ + color: #575E75; + font-size: 12px; + padding-bottom: 10px; + } + text-align: left; + border-radius: 8px; + padding: 16px; + background-color: #E5F0FF; + margin: 10px; +} + +#force-account-rename-text{ + h1, h3, p{ + color: white; + } +} + +.empty{ + text-align: left; + + .admin-message{ + margin: 10px; + } +} + +.banned-message-box{ + margin: 20px; + text-align: left; +} + +.join-flow-outer-content{ + background-color: white; + border-radius: 16px; + color: #575e75; + max-width: 468px; + min-height: auto !important; + @media only screen and (max-width: 800px) { + margin: auto; + } +}