Added login page
This commit is contained in:
parent
472f43a950
commit
0f0e5d9d1c
@ -26,7 +26,10 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<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\Auth.tsx" />
|
||||||
|
<None Remove="ClientApp\src\components\auth\AuthService.ts" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<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 { Box, Container } from '@material-ui/core';
|
||||||
import { Route } from 'react-router';
|
import AppBar from '@material-ui/core/AppBar';
|
||||||
import Layout from './components/Layout';
|
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 Home from './components/Home';
|
||||||
import Counter from './components/Counter';
|
import './custom.css';
|
||||||
import FetchData from './components/FetchData';
|
|
||||||
|
|
||||||
import './custom.css'
|
|
||||||
|
|
||||||
export default () => (
|
const theme = createMuiTheme({
|
||||||
<Layout>
|
palette: {
|
||||||
<Route exact path='/' component={Home} />
|
primary: {
|
||||||
<Route path='/counter' component={Counter} />
|
main: blue[800]
|
||||||
<Route path='/fetch-data/:startDateIndex?' component={FetchData} />
|
},
|
||||||
</Layout>
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
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)
|
public async Task<IActionResult> AuthenticateAsync([FromBody] AuthenticateRequest model)
|
||||||
{
|
{
|
||||||
var user = await _service.AuthenticateUserAsync(model.Username, model.Password);
|
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 tokenHandler = new JwtSecurityTokenHandler();
|
||||||
var key = Encoding.ASCII.GetBytes(_configuration["BasicAuth:Secret"]);
|
var key = Encoding.ASCII.GetBytes(_configuration["BasicAuth:Secret"]);
|
||||||
var tokenDescriptor = new SecurityTokenDescriptor
|
var tokenDescriptor = new SecurityTokenDescriptor
|
||||||
@ -42,7 +42,7 @@ namespace Birdmap.Controllers
|
|||||||
{
|
{
|
||||||
new Claim(ClaimTypes.Name, user.Name)
|
new Claim(ClaimTypes.Name, user.Name)
|
||||||
}),
|
}),
|
||||||
Expires = expires,
|
Expires = DateTime.UtcNow.AddHours(expiresInSeconds),
|
||||||
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
|
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
|
||||||
};
|
};
|
||||||
var token = tokenHandler.CreateToken(tokenDescriptor);
|
var token = tokenHandler.CreateToken(tokenDescriptor);
|
||||||
@ -51,9 +51,10 @@ namespace Birdmap.Controllers
|
|||||||
return Ok(
|
return Ok(
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
Name = user.Name,
|
user_name = user.Name,
|
||||||
Token = tokenString,
|
access_token = tokenString,
|
||||||
Expires = expires,
|
token_type = "Bearer",
|
||||||
|
expires_in = expiresInSeconds,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user