Skip to content

Commit ee1c67b

Browse files
authored
Token based auth (codesandbox#29)
* Remove sockjs-client * Move to token based authorization * Remove postinstall task
1 parent e220f08 commit ee1c67b

File tree

6 files changed

+148
-144
lines changed

6 files changed

+148
-144
lines changed

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,6 @@
113113
"redbox-react": "^1.4.2",
114114
"redux": "^3.7.0",
115115
"reselect": "^3.0.0",
116-
"sockjs-client": "^1.1.4",
117116
"store": "^2.0.4",
118117
"styled-components": "^2.1.0",
119118
"tern": "^0.21.0"

src/app/containers/Navigation/index.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ const Action = styled.div`
4040
transition: 0.3s ease all;
4141
margin: 0 2rem;
4242
cursor: pointer;
43+
color: white;
4344
4445
&:hover {
4546
color: white;
@@ -79,7 +80,9 @@ class Navigation extends React.PureComponent {
7980
<LogoWithBorder height={40} width={40} />
8081
</a>
8182
<Border width={1} size={500} />
82-
<Title>{title}</Title>
83+
<Title>
84+
{title}
85+
</Title>
8386
</Row>
8487
<Row>
8588
<Action>
@@ -91,9 +94,8 @@ class Navigation extends React.PureComponent {
9194
? <User signOut={userActions.signOut} user={user} />
9295
: <Button small onClick={userActions.signIn}>
9396
<Row>
94-
<GithubIcon style={{ marginRight: '0.5rem' }} />
95-
{' '}
96-
Sign in with GitHub
97+
<GithubIcon style={{ marginRight: '0.5rem' }} /> Sign in with
98+
GitHub
9799
</Row>
98100
</Button>}
99101
</Row>

src/app/pages/CLI/Prompt.js

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
import React from 'react';
2+
import styled from 'styled-components';
3+
4+
import Title from 'app/components/text/Title';
5+
import SubTitle from 'app/components/text/SubTitle';
6+
import Button from 'app/components/buttons/Button';
7+
8+
const Container = styled.div`
9+
height: 100%;
10+
width: 100%;
11+
margin-top: 10%;
12+
text-align: center;
13+
`;
14+
15+
const Buttons = styled.div`
16+
display: flex;
17+
justify-content: center;
18+
19+
> button {
20+
margin: 1rem;
21+
}
22+
`;
23+
24+
const TokenContainer = styled.input`
25+
color: white;
26+
27+
width: 100%;
28+
max-width: 20em;
29+
border: none;
30+
outline: none;
31+
padding: 1rem;
32+
font-size: 1.5rem;
33+
text-align: center;
34+
margin: auto;
35+
36+
border-radius: 2px;
37+
box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.5);
38+
39+
background-color: rgba(0, 0, 0, 0.5);
40+
`;
41+
42+
type Props = {
43+
error: ?string,
44+
token: ?string,
45+
loading: boolean,
46+
username: ?string,
47+
signIn: () => void,
48+
};
49+
50+
const select = event => event.target.select();
51+
52+
export default ({ error, token, loading, username, signIn }: Props) => {
53+
if (error) {
54+
return (
55+
<Container>
56+
<Title>An error occured:</Title>
57+
<SubTitle>
58+
{error}
59+
</SubTitle>
60+
<Buttons>
61+
<Button href="/">Go to homepage</Button>
62+
</Buttons>
63+
</Container>
64+
);
65+
}
66+
67+
if (!username) {
68+
return (
69+
<Container>
70+
<Title>Welcome to CodeSandbox!</Title>
71+
<SubTitle>
72+
You need to sign in with your GitHub account to use the CLI.
73+
</SubTitle>
74+
<Buttons>
75+
<Button onClick={signIn}>Sign in with Github</Button>
76+
</Buttons>
77+
</Container>
78+
);
79+
}
80+
81+
if (loading) {
82+
return (
83+
<Container>
84+
<Title>Fetching authorization key...</Title>
85+
</Container>
86+
);
87+
}
88+
89+
return (
90+
<Container>
91+
<Title>
92+
Hello {username}!
93+
</Title>
94+
<SubTitle>
95+
The CLI needs authorization to work.
96+
<br />Please paste the following code in the CLI:
97+
</SubTitle>
98+
<TokenContainer onClick={select} value={token} />
99+
</Container>
100+
);
101+
};

src/app/pages/CLI/index.js

Lines changed: 29 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -3,114 +3,61 @@ import React from 'react';
33
import styled from 'styled-components';
44
import { connect } from 'react-redux';
55
import { bindActionCreators } from 'redux';
6-
import SockJS from 'sockjs-client';
76

87
import type { CurrentUser } from 'common/types';
98

10-
import Centered from 'app/components/flex/Centered';
11-
import Title from 'app/components/text/Title';
12-
import SubTitle from 'app/components/text/SubTitle';
13-
import Button from '../../components/buttons/Button';
9+
import Navigation from 'app/containers/Navigation';
10+
1411
import { currentUserSelector } from '../../store/user/selectors';
1512
import userActionCreators from '../../store/user/actions';
1613

17-
const Buttons = styled.div`
18-
display: flex;
14+
import Prompt from './Prompt';
1915

