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;
+ }
+}