add and test logout

This commit is contained in:
catarak 2016-08-27 20:46:20 -04:00
parent 515febceb2
commit 64b2ea3da4
8 changed files with 84 additions and 8 deletions

View file

@ -85,10 +85,34 @@ function Nav(props) {
</li> </li>
</ul> </ul>
<ul className="nav__items-right" title="user-menu"> <ul className="nav__items-right" title="user-menu">
{(() => {
if (!props.user.authenticated) {
return (
<li className="nav__item"> <li className="nav__item">
{props.user.authenticated && <p>Hello, {props.user.username}!</p>} <p>
{!props.user.authenticated && <p><Link to="/login">Login</Link> or <Link to="/signup">Sign Up</Link></p>} <Link to="/login">Login</Link> or <Link to="/signup">Sign Up</Link>
</p>
</li> </li>
);
}
return (
<li className="nav__item">
<a>Hello, {props.user.username}!</a>
<ul className="nav__dropdown">
<li>
<Link to="/sketches">
My Sketches
</Link>
</li>
<li>
<a onClick={props.logoutUser} >
Logout
</a>
</li>
</ul>
</li>
);
})()}
</ul> </ul>
</nav> </nav>
); );
@ -105,7 +129,8 @@ Nav.propTypes = {
}).isRequired, }).isRequired,
project: PropTypes.shape({ project: PropTypes.shape({
id: PropTypes.string id: PropTypes.string
}) }),
logoutUser: PropTypes.func.isRequired
}; };
export default Nav; export default Nav;

View file

@ -15,6 +15,7 @@ import * as IDEActions from '../actions/ide';
import * as ProjectActions from '../actions/project'; import * as ProjectActions from '../actions/project';
import * as EditorAccessibilityActions from '../actions/editorAccessibility'; import * as EditorAccessibilityActions from '../actions/editorAccessibility';
import * as PreferencesActions from '../actions/preferences'; import * as PreferencesActions from '../actions/preferences';
import * as UserActions from '../../User/actions';
import { getFile, getHTMLFile, getJSFiles, getCSSFiles, setSelectedFile } from '../reducers/files'; import { getFile, getHTMLFile, getJSFiles, getCSSFiles, setSelectedFile } from '../reducers/files';
import SplitPane from 'react-split-pane'; import SplitPane from 'react-split-pane';
import Overlay from '../../App/components/Overlay'; import Overlay from '../../App/components/Overlay';
@ -117,6 +118,7 @@ class IDEView extends React.Component {
exportProjectAsZip={this.props.exportProjectAsZip} exportProjectAsZip={this.props.exportProjectAsZip}
cloneProject={this.props.cloneProject} cloneProject={this.props.cloneProject}
project={this.props.project} project={this.props.project}
logoutUser={this.props.logoutUser}
/> />
<Toolbar <Toolbar
className="Toolbar" className="Toolbar"
@ -366,7 +368,8 @@ IDEView.propTypes = {
hideEditFileName: PropTypes.func.isRequired, hideEditFileName: PropTypes.func.isRequired,
updateFileName: PropTypes.func.isRequired, updateFileName: PropTypes.func.isRequired,
showEditProjectName: PropTypes.func.isRequired, showEditProjectName: PropTypes.func.isRequired,
hideEditProjectName: PropTypes.func.isRequired hideEditProjectName: PropTypes.func.isRequired,
logoutUser: PropTypes.func.isRequired
}; };
function mapStateToProps(state) { function mapStateToProps(state) {
@ -390,7 +393,8 @@ function mapDispatchToProps(dispatch) {
FileActions, FileActions,
ProjectActions, ProjectActions,
IDEActions, IDEActions,
PreferencesActions), PreferencesActions,
UserActions),
dispatch); dispatch);
} }

View file

@ -56,3 +56,16 @@ export function getUser() {
}); });
}; };
} }
export function logoutUser() {
return (dispatch) => {
axios.get(`${ROOT_URL}/logout`, { withCredentials: true })
.then(() => {
dispatch({
type: ActionTypes.UNAUTH_USER
});
})
.catch(response => dispatch(authError(response.data.error)));
};
}

View file

@ -5,6 +5,10 @@ const user = (state = { authenticated: false }, action) => {
case ActionTypes.AUTH_USER: case ActionTypes.AUTH_USER:
return { ...action.user, return { ...action.user,
authenticated: true }; authenticated: true };
case ActionTypes.UNAUTH_USER:
return {
authenticated: false
};
case ActionTypes.AUTH_ERROR: case ActionTypes.AUTH_ERROR:
return { return {
authenticated: false authenticated: false

View file

@ -11,6 +11,10 @@ body, input, button {
color: $light-primary-text-color; color: $light-primary-text-color;
} }
body {
background-color: $light-background-color;
}
.root-app, .app { .root-app, .app {
min-height: 100%; min-height: 100%;
height: 100%; height: 100%;

View file

@ -1,6 +1,6 @@
.nav { .nav {
width: 100%; width: 100%;
padding: #{10 / $base-font-size}rem #{40 / $base-font-size}rem; padding: #{10 / $base-font-size}rem #{70 / $base-font-size}rem;
padding-left: #{170 / $base-font-size}rem; padding-left: #{170 / $base-font-size}rem;
display: flex; display: flex;
flex-direction: row; flex-direction: row;
@ -24,4 +24,22 @@
& + & { & + & {
margin-left: #{20 / $base-font-size}rem; margin-left: #{20 / $base-font-size}rem;
} }
position: relative;
&:hover .nav__dropdown {
display: flex;
}
}
.nav__dropdown {
display: none;
position: absolute;
flex-direction: column;
background-color: $light-background-color;
padding: #{10 / $base-font-size}rem;
left: #{-10 / $base-font-size}rem;
border: 1px solid $ide-border-color;
& li + li {
margin-top: #{10 / $base-font-size}rem;
}
width: #{140 / $base-font-size}rem;
} }

View file

@ -30,3 +30,9 @@ export function getSession(req, res) {
} }
return res.status(404).send({ message: 'Session does not exist' }); return res.status(404).send({ message: 'Session does not exist' });
} }
export function destroySession(req, res) {
req.logout();
res.json({success: true});
}

View file

@ -7,6 +7,8 @@ router.route('/login').post(SessionController.createSession);
router.route('/session').get(SessionController.getSession); router.route('/session').get(SessionController.getSession);
router.route('/logout').get(SessionController.destroySession);
export default router; export default router;
// TODO add github authentication stuff // TODO add github authentication stuff