20-
> button {
21-
margin: 1rem;
22-
}
16+
const Container = styled.div`
17+
height: 100%;
18+
width: 100%;
19+
margin: 1rem;
2320
`;
2421

2522
type State = {
26-
success: boolean,
2723
loading: boolean,
2824
error: ?string,
25+
token: string,
2926
};
3027

3128
type Props = {
3229
user: CurrentUser,
3330
signIn: typeof userActionCreators.signIn,
31+
getAuthToken: typeof userActionCreators.getAuthToken,
3432
};
3533

3634
const mapStateToProps = state => ({
3735
user: currentUserSelector(state),
3836
});
3937
const mapDispatchToProps = dispatch => ({
4038
signIn: bindActionCreators(userActionCreators.signIn, dispatch),
39+
getAuthToken: bindActionCreators(userActionCreators.getAuthToken, dispatch),
4140
});
4241
class CLI extends React.PureComponent {
4342
props: Props;
4443
state: State = {
45-
success: false,
46-
loading: false,
44+
loading: true,
45+
token: '',
4746
error: null,
4847
};
4948

50-
constructor(props) {
51-
super(props);
52-
53-
const port = this.getPort();
54-
if (port === null) {
55-
document.location.href = '/';
56-
return;
49+
componentDidMount() {
50+
if (this.props.user.jwt) {
51+
this.authorize();
5752
}
58-
59-
this.port = port;
6053
}
6154

62-
port: number;
63-
64-
getPort = () => {
65-
const match = document.location.search.match(/\?port=(.*)/);
66-
if (match) {
67-
const portString = match[1];
68-
return +portString;
69-
}
70-
return null;
71-
};
72-
73-
$authorizeCLI = (user: CurrentUser) =>
74-
new Promise((resolve, reject) => {
75-
try {
76-
this.setState({ loading: true });
77-
78-
const sock = new SockJS(
79-
`${location.protocol}//localhost:${this.port}/login`,
80-
);
81-
let signedIn = false;
82-
83-
sock.onopen = () => {
84-
signedIn = true;
85-
sock.send(JSON.stringify(user));
86-
resolve();
87-
};
88-
89-
sock.onmessage = () => {
90-
sock.close();
91-
};
92-
93-
sock.onclose = () => {
94-
if (!signedIn) {
95-
reject(
96-
new Error(
97-
'Could not connect with the CLI, please send a message to @Ives13.',
98-
),
99-
);
100-
}
101-
};
102-
} catch (e) {
103-
reject(e);
104-
}
105-
});
106-
10755
authorize = async () => {
56+
const { getAuthToken } = this.props;
10857
try {
109-
await this.$authorizeCLI(this.props.user);
58+
const token = await getAuthToken();
11059

111-
// Close window after succesfull authorization
112-
window.close();
113-
this.setState({ success: true });
60+
this.setState({ token, loading: false });
11461
} catch (e) {
11562
this.setState({ error: e.message });
11663
}
@@ -127,63 +74,19 @@ class CLI extends React.PureComponent {
12774

12875
render() {
12976
const { user } = this.props;
130-
const { error, loading, success } = this.state;
131-
132-
if (success) {
133-
return (
134-
<Centered horizontal vertical>
135-
<Title>Succesfully authorized the CLI</Title>
136-
<SubTitle>You can now close this window</SubTitle>
137-
</Centered>
138-
);
139-
}
140-
141-
if (error) {
142-
return (
143-
<Centered horizontal vertical>
144-
<Title>An error occured:</Title>
145-
<SubTitle>{error}</SubTitle>
146-
<Buttons>
147-
<Button href="/">Go to homepage</Button>
148-
</Buttons>
149-
</Centered>
150-
);
151-
}
152-
153-
if (loading) {
154-
return (
155-
<Centered horizontal vertical>
156-
<Title>Authorizing...</Title>
157-
</Centered>
158-
);
159-
}
160-
161-
if (!user.jwt) {
162-
return (
163-
<Centered horizontal vertical>
164-
<Title>Welcome to CodeSandbox!</Title>
165-
<SubTitle>
166-
To use the CLI you need to sign in with your GitHub account.
167-
</SubTitle>
168-
<Buttons>
169-
<Button onClick={this.signIn}>Sign in with Github</Button>
170-
</Buttons>
171-
</Centered>
172-
);
173-
}
77+
const { error, token, loading } = this.state;
17478

17579
return (
176-
<Centered horizontal vertical>
177-
<Title>Hello {user.username}!</Title>
178-
<SubTitle>
179-
To make use of the CLI you need to authorize it first,<br /> you can
180-
authorize by pressing {"'"}login{"'"}.
181-
</SubTitle>
182-
<Buttons>
183-
<Button red>Cancel</Button>
184-
<Button onClick={this.authorize}>Login</Button>
185-
</Buttons>
186-
</Centered>
80+
<Container>
81+
<Navigation title="CLI Authorization" />
82+
<Prompt
83+
error={error}
84+
token={token}
85+
loading={loading}
86+
username={user && user.username}
87+
signIn={this.signIn}
88+
/>
89+
</Container>
18790
);
18891
}
18992
}

src/app/store/user/actions.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ export const LOAD_USER_SANDBOXES = createAPIActions(
2424
'FETCH_SANDBOXES',
2525
);
2626
export const SEND_FEEDBACK_API = createAPIActions('FEEDBACK', 'SEND');
27+
export const GET_AUTH_TOKEN_API = createAPIActions('AUTH_TOKEN', 'FETCH');
2728

2829
const deleteCookie = (name: string) => {
2930
document.cookie = `${name}=; Path=/; expires=Thu, 01 Jan 1970 00:00:01 GMT;`;
@@ -81,6 +82,14 @@ const signIn = () => (dispatch: Function) =>
8182
});
8283
});
8384

85+
const getAuthToken = () => async (dispatch: Function): string => {
86+
const { data } = await dispatch(
87+
doRequest(GET_AUTH_TOKEN_API, 'auth/auth-token'),
88+
);
89+
90+
return data.token;
91+
};
92+
8493
const loadUserSandboxes = () => async (dispatch: Function) => {
8594
const { data } = await dispatch(doRequest(LOAD_USER_SANDBOXES, `sandboxes`));
8695

@@ -109,6 +118,7 @@ const sendFeedback = (message: string) => async (dispatch: Function) => {
109118
};
110119

111120
export default {
121+
getAuthToken,
112122
signOut,
113123
signIn,
114124
getCurrentUser,

0 commit comments

Comments
 (0)