Added login page
This commit is contained in:
parent
472f43a950
commit
0f0e5d9d1c
@ -26,7 +26,10 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="ClientApp\src\common\ErrorDispatcher.ts" />
|
||||
<None Remove="ClientApp\src\common\ServiceBase.ts" />
|
||||
<None Remove="ClientApp\src\components\auth\Auth.tsx" />
|
||||
<None Remove="ClientApp\src\components\auth\AuthService.ts" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
31
Birdmap/ClientApp/src/App.test.js
Normal file
31
Birdmap/ClientApp/src/App.test.js
Normal file
@ -0,0 +1,31 @@
|
||||
"use strict";
|
||||
var __assign = (this && this.__assign) || function () {
|
||||
__assign = Object.assign || function(t) {
|
||||
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
||||
s = arguments[i];
|
||||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
||||
t[p] = s[p];
|
||||
}
|
||||
return t;
|
||||
};
|
||||
return __assign.apply(this, arguments);
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var React = require("react");
|
||||
var ReactDOM = require("react-dom");
|
||||
var react_redux_1 = require("react-redux");
|
||||
var react_router_dom_1 = require("react-router-dom");
|
||||
var App_1 = require("./App");
|
||||
it('renders without crashing', function () {
|
||||
var storeFake = function (state) { return ({
|
||||
default: function () { },
|
||||
subscribe: function () { },
|
||||
dispatch: function () { },
|
||||
getState: function () { return (__assign({}, state)); }
|
||||
}); };
|
||||
var store = storeFake({});
|
||||
ReactDOM.render(React.createElement(react_redux_1.Provider, { store: store },
|
||||
React.createElement(react_router_dom_1.MemoryRouter, null,
|
||||
React.createElement(App_1.default, null))), document.createElement('div'));
|
||||
});
|
||||
//# sourceMappingURL=App.test.js.map
|
1
Birdmap/ClientApp/src/App.test.js.map
Normal file
1
Birdmap/ClientApp/src/App.test.js.map
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"App.test.js","sourceRoot":"","sources":["App.test.tsx"],"names":[],"mappings":";;;;;;;;;;;;;AAAA,6BAA+B;AAC/B,oCAAsC;AACtC,2CAAuC;AACvC,qDAAgD;AAChD,6BAAwB;AAExB,EAAE,CAAC,0BAA0B,EAAE;IAC3B,IAAM,SAAS,GAAG,UAAC,KAAU,IAAK,OAAA,CAAC;QAC/B,OAAO,EAAE,cAAO,CAAC;QACjB,SAAS,EAAE,cAAO,CAAC;QACnB,QAAQ,EAAE,cAAO,CAAC;QAClB,QAAQ,EAAE,cAAM,OAAA,cAAM,KAAK,EAAG,EAAd,CAAc;KACjC,CAAC,EALgC,CAKhC,CAAC;IACH,IAAM,KAAK,GAAG,SAAS,CAAC,EAAE,CAAQ,CAAC;IAEnC,QAAQ,CAAC,MAAM,CACX,oBAAC,sBAAQ,IAAC,KAAK,EAAE,KAAK;QAClB,oBAAC,+BAAY;YACT,oBAAC,aAAG,OAAE,CACK,CACR,EAAE,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC;AACpD,CAAC,CAAC,CAAC"}
|
@ -1,16 +1,93 @@
|
||||
import * as React from 'react';
|
||||
import { Route } from 'react-router';
|
||||
import Layout from './components/Layout';
|
||||
import { Box, Container } from '@material-ui/core';
|
||||
import AppBar from '@material-ui/core/AppBar';
|
||||
import blue from '@material-ui/core/colors/blue';
|
||||
import { createMuiTheme } from '@material-ui/core/styles';
|
||||
import Toolbar from '@material-ui/core/Toolbar';
|
||||
import Typography from '@material-ui/core/Typography';
|
||||
import { ThemeProvider } from '@material-ui/styles';
|
||||
import React, { useState } from 'react';
|
||||
import { BrowserRouter, NavLink, Redirect, Route, Switch } from 'react-router-dom';
|
||||
import Auth from './components/auth/Auth';
|
||||
import AuthService from './components/auth/AuthService';
|
||||
import Home from './components/Home';
|
||||
import Counter from './components/Counter';
|
||||
import FetchData from './components/FetchData';
|
||||
import './custom.css';
|
||||
|
||||
import './custom.css'
|
||||
|
||||
export default () => (
|
||||
<Layout>
|
||||
<Route exact path='/' component={Home} />
|
||||
<Route path='/counter' component={Counter} />
|
||||
<Route path='/fetch-data/:startDateIndex?' component={FetchData} />
|
||||
</Layout>
|
||||
const theme = createMuiTheme({
|
||||
palette: {
|
||||
primary: {
|
||||
main: blue[800]
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
function App() {
|
||||
const [authenticated, setAuthenticated] = useState(AuthService.isAuthenticated());
|
||||
|
||||
const onAuthenticated = () => {
|
||||
setAuthenticated(AuthService.isAuthenticated());
|
||||
};
|
||||
|
||||
const LoginComponent = () => {
|
||||
return (
|
||||
<Auth onAuthenticated={onAuthenticated} />
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<ThemeProvider theme={theme}>
|
||||
<BrowserRouter>
|
||||
<Switch>
|
||||
<PublicRoute path="/login" component={LoginComponent} />
|
||||
<PrivateRoute path="/" exact authenticated={authenticated} component={Home} />
|
||||
</Switch>
|
||||
</BrowserRouter>
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
||||
|
||||
const PublicRoute = ({ component: Component, ...rest }: { [x: string]: any, component: any}) => {
|
||||
return (
|
||||
<Route {...rest} render={matchProps => (
|
||||
<NoLayout component={Component} {...matchProps} />
|
||||
)} />
|
||||
);
|
||||
}
|
||||
|
||||
const PrivateRoute = ({ component: Component, authenticated: Authenticated, ...rest }: { [x: string]: any, component: any, authenticated: any }) => {
|
||||
return (
|
||||
<Route {...rest} render={matchProps => (
|
||||
Authenticated
|
||||
? <DefaultLayout component={Component} {...matchProps} />
|
||||
: <Redirect to='/login' />
|
||||
)} />
|
||||
);
|
||||
};
|
||||
|
||||
const NoLayout = ({ component: Component, ...rest }: { [x: string]: any, component: any }) => {
|
||||
return (
|
||||
<Component {...rest} />
|
||||
);
|
||||
};
|
||||
|
||||
const DefaultLayout = ({ component: Component, ...rest }: { [x: string]: any, component: any }) => {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<AppBar position="static">
|
||||
<Toolbar>
|
||||
<Typography component={'span'}>
|
||||
<Container className="nav-menu">
|
||||
<NavLink exact to="/" className="nav-menu-item" activeStyle={{ color: 'white' }}>Dashboard</NavLink>
|
||||
<NavLink exact to="/login" className="nav-menu-item" activeStyle={{ color: 'white' }}>Login</NavLink>
|
||||
</Container>
|
||||
</Typography>
|
||||
</Toolbar>
|
||||
</AppBar>
|
||||
<Box style={{ margin: '32px' }}>
|
||||
<Component {...rest} />
|
||||
</Box>
|
||||
</React.Fragment>
|
||||
);
|
||||
};
|
14
Birdmap/ClientApp/src/common/ErrorDispatcher.js
Normal file
14
Birdmap/ClientApp/src/common/ErrorDispatcher.js
Normal file
@ -0,0 +1,14 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var ErrorDispatcher = {
|
||||
errorHandlers: [],
|
||||
registerErrorHandler: function (errorHandlerFn) {
|
||||
this.errorHandlers.push(errorHandlerFn);
|
||||
},
|
||||
raiseError: function (errorMessage) {
|
||||
for (var i = 0; i < this.errorHandlers.length; i++)
|
||||
this.errorHandlers[i](errorMessage);
|
||||
}
|
||||
};
|
||||
exports.default = ErrorDispatcher;
|
||||
//# sourceMappingURL=ErrorDispatcher.js.map
|
1
Birdmap/ClientApp/src/common/ErrorDispatcher.js.map
Normal file
1
Birdmap/ClientApp/src/common/ErrorDispatcher.js.map
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"ErrorDispatcher.js","sourceRoot":"","sources":["ErrorDispatcher.ts"],"names":[],"mappings":";;AAAA,IAAM,eAAe,GAAG;IACtB,aAAa,EAAE,EAAE;IAEjB,oBAAoB,YAAC,cAAc;QACjC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAC1C,CAAC;IAED,UAAU,YAAC,YAAY;QACrB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,CAAC,EAAE;YAChD,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;IACxC,CAAC;CACF,CAAC;AAEF,kBAAe,eAAe,CAAC"}
|
14
Birdmap/ClientApp/src/common/ErrorDispatcher.ts
Normal file
14
Birdmap/ClientApp/src/common/ErrorDispatcher.ts
Normal file
@ -0,0 +1,14 @@
|
||||
const ErrorDispatcher = {
|
||||
errorHandlers: [],
|
||||
|
||||
registerErrorHandler(errorHandlerFn) {
|
||||
this.errorHandlers.push(errorHandlerFn);
|
||||
},
|
||||
|
||||
raiseError(errorMessage) {
|
||||
for (let i = 0; i < this.errorHandlers.length; i++)
|
||||
this.errorHandlers[i](errorMessage);
|
||||
}
|
||||
};
|
||||
|
||||
export default ErrorDispatcher;
|
50
Birdmap/ClientApp/src/common/ServiceBase.js
Normal file
50
Birdmap/ClientApp/src/common/ServiceBase.js
Normal file
@ -0,0 +1,50 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var ErrorDispatcher_1 = require("./ErrorDispatcher");
|
||||
function get(url) {
|
||||
var options = {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': sessionStorage.getItem('user')
|
||||
}
|
||||
};
|
||||
return makeRequest(url, options);
|
||||
}
|
||||
function post(url, request) {
|
||||
var options = {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': sessionStorage.getItem('user')
|
||||
},
|
||||
body: "",
|
||||
};
|
||||
if (request)
|
||||
options.body = JSON.stringify(request);
|
||||
return makeRequest(url, options);
|
||||
}
|
||||
function makeRequest(url, options) {
|
||||
return fetch(url, options)
|
||||
.then(ensureResponseSuccess)
|
||||
.catch(errorHandler);
|
||||
}
|
||||
function ensureResponseSuccess(response) {
|
||||
if (!response.ok)
|
||||
return response.json()
|
||||
.then(function (data) { return errorHandler(data); });
|
||||
return response.text()
|
||||
.then(function (text) { return text.length ? JSON.parse(text) : {}; });
|
||||
}
|
||||
function errorHandler(response) {
|
||||
console.log(response);
|
||||
if (response && response.Error)
|
||||
ErrorDispatcher_1.default.raiseError(response.Error);
|
||||
return Promise.reject();
|
||||
}
|
||||
exports.default = {
|
||||
get: get,
|
||||
post: post,
|
||||
makeRequest: makeRequest
|
||||
};
|
||||
//# sourceMappingURL=ServiceBase.js.map
|
1
Birdmap/ClientApp/src/common/ServiceBase.js.map
Normal file
1
Birdmap/ClientApp/src/common/ServiceBase.js.map
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"ServiceBase.js","sourceRoot":"","sources":["ServiceBase.ts"],"names":[],"mappings":";;AAAA,qDAAgD;AAEhD,SAAS,GAAG,CAAC,GAAG;IACZ,IAAI,OAAO,GAAG;QACV,MAAM,EAAE,KAAK;QACb,OAAO,EAAE;YACL,cAAc,EAAE,kBAAkB;YAClC,eAAe,EAAE,cAAc,CAAC,OAAO,CAAC,MAAM,CAAC;SAClD;KACJ,CAAC;IAEF,OAAO,WAAW,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;AACrC,CAAC;AAED,SAAS,IAAI,CAAC,GAAG,EAAE,OAAO;IACtB,IAAI,OAAO,GAAG;QACV,MAAM,EAAE,MAAM;QACd,OAAO,EAAE;YACL,cAAc,EAAE,kBAAkB;YAClC,eAAe,EAAE,cAAc,CAAC,OAAO,CAAC,MAAM,CAAC;SAClD;QACD,IAAI,EAAE,EAAE;KACX,CAAC;IAEF,IAAI,OAAO;QACP,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IAE3C,OAAO,WAAW,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;AACrC,CAAC;AAED,SAAS,WAAW,CAAC,GAAG,EAAE,OAAO;IAC7B,OAAO,KAAK,CAAC,GAAG,EAAE,OAAO,CAAC;SACrB,IAAI,CAAC,qBAAqB,CAAC;SAC3B,KAAK,CAAC,YAAY,CAAC,CAAC;AAC7B,CAAC;AAED,SAAS,qBAAqB,CAAC,QAAQ;IACnC,IAAI,CAAC,QAAQ,CAAC,EAAE;QACZ,OAAO,QAAQ,CAAC,IAAI,EAAE;aACjB,IAAI,CAAC,UAAA,IAAI,IAAI,OAAA,YAAY,CAAC,IAAI,CAAC,EAAlB,CAAkB,CAAC,CAAC;IAE1C,OAAO,QAAQ,CAAC,IAAI,EAAE;SACjB,IAAI,CAAC,UAAA,IAAI,IAAI,OAAA,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,EAAnC,CAAmC,CAAC,CAAC;AAC3D,CAAC;AAED,SAAS,YAAY,CAAC,QAAQ;IAC1B,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAEtB,IAAI,QAAQ,IAAI,QAAQ,CAAC,KAAK;QAC1B,yBAAe,CAAC,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAE/C,OAAO,OAAO,CAAC,MAAM,EAAE,CAAC;AAC5B,CAAC;AAED,kBAAe;IACX,GAAG,KAAA;IACH,IAAI,MAAA;IACJ,WAAW,aAAA;CACd,CAAC"}
|
59
Birdmap/ClientApp/src/common/ServiceBase.ts
Normal file
59
Birdmap/ClientApp/src/common/ServiceBase.ts
Normal file
@ -0,0 +1,59 @@
|
||||
import ErrorDispatcher from './ErrorDispatcher';
|
||||
|
||||
function get(url) {
|
||||
let options = {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': sessionStorage.getItem('user')
|
||||
}
|
||||
};
|
||||
|
||||
return makeRequest(url, options);
|
||||
}
|
||||
|
||||
function post(url, request) {
|
||||
let options = {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': sessionStorage.getItem('user')
|
||||
},
|
||||
body: "",
|
||||
};
|
||||
|
||||
if (request)
|
||||
options.body = JSON.stringify(request);
|
||||
|
||||
return makeRequest(url, options);
|
||||
}
|
||||
|
||||
function makeRequest(url, options) {
|
||||
return fetch(url, options)
|
||||
.then(ensureResponseSuccess)
|
||||
.catch(errorHandler);
|
||||
}
|
||||
|
||||
function ensureResponseSuccess(response) {
|
||||
if (!response.ok)
|
||||
return response.json()
|
||||
.then(data => errorHandler(data));
|
||||
|
||||
return response.text()
|
||||
.then(text => text.length ? JSON.parse(text) : {});
|
||||
}
|
||||
|
||||
function errorHandler(response) {
|
||||
console.log(response);
|
||||
|
||||
if (response && response.Error)
|
||||
ErrorDispatcher.raiseError(response.Error);
|
||||
|
||||
return Promise.reject();
|
||||
}
|
||||
|
||||
export default {
|
||||
get,
|
||||
post,
|
||||
makeRequest
|
||||
};
|
@ -1 +1,119 @@
|
||||
|
||||
import React, { useState } from 'react';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { Box, Grid, TextField, Button, Typography, Paper } from '@material-ui/core';
|
||||
import { makeStyles, createStyles, Theme } from '@material-ui/core/styles';
|
||||
import AuthService from './AuthService';
|
||||
|
||||
export default function MenuItem(props: any) {
|
||||
const history = useHistory();
|
||||
const classes = useStyles();
|
||||
|
||||
const [username, setUsername] = useState(null);
|
||||
const [password, setPassword] = useState(null);
|
||||
|
||||
const [showError, setShowError] = useState(false);
|
||||
const [errorMessage, setErrorMessage] = useState('');
|
||||
|
||||
const onUsernameChanged = (event: any) => {
|
||||
setUsername(event.target.value);
|
||||
|
||||
setShowError(false);
|
||||
setErrorMessage('');
|
||||
};
|
||||
|
||||
const onPasswordChanged = (event: any) => {
|
||||
setPassword(event.target.value);
|
||||
|
||||
setShowError(false);
|
||||
setErrorMessage('');
|
||||
};
|
||||
|
||||
const onPasswordKeyPress = (event: any) => {
|
||||
if (event.key === 'Enter') {
|
||||
onLoginClicked();
|
||||
}
|
||||
};
|
||||
|
||||
const onLoginClicked = () => {
|
||||
if (!username) {
|
||||
setShowError(true);
|
||||
setErrorMessage('Username required');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!password) {
|
||||
setShowError(true);
|
||||
setErrorMessage('Password required');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
AuthService.login(username, password).then(() => {
|
||||
props.onAuthenticated();
|
||||
history.push('/');
|
||||
|
||||
}).catch(() => {
|
||||
setShowError(true);
|
||||
setErrorMessage('Invalid credentials');
|
||||
});
|
||||
};
|
||||
|
||||
const renderErrorLabel = () => {
|
||||
return showError
|
||||
? <Typography>{errorMessage}</Typography>
|
||||
: <React.Fragment />;
|
||||
};
|
||||
|
||||
return (
|
||||
<Box className={classes.root}>
|
||||
<Paper className={classes.paper}>
|
||||
<Grid container className={classes.container} spacing={2}>
|
||||
<Grid item>
|
||||
<Typography component="h1" variant="h5">
|
||||
Sign in
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={12} >
|
||||
<TextField label="Username" type="text" onChange={onUsernameChanged} />
|
||||
</Grid>
|
||||
<Grid item xs={12} >
|
||||
<TextField label="Password" type="password" onChange={onPasswordChanged} onKeyPress={onPasswordKeyPress} />
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.error}>
|
||||
{renderErrorLabel()}
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.button}>
|
||||
<Button className={classes.button} variant="contained" color="primary" onClick={onLoginClicked}>Login</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Paper>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) =>
|
||||
createStyles({
|
||||
root: {
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
minWidth: 400,
|
||||
minHeight: 600,
|
||||
},
|
||||
container: {
|
||||
padding: 40,
|
||||
flexDirection: "column",
|
||||
justifyContent: "space-around",
|
||||
alignItems: "center",
|
||||
},
|
||||
paper: {
|
||||
},
|
||||
button: {
|
||||
width: '100%',
|
||||
},
|
||||
error: {
|
||||
color: "red",
|
||||
}
|
||||
}),
|
||||
);
|
28
Birdmap/ClientApp/src/components/auth/AuthService.js
Normal file
28
Birdmap/ClientApp/src/components/auth/AuthService.js
Normal file
@ -0,0 +1,28 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var ServiceBase_1 = require("../../common/ServiceBase");
|
||||
var login_url = '/auth/authenticate';
|
||||
exports.default = {
|
||||
isAuthenticated: function () {
|
||||
return sessionStorage.getItem('user') !== null;
|
||||
},
|
||||
login: function (username, password) {
|
||||
var body = {
|
||||
username: username,
|
||||
password: password
|
||||
};
|
||||
var options = {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(body),
|
||||
};
|
||||
return ServiceBase_1.default.makeRequest(login_url, options)
|
||||
.then(function (response) {
|
||||
sessionStorage.setItem('user', response.token_type + " " + response.access_token);
|
||||
return Promise.resolve();
|
||||
});
|
||||
}
|
||||
};
|
||||
//# sourceMappingURL=AuthService.js.map
|
1
Birdmap/ClientApp/src/components/auth/AuthService.js.map
Normal file
1
Birdmap/ClientApp/src/components/auth/AuthService.js.map
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"AuthService.js","sourceRoot":"","sources":["AuthService.ts"],"names":[],"mappings":";;AAAA,wDAAmD;AAEnD,IAAM,SAAS,GAAG,oBAAoB,CAAC;AAEvC,kBAAe;IACX,eAAe;QACX,OAAO,cAAc,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC;IACnD,CAAC;IAED,KAAK,YAAC,QAAQ,EAAE,QAAQ;QACpB,IAAI,IAAI,GAAG;YACP,QAAQ,EAAE,QAAQ;YAClB,QAAQ,EAAE,QAAQ;SACrB,CAAC;QACF,IAAI,OAAO,GAAG;YACV,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACL,cAAc,EAAE,kBAAkB;aACrC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;SAC7B,CAAC;QAEF,OAAO,qBAAW,CAAC,WAAW,CAAC,SAAS,EAAE,OAAO,CAAC;aAC7C,IAAI,CAAC,UAAA,QAAQ;YACV,cAAc,CAAC,OAAO,CAAC,MAAM,EAAK,QAAQ,CAAC,UAAU,SAAI,QAAQ,CAAC,YAAc,CAAC,CAAC;YAClF,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;QAC7B,CAAC,CAAC,CAAC;IACX,CAAC;CACJ,CAAA"}
|
29
Birdmap/ClientApp/src/components/auth/AuthService.ts
Normal file
29
Birdmap/ClientApp/src/components/auth/AuthService.ts
Normal file
@ -0,0 +1,29 @@
|
||||
import ServiceBase from '../../common/ServiceBase';
|
||||
|
||||
const login_url = '/auth/authenticate';
|
||||
|
||||
export default {
|
||||
isAuthenticated() {
|
||||
return sessionStorage.getItem('user') !== null;
|
||||
},
|
||||
|
||||
login(username, password) {
|
||||
let body = {
|
||||
username: username,
|
||||
password: password
|
||||
};
|
||||
let options = {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(body),
|
||||
};
|
||||
|
||||
return ServiceBase.makeRequest(login_url, options)
|
||||
.then(response => {
|
||||
sessionStorage.setItem('user', `${response.token_type} ${response.access_token}`);
|
||||
return Promise.resolve();
|
||||
});
|
||||
}
|
||||
}
|
21
Birdmap/ClientApp/src/index.js
Normal file
21
Birdmap/ClientApp/src/index.js
Normal file
@ -0,0 +1,21 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
require("bootstrap/dist/css/bootstrap.css");
|
||||
var React = require("react");
|
||||
var ReactDOM = require("react-dom");
|
||||
var react_redux_1 = require("react-redux");
|
||||
var connected_react_router_1 = require("connected-react-router");
|
||||
var history_1 = require("history");
|
||||
var configureStore_1 = require("./store/configureStore");
|
||||
var App_1 = require("./App");
|
||||
var registerServiceWorker_1 = require("./registerServiceWorker");
|
||||
// Create browser history to use in the Redux store
|
||||
var baseUrl = document.getElementsByTagName('base')[0].getAttribute('href');
|
||||
var history = history_1.createBrowserHistory({ basename: baseUrl });
|
||||
// Get the application-wide store instance, prepopulating with state from the server where available.
|
||||
var store = configureStore_1.default(history);
|
||||
ReactDOM.render(React.createElement(react_redux_1.Provider, { store: store },
|
||||
React.createElement(connected_react_router_1.ConnectedRouter, { history: history },
|
||||
React.createElement(App_1.default, null))), document.getElementById('root'));
|
||||
registerServiceWorker_1.default();
|
||||
//# sourceMappingURL=index.js.map
|
1
Birdmap/ClientApp/src/index.js.map
Normal file
1
Birdmap/ClientApp/src/index.js.map
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.js","sourceRoot":"","sources":["index.tsx"],"names":[],"mappings":";;AAAA,4CAA0C;AAE1C,6BAA+B;AAC/B,oCAAsC;AACtC,2CAAuC;AACvC,iEAAyD;AACzD,mCAA+C;AAC/C,yDAAoD;AACpD,6BAAwB;AACxB,iEAA4D;AAE5D,mDAAmD;AACnD,IAAM,OAAO,GAAG,QAAQ,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,MAAM,CAAW,CAAC;AACxF,IAAM,OAAO,GAAG,8BAAoB,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;AAE5D,qGAAqG;AACrG,IAAM,KAAK,GAAG,wBAAc,CAAC,OAAO,CAAC,CAAC;AAEtC,QAAQ,CAAC,MAAM,CACX,oBAAC,sBAAQ,IAAC,KAAK,EAAE,KAAK;IAClB,oBAAC,wCAAe,IAAC,OAAO,EAAE,OAAO;QAC7B,oBAAC,aAAG,OAAG,CACO,CACX,EACX,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC;AAErC,+BAAqB,EAAE,CAAC"}
|
@ -33,7 +33,7 @@ namespace Birdmap.Controllers
|
||||
public async Task<IActionResult> AuthenticateAsync([FromBody] AuthenticateRequest model)
|
||||
{
|
||||
var user = await _service.AuthenticateUserAsync(model.Username, model.Password);
|
||||
var expires = DateTime.UtcNow.AddHours(2);
|
||||
var expiresInSeconds = TimeSpan.FromHours(2).TotalSeconds;
|
||||
var tokenHandler = new JwtSecurityTokenHandler();
|
||||
var key = Encoding.ASCII.GetBytes(_configuration["BasicAuth:Secret"]);
|
||||
var tokenDescriptor = new SecurityTokenDescriptor
|
||||
@ -42,7 +42,7 @@ namespace Birdmap.Controllers
|
||||
{
|
||||
new Claim(ClaimTypes.Name, user.Name)
|
||||
}),
|
||||
Expires = expires,
|
||||
Expires = DateTime.UtcNow.AddHours(expiresInSeconds),
|
||||
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
|
||||
};
|
||||
var token = tokenHandler.CreateToken(tokenDescriptor);
|
||||
@ -51,9 +51,10 @@ namespace Birdmap.Controllers
|
||||
return Ok(
|
||||
new
|
||||
{
|
||||
Name = user.Name,
|
||||
Token = tokenString,
|
||||
Expires = expires,
|
||||
user_name = user.Name,
|
||||
access_token = tokenString,
|
||||
token_type = "Bearer",
|
||||
expires_in = expiresInSeconds,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user