Implement login and logout with JWT
This commit is contained in:
Generated
+5
@@ -9146,6 +9146,11 @@
|
||||
"integrity": "sha512-aUnNwqMOXw3yvErjMPSQu6qIIzUmT1e5KcU1OZxRDU1g/am6mzBvcrmLAYwzmB59BHPrh5/tKaiF4OPhqRWESQ==",
|
||||
"dev": true
|
||||
},
|
||||
"js-cookie": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-2.2.0.tgz",
|
||||
"integrity": "sha1-Gywnmm7s44ChIWi5JIUmWzWx7/s="
|
||||
},
|
||||
"js-tokens": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
|
||||
|
||||
@@ -94,6 +94,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^0.18.0",
|
||||
"js-cookie": "^2.2.0",
|
||||
"mobx": "^5.0.3",
|
||||
"mobx-react": "^5.2.3",
|
||||
"normalize.css": "^8.0.0",
|
||||
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
import axios from "axios";
|
||||
import * as Cookies from "js-cookie";
|
||||
|
||||
const url = `${process.env.API_URL}/api-token-auth/`;
|
||||
|
||||
export async function generateToken(username: string, password: string): Promise<string> {
|
||||
try {
|
||||
const resp = await axios.post(url, {
|
||||
username,
|
||||
password,
|
||||
});
|
||||
return resp.data["token"];
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
export function setTokenCookie(token: string) {
|
||||
Cookies.set("jwt", token);
|
||||
}
|
||||
|
||||
export function getTokenCookie(): string {
|
||||
return Cookies.get("jwt");
|
||||
}
|
||||
|
||||
export function deleteTokenCookie(): string {
|
||||
return Cookies.remove("jwt");
|
||||
}
|
||||
@@ -15,6 +15,7 @@ class AdminSidebar extends React.Component<AdminSiderbarProps, AdminSiderbarStat
|
||||
<div className="admin-sidebar">
|
||||
<AdminSidebarLink to="/admin" path={path}>Home</AdminSidebarLink>
|
||||
<AdminSidebarLink to="/admin/events" path={path}>Events</AdminSidebarLink>
|
||||
<AdminSidebarLink to="/admin/logout" path={path}>Logout</AdminSidebarLink>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
.admin-login-page {
|
||||
input {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
import * as React from "react";
|
||||
import Helmet from "react-helmet";
|
||||
import { Redirect } from "react-router-dom";
|
||||
import { generateToken, setTokenCookie, getTokenCookie } from "../../auth";
|
||||
import "./AdminLoginPage.scss";
|
||||
|
||||
export interface AdminLoginPageProps {
|
||||
history: {
|
||||
push: (to: string) => void;
|
||||
};
|
||||
}
|
||||
export interface AdminLoginPageState {
|
||||
username: string;
|
||||
password: string;
|
||||
existingToken: string;
|
||||
}
|
||||
|
||||
class AdminLoginPage extends React.Component<AdminLoginPageProps, AdminLoginPageState> {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
username: "",
|
||||
password: "",
|
||||
existingToken: getTokenCookie(),
|
||||
};
|
||||
}
|
||||
|
||||
handleSubmit = async (e) => {
|
||||
e.preventDefault();
|
||||
const { username, password } = this.state;
|
||||
const { history } = this.props;
|
||||
|
||||
try {
|
||||
const token = await generateToken(username, password);
|
||||
console.log("JWT token:", token);
|
||||
setTokenCookie(token);
|
||||
|
||||
history.push("/admin");
|
||||
} catch (err) {
|
||||
console.error("Failed to log in!");
|
||||
}
|
||||
}
|
||||
|
||||
handleUserNameChange = (e) => {
|
||||
this.setState({
|
||||
username: e.target.value,
|
||||
});
|
||||
}
|
||||
|
||||
handlePasswordChange = (e) => {
|
||||
this.setState({
|
||||
password: e.target.value,
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const { username, password, existingToken } = this.state;
|
||||
if (existingToken) {
|
||||
return <Redirect to="/admin" />;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="admin-login-page">
|
||||
<Helmet>
|
||||
<link rel="canonical" href="https://sik.ayy.fi/admin/login" />
|
||||
</Helmet>
|
||||
<form onSubmit={this.handleSubmit}>
|
||||
<label>Username
|
||||
<input type="text" name="username" value={username} onChange={this.handleUserNameChange} />
|
||||
</label>
|
||||
<label>Password
|
||||
<input type="password" name="password" value={password} onChange={this.handlePasswordChange} />
|
||||
</label>
|
||||
<input type="submit" />
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default AdminLoginPage;
|
||||
@@ -0,0 +1,2 @@
|
||||
import AdminLoginPage from "./AdminLoginPage";
|
||||
export default AdminLoginPage;
|
||||
@@ -0,0 +1,21 @@
|
||||
import * as React from "react";
|
||||
import { Redirect } from "react-router-dom";
|
||||
import { deleteTokenCookie } from "../../auth";
|
||||
|
||||
export interface AdminLogoutPageProps {}
|
||||
export interface AdminLogoutPageState {}
|
||||
|
||||
class AdminLogoutPage extends React.Component<AdminLogoutPageProps, AdminLogoutPageState> {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
deleteTokenCookie();
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Redirect to="/admin/login" />
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default AdminLogoutPage;
|
||||
@@ -0,0 +1,2 @@
|
||||
import AdminLogoutPage from "./AdminLogoutPage";
|
||||
export default AdminLogoutPage;
|
||||
+20
-2
@@ -1,6 +1,6 @@
|
||||
import * as React from "react";
|
||||
import { Fragment } from "react";
|
||||
import { Switch, Route, DefaultRoute } from "react-router-dom";
|
||||
import { Switch, Route, Redirect } from "react-router-dom";
|
||||
import Helmet from "react-helmet";
|
||||
import FrontPage from "./pages/FrontPage";
|
||||
import GuildPage from "./pages/GuildPage";
|
||||
@@ -11,22 +11,39 @@ import "./index.scss";
|
||||
import AdminFrontPage from "./pages/AdminFrontPage";
|
||||
import AdminEventPage from "./pages/AdminEventPage";
|
||||
import AdminCommonPage from "./pages/AdminCommonPage";
|
||||
import AdminLoginPage from "./pages/AdminLoginPage";
|
||||
import { getTokenCookie } from "./auth";
|
||||
import AdminLogoutPage from "./pages/AdminLogoutPage";
|
||||
|
||||
const renderPage = (Page) => (props): JSX.Element => {
|
||||
return <CommonPage page={Page} {...props} />;
|
||||
};
|
||||
|
||||
const renderAdminPage = (Page) => (props): JSX.Element => {
|
||||
const renderAdminLoginPage = (Page) => (props): JSX.Element => {
|
||||
return <AdminCommonPage page={Page} {...props} />;
|
||||
};
|
||||
|
||||
const renderAdminPage = (Page) => (props): JSX.Element => {
|
||||
const token = getTokenCookie();
|
||||
if (token) {
|
||||
return <AdminCommonPage page={Page} {...props} />;
|
||||
} else {
|
||||
return <Redirect to="/admin/login" />;
|
||||
}
|
||||
};
|
||||
|
||||
const commonRoutes = [
|
||||
{ path: "/", page: FrontPage },
|
||||
{ path: "/kilta", page: GuildPage },
|
||||
];
|
||||
|
||||
const adminLoginRoutes = [
|
||||
{ path: "/admin/login", page: AdminLoginPage },
|
||||
];
|
||||
|
||||
const adminRoutes = [
|
||||
{ path: "/admin/events", page: AdminEventPage },
|
||||
{ path: "/admin/logout", page: AdminLogoutPage },
|
||||
{ path: "/admin", page: AdminFrontPage },
|
||||
];
|
||||
|
||||
@@ -45,6 +62,7 @@ const Routes = () => (
|
||||
}} />
|
||||
<Switch>
|
||||
{ commonRoutes.map(r => <Route key={r.path} exact path={r.path} render={renderPage(r.page) }/>) }
|
||||
{ adminLoginRoutes.map(r => <Route key={r.path} exact path={r.path} render={renderAdminLoginPage(r.page) }/>) }
|
||||
{ adminRoutes.map(r => <Route key={r.path} exact path={r.path} render={renderAdminPage(r.page) }/>) }
|
||||
<Route component={NotFoundPage} />
|
||||
</Switch>
|
||||
|
||||
Reference in New Issue
Block a user