mirror of
https://github.com/sigmasternchen/threadule
synced 2025-03-15 08:09:01 +00:00
basic login should work now
This commit is contained in:
parent
b253feda0c
commit
d122924fde
8 changed files with 157 additions and 28 deletions
|
@ -3,6 +3,8 @@
|
|||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@material-ui/core": "^4.12.3",
|
||||
"@material-ui/lab": "^4.0.0-alpha.60",
|
||||
"@testing-library/jest-dom": "^5.11.4",
|
||||
"@testing-library/react": "^11.1.0",
|
||||
"@testing-library/user-event": "^12.1.10",
|
||||
|
@ -10,12 +12,17 @@
|
|||
"@types/node": "^12.0.0",
|
||||
"@types/react": "^17.0.0",
|
||||
"@types/react-dom": "^17.0.0",
|
||||
"@types/react-router-dom": "^5.1.8",
|
||||
"axios": "^0.21.1",
|
||||
"formik": "^2.2.9",
|
||||
"formik-material-ui": "^3.0.1",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-router-dom": "^5.2.0",
|
||||
"react-scripts": "4.0.3",
|
||||
"typescript": "^4.1.2",
|
||||
"web-vitals": "^1.0.1"
|
||||
"web-vitals": "^1.0.1",
|
||||
"yup": "^0.32.9"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "react-scripts start",
|
||||
|
|
|
@ -1,15 +1,28 @@
|
|||
import React from 'react';
|
||||
import './App.css';
|
||||
import AuthProvider from "./auth/AuthProvider";
|
||||
import {BrowserRouter, Route, Switch} from "react-router-dom";
|
||||
import PrivateRoute from "./auth/PrivateRoute";
|
||||
import Login from "./components/Login";
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<AuthProvider>
|
||||
<div className="App">
|
||||
<h1>Hi</h1>
|
||||
</div>
|
||||
</AuthProvider>
|
||||
);
|
||||
return (
|
||||
<AuthProvider>
|
||||
<BrowserRouter>
|
||||
<Switch>
|
||||
<Route path="/login">
|
||||
<Login/>
|
||||
</Route>
|
||||
<PrivateRoute path="/">
|
||||
<h1>Private</h1>
|
||||
</PrivateRoute>
|
||||
<Route path="/*">
|
||||
<h1>Test</h1>
|
||||
</Route>
|
||||
</Switch>
|
||||
</BrowserRouter>
|
||||
</AuthProvider>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
||||
|
|
|
@ -9,6 +9,7 @@ export type Client = {
|
|||
|
||||
export const getClient = (authToken?: string): Client => {
|
||||
if (authToken) {
|
||||
console.log(authToken)
|
||||
return {
|
||||
axios: axios.create({
|
||||
headers: {
|
||||
|
|
|
@ -3,7 +3,7 @@ import {Client} from "../client";
|
|||
import {LoginParams, LoginResponse} from "../entities/login";
|
||||
import User from "../entities/User";
|
||||
|
||||
const API_PREFIX = "http://localhost:8080/authentication/"
|
||||
const API_PREFIX = "/api/authentication/"
|
||||
|
||||
class AuthenticationEndpoint extends Endpoint {
|
||||
constructor(client: Client) {
|
||||
|
@ -11,9 +11,7 @@ class AuthenticationEndpoint extends Endpoint {
|
|||
}
|
||||
|
||||
public async login(params: LoginParams): Promise<LoginResponse> {
|
||||
return this.post<LoginResponse>(API_PREFIX, {
|
||||
data: params
|
||||
})
|
||||
return this.post<LoginParams, LoginResponse>(API_PREFIX, params)
|
||||
}
|
||||
|
||||
public async getUser(): Promise<User> {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import {Client} from "../client";
|
||||
import {AxiosRequestConfig} from "axios";
|
||||
import {AxiosRequestConfig, AxiosResponse} from "axios";
|
||||
import ErrorStatus, {ErrorStatusGuard} from "../entities/ErrorStatus";
|
||||
|
||||
abstract class Endpoint {
|
||||
|
@ -14,47 +14,47 @@ abstract class Endpoint {
|
|||
throw "this endpoint needs an authorized client"
|
||||
}
|
||||
|
||||
private static handleResponse<T>(response: any): T {
|
||||
if (ErrorStatusGuard(response)) {
|
||||
throw (response as ErrorStatus)
|
||||
private static handleResponse<T>(response: AxiosResponse<T|ErrorStatus>): T {
|
||||
if (ErrorStatusGuard(response.data)) {
|
||||
throw (response.data as ErrorStatus)
|
||||
}
|
||||
|
||||
return response as T
|
||||
return response.data as T
|
||||
}
|
||||
|
||||
protected async get<T>(path: string, config?: AxiosRequestConfig): Promise<T> {
|
||||
return Endpoint.handleResponse<T>(
|
||||
this.client.axios.get(path, config)
|
||||
await this.client.axios.get<T|ErrorStatus>(path, config)
|
||||
)
|
||||
}
|
||||
|
||||
protected async post<T>(path: string, config?: AxiosRequestConfig): Promise<T> {
|
||||
protected async post<S, T>(path: string, data: S, config?: AxiosRequestConfig): Promise<T> {
|
||||
return Endpoint.handleResponse<T>(
|
||||
this.client.axios.post(path, config)
|
||||
await this.client.axios.post<T|ErrorStatus>(path, data, config)
|
||||
)
|
||||
}
|
||||
|
||||
protected async options<T>(path: string, config?: AxiosRequestConfig): Promise<T> {
|
||||
return Endpoint.handleResponse<T>(
|
||||
this.client.axios.options(path, config)
|
||||
await this.client.axios.options<T|ErrorStatus>(path, config)
|
||||
)
|
||||
}
|
||||
|
||||
protected async head<T>(path: string, config?: AxiosRequestConfig): Promise<T> {
|
||||
return Endpoint.handleResponse<T>(
|
||||
this.client.axios.head(path, config)
|
||||
await this.client.axios.head<T|ErrorStatus>(path, config)
|
||||
)
|
||||
}
|
||||
|
||||
protected async put<T>(path: string, config?: AxiosRequestConfig): Promise<T> {
|
||||
protected async put<S, T>(path: string, data: S, config?: AxiosRequestConfig): Promise<T> {
|
||||
return Endpoint.handleResponse<T>(
|
||||
this.client.axios.put(path, config)
|
||||
await this.client.axios.put<T|ErrorStatus>(path, data, config)
|
||||
)
|
||||
}
|
||||
|
||||
protected async delete<T>(path: string, config?: AxiosRequestConfig): Promise<T> {
|
||||
return Endpoint.handleResponse<T>(
|
||||
this.client.axios.delete(path, config)
|
||||
await this.client.axios.delete<T|ErrorStatus>(path, config)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,11 +41,12 @@ const AuthProvider: FunctionComponent<AuthProviderProps> = ({children}) => {
|
|||
})
|
||||
|
||||
// local new client
|
||||
const client = getClient(response.token)
|
||||
setClient(client)
|
||||
console.log(response)
|
||||
const tmpClient = getClient(response.token)
|
||||
setClient(tmpClient)
|
||||
|
||||
// local new authenticationEndpoint
|
||||
const tmpAuthenticationEndpoint = new AuthenticationEndpoint(client)
|
||||
const tmpAuthenticationEndpoint = new AuthenticationEndpoint(tmpClient)
|
||||
return await tmpAuthenticationEndpoint.getUser()
|
||||
}
|
||||
})
|
||||
|
|
22
frontend/src/auth/PrivateRoute.tsx
Normal file
22
frontend/src/auth/PrivateRoute.tsx
Normal file
|
@ -0,0 +1,22 @@
|
|||
import {FunctionComponent} from "react";
|
||||
import {useAuth} from "./AuthProvider";
|
||||
import {Redirect, Route, RouteProps} from "react-router-dom";
|
||||
|
||||
type PrivateRouteProps = RouteProps & {
|
||||
}
|
||||
|
||||
const PrivateRoute: FunctionComponent<PrivateRouteProps> = ({
|
||||
...props
|
||||
}) => {
|
||||
const { loggedIn } = useAuth();
|
||||
|
||||
const ok = loggedIn
|
||||
|
||||
if (ok) {
|
||||
return <Route {...props} />;
|
||||
} else {
|
||||
return <Redirect to="/login" />;
|
||||
}
|
||||
}
|
||||
|
||||
export default PrivateRoute
|
87
frontend/src/components/Login/index.tsx
Normal file
87
frontend/src/components/Login/index.tsx
Normal file
|
@ -0,0 +1,87 @@
|
|||
import {Button, Grid, LinearProgress} from "@material-ui/core";
|
||||
import Alert from '@material-ui/lab/Alert';
|
||||
import {Field, Formik, FormikHelpers} from "formik"
|
||||
import {TextField} from "formik-material-ui";
|
||||
import {useAuth} from "../../auth/AuthProvider";
|
||||
import * as yup from "yup"
|
||||
import {useState} from "react";
|
||||
|
||||
type LoginFormProps = {
|
||||
username: string
|
||||
password: string
|
||||
}
|
||||
|
||||
const LoginFormValidationSchema = yup.object({
|
||||
username: yup.string().required(),
|
||||
password: yup.string().required()
|
||||
})
|
||||
|
||||
const Login = () => {
|
||||
|
||||
const auth = useAuth()
|
||||
const [error, setError] = useState<string|null>(null)
|
||||
|
||||
const onSubmit = async (values: LoginFormProps, helper: FormikHelpers<LoginFormProps>) => {
|
||||
console.log(values)
|
||||
try {
|
||||
const user = await auth.login(values.username, values.password)
|
||||
console.log(user)
|
||||
} catch (e) {
|
||||
helper.setSubmitting(false)
|
||||
setError("Login failed!")
|
||||
console.error(e)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Grid container xs={12} justifyContent="center">
|
||||
<Grid item container xs={4} spacing={2}>
|
||||
<Formik<LoginFormProps>
|
||||
initialValues={{
|
||||
username: "",
|
||||
password: ""
|
||||
}}
|
||||
onSubmit={onSubmit}
|
||||
validationSchema={LoginFormValidationSchema}
|
||||
>
|
||||
{({submitForm, isSubmitting}) => <>
|
||||
<Grid item xs={12}>
|
||||
<Field
|
||||
component={TextField}
|
||||
label="Username"
|
||||
name="username"
|
||||
variant="outlined"
|
||||
fullWidth
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<Field
|
||||
component={TextField}
|
||||
label="Password"
|
||||
name="password"
|
||||
type="password"
|
||||
variant="outlined"
|
||||
fullWidth
|
||||
/>
|
||||
</Grid>
|
||||
{ isSubmitting && <LinearProgress /> }
|
||||
<Grid item xs={12}>
|
||||
<Button
|
||||
variant={"contained"}
|
||||
onClick={submitForm}
|
||||
fullWidth
|
||||
>
|
||||
Submit
|
||||
</Button>
|
||||
</Grid>
|
||||
{ error && <Grid item xs={12}>
|
||||
<Alert severity="error">{error}</Alert>
|
||||
</Grid>}
|
||||
</>}
|
||||
</Formik>
|
||||
</Grid>
|
||||
</Grid>
|
||||
)
|
||||
}
|
||||
|
||||
export default Login
|
Loading…
Reference in a new issue