-
-
Save bpas247/54c686975ee716d8fc663343eecf0922 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { Component } from "react"; | |
import { render } from "react-dom"; | |
import { | |
BrowserRouter as Router, | |
Switch, | |
Route, | |
Link, | |
Redirect, | |
withRouter, | |
} from "react-router-dom"; | |
import { Login } from "./Authentication"; | |
import AuthenticatedRoute from "./AuthenticatedRoute"; | |
class App extends Component { | |
constructor(props) { | |
super(props); | |
this.state = { | |
data: [], | |
loaded: false, | |
placeholder: "Loading", | |
}; | |
} | |
componentDidMount() { | |
fetch("api/characters") | |
.then((response) => { | |
if (response.status > 400) { | |
return this.setState(() => { | |
return { placeholder: "Something went wrong!" }; | |
}); | |
} | |
return response.json(); | |
}) | |
.then((data) => { | |
this.setState(() => { | |
return { | |
data, | |
loaded: true, | |
}; | |
}); | |
}); | |
} | |
render() { | |
return ( | |
<Router> | |
<div> | |
<nav> | |
<ul> | |
<li> | |
<Link to="/">Home</Link> | |
</li> | |
<li> | |
<Link to="/about">About</Link> | |
</li> | |
<li> | |
<Link to="/users">Users</Link> | |
</li> | |
</ul> | |
</nav> | |
{/* A <Switch> looks through its children <Route>s and | |
renders the first one that matches the current URL. */} | |
<Switch> | |
<AuthenticatedRoute path="/about"> | |
<About /> | |
</AuthenticatedRoute> | |
<AuthenticatedRoute path="/users"> | |
<Users /> | |
</AuthenticatedRoute> | |
<Route path="/login"> | |
<Login /> | |
</Route> | |
<Route path="/"> | |
<Home /> | |
</Route> | |
</Switch> | |
</div> | |
</Router> | |
); | |
} | |
} | |
class CharacterList extends Component { | |
constructor(props) { | |
super(props); | |
this.state = { | |
data: [], | |
loaded: false, | |
placeholder: "Loading", | |
}; | |
} | |
componentDidMount() { | |
fetch("api/characters") | |
.then((response) => { | |
if (response.status > 400) { | |
return this.setState(() => { | |
return { placeholder: "Something went wrong!" }; | |
}); | |
} | |
return response.json(); | |
}) | |
.then((data) => { | |
this.setState(() => { | |
return { | |
data, | |
loaded: true, | |
}; | |
}); | |
}); | |
} | |
render() { | |
return ( | |
<ul> | |
{this.state.data.map((character) => { | |
return ( | |
<li key={character.char_name}> | |
<h2>{character.char_name}</h2> | |
<h3>{character.char_race}</h3> | |
</li> | |
); | |
})} | |
</ul> | |
); | |
} | |
} | |
class CreateAccount extends Component { | |
constructor(props) { | |
super(props); | |
this.state = { | |
userName: "", | |
password: "", | |
confirmPassword: "", | |
passwordErrorMessage: "", | |
redirect: false, | |
}; | |
this.handleUserNameChange = this.handleUserNameChange.bind(this); | |
this.handlePasswordChange = this.handlePasswordChange.bind(this); | |
this.handleConfirmPasswordChange = this.handleConfirmPasswordChange.bind( | |
this | |
); | |
this.handleSubmit = this.handleSubmit.bind(this); | |
} | |
handleUserNameChange(event) { | |
this.setState({ userName: event.target.value }); | |
} | |
handlePasswordChange(event) { | |
this.setState({ password: event.target.value }); | |
} | |
handleConfirmPasswordChange(event) { | |
this.setState({ confirmPassword: event.target.value }); | |
} | |
handleSubmit(event) { | |
if (this.state.password !== this.state.confirmPassword) { | |
this.setState({ | |
passwordErrorMessage: "Provided passwords do not match", | |
password: "", | |
confirmPassword: "", | |
errorMessage: "", | |
}); | |
event.preventDefault(); | |
return; | |
} | |
const requestOptions = { | |
method: "POST", | |
headers: { "Content-Type": "application/json" }, | |
body: JSON.stringify({ | |
username: this.state.userName, | |
password: this.state.password, | |
}), | |
}; | |
fetch("api/users/", requestOptions) | |
.then((response) => { | |
console.log(requestOptions.body); | |
// check for error response | |
if (!response.ok) { | |
// get error message from body or default to response status | |
const data = response.json(); | |
const error = (data && data.message) || response.status; | |
return Promise.reject(error); | |
} | |
return response.json(); | |
}) | |
.then((data) => | |
this.setState({ | |
userName: "", | |
password: "", | |
confirmPassword: "", | |
redirect: true, | |
}) | |
) | |
.catch((error) => { | |
this.setState({ passwordErrorMessage: error.toString() }); | |
console.error("There was an error!", error); | |
}); | |
event.preventDefault(); | |
} | |
render() { | |
if (this.state.redirect) { | |
return <Redirect to="/about" />; | |
} | |
return ( | |
<form onSubmit={this.handleSubmit}> | |
<label> | |
Username: | |
<input | |
type="text" | |
value={this.state.userName} | |
onChange={this.handleUserNameChange} | |
/> | |
</label> | |
<p>{this.state.passwordErrorMessage}</p> | |
<label> | |
Password: | |
<input | |
type="text" | |
value={this.state.password} | |
onChange={this.handlePasswordChange} | |
/> | |
</label> | |
<label> | |
Confirm Password: | |
<input | |
type="text" | |
value={this.state.confirmPassword} | |
onChange={this.handleConfirmPasswordChange} | |
/> | |
</label> | |
<input type="submit" value="Submit" /> | |
</form> | |
); | |
} | |
} | |
function About() { | |
return <h2>About</h2>; | |
} | |
function Users() { | |
return <h2>Users</h2>; | |
} | |
function Home() { | |
return ( | |
<div> | |
<h2>Home</h2> | |
<CreateAccount /> | |
</div> | |
); | |
} | |
export default withRouter(App); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Cookies from "js-cookie"; | |
import React, { Component } from "react"; | |
import { | |
BrowserRouter as Router, | |
Switch, | |
Route, | |
Link, | |
Redirect, | |
useHistory, | |
withRouter, | |
} from "react-router-dom"; | |
export const getAccessToken = () => Cookies.get("access_token"); | |
export const getRefreshToken = () => Cookies.get("refresh_token"); | |
export const isAuthenticated = () => !!getAccessToken(); | |
function refreshTokens() { | |
const requestOptions = { | |
method: "POST", | |
headers: { "Content-Type": "application/json" }, | |
body: JSON.stringify({ | |
refresh: getRefreshToken(), | |
}), | |
}; | |
return fetch("token/refresh/", requestOptions) | |
.then((response) => { | |
console.log(requestOptions.body); | |
return response.json(); | |
}) | |
.then((data) => { | |
return data; | |
}) | |
.catch((error) => { | |
console.error("There was an error!", error); | |
}); | |
} | |
function setTokens(access_token, refresh_token) { | |
const expires = (tokens.expires_in || 60 * 60) * 1000; | |
const inOneHour = new Date(new Date().getTime() + expires); | |
// you will have the exact same setters in your Login page/app too | |
Cookies.set("access_token", tokens.access_token, { expires: inOneHour }); | |
Cookies.set("refresh_token", tokens.refresh_token); | |
} | |
export const authenticate = async () => { | |
if (getRefreshToken()) { | |
try { | |
const tokens = await refreshTokens(); // call an API, returns tokens | |
setTokens(tokes.access_token, getRefreshToken()); | |
return true; | |
} catch (error) { | |
this.props.history.push("/login"); | |
return false; | |
} | |
} | |
this.props.history.push("/login"); | |
return false; | |
}; | |
class AuthenticateBeforeRender extends Component { | |
constructor(props) { | |
super(props); | |
this.state = { | |
isAuthenticated: false, | |
}; | |
} | |
componentDidMount() { | |
authenticate().then((isAuthenticated) => { | |
this.setState({ isAuthenticated }); | |
}); | |
} | |
render() { | |
return this.state.isAuthenticated ? this.props.render() : null; | |
} | |
} | |
const WrappedThingy = withRouter(AuthenticateBeforeRender); | |
const AuthenticatedRoute = ({ component: Component, exact, path }) => ( | |
<Route | |
exact={exact} | |
path={path} | |
render={(props) => | |
isAuthenticated() ? ( | |
<Component {...props} /> | |
) : ( | |
<WrappedThingy render={() => <Component {...props} />} /> | |
) | |
} | |
/> | |
); | |
export default AuthenticatedRoute |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Cookies from "js-cookie"; | |
import React, { Component } from "react"; | |
import { | |
BrowserRouter as Router, | |
Switch, | |
Route, | |
Link, | |
Redirect, | |
useHistory, | |
} from "react-router-dom"; | |
export class Login extends Component { | |
constructor(props) { | |
super(props); | |
this.state = { | |
userName: "", | |
password: "", | |
passwordErrorMessage: "", | |
redirect: false, | |
}; | |
this.handleUserNameChange = this.handleUserNameChange.bind(this); | |
this.handlePasswordChange = this.handlePasswordChange.bind(this); | |
this.handleSubmit = this.handleSubmit.bind(this); | |
} | |
handleUserNameChange(event) { | |
this.setState({ userName: event.target.value }); | |
} | |
handlePasswordChange(event) { | |
this.setState({ password: event.target.value }); | |
} | |
handleSubmit(event) { | |
if (this.state.password !== this.state.confirmPassword) { | |
this.setState({ | |
passwordErrorMessage: "Provided passwords do not match", | |
password: "", | |
errorMessage: "", | |
}); | |
event.preventDefault(); | |
return; | |
} | |
const requestOptions = { | |
method: "POST", | |
headers: { "Content-Type": "application/json" }, | |
body: JSON.stringify({ | |
username: this.state.userName, | |
password: this.state.password, | |
}), | |
}; | |
fetch("token/obtain/", requestOptions) | |
.then((response) => { | |
console.log(requestOptions.body); | |
// check for error response | |
if (!response.ok) { | |
// get error message from body or default to response status | |
const data = response.json(); | |
const error = (data && data.message) || response.status; | |
return Promise.reject(error); | |
} | |
return response.json(); | |
}) | |
.then((data) => { | |
setTokens(data.access, data.refresh); | |
}) | |
.catch((error) => { | |
this.setState({ passwordErrorMessage: error.toString() }); | |
console.error("There was an error!", error); | |
}); | |
event.preventDefault(); | |
} | |
render() { | |
return ( | |
<div> | |
<h1>Login</h1> | |
<form onSubmit={this.handleSubmit}> | |
<label> | |
Username: | |
<input | |
type="text" | |
value={this.state.userName} | |
onChange={this.handleUserNameChange} | |
/> | |
</label> | |
<p>{this.state.passwordErrorMessage}</p> | |
<label> | |
Password: | |
<input | |
type="text" | |
value={this.state.password} | |
onChange={this.handlePasswordChange} | |
/> | |
</label> | |
<input type="submit" value="Submit" /> | |
</form> | |
</div> | |
); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { Component } from "react"; | |
import { BrowserRouter } from "react-router-dom"; | |
import { render } from "react-dom"; | |
import App from "./Components/App"; | |
render( | |
<BrowserRouter> | |
<App /> | |
</BrowserRouter>, | |
document.getElementById("app") | |
); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment