basic login should work now

This commit is contained in:
overflowerror 2021-08-15 16:02:00 +02:00
parent b253feda0c
commit d122924fde
8 changed files with 157 additions and 28 deletions

View file

@ -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",

View file

@ -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;

View file

@ -9,6 +9,7 @@ export type Client = {
export const getClient = (authToken?: string): Client => {
if (authToken) {
console.log(authToken)
return {
axios: axios.create({
headers: {

View file

@ -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> {

View file

@ -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)
)
}
}

View file

@ -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()
}
})

View 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

View 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