Allow requesting user API key
This commit is contained in:
parent
daca8e46ee
commit
ab2db30bc4
@ -27,6 +27,7 @@ class App extends React.Component {
|
|||||||
building: props.building,
|
building: props.building,
|
||||||
};
|
};
|
||||||
this.login = this.login.bind(this);
|
this.login = this.login.bind(this);
|
||||||
|
this.updateUser = this.updateUser.bind(this);
|
||||||
this.logout = this.logout.bind(this);
|
this.logout = this.logout.bind(this);
|
||||||
this.selectBuilding = this.selectBuilding.bind(this);
|
this.selectBuilding = this.selectBuilding.bind(this);
|
||||||
}
|
}
|
||||||
@ -39,6 +40,11 @@ class App extends React.Component {
|
|||||||
this.setState({user: user});
|
this.setState({user: user});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateUser(user){
|
||||||
|
console.log(user);
|
||||||
|
this.setState({user: { ...this.state.user, ...user }});
|
||||||
|
}
|
||||||
|
|
||||||
logout() {
|
logout() {
|
||||||
this.setState({user: undefined});
|
this.setState({user: undefined});
|
||||||
}
|
}
|
||||||
@ -94,7 +100,11 @@ class App extends React.Component {
|
|||||||
<SignUp user={this.state.user} login={this.login} />
|
<SignUp user={this.state.user} login={this.login} />
|
||||||
</Route>
|
</Route>
|
||||||
<Route exact path="/my-account.html">
|
<Route exact path="/my-account.html">
|
||||||
<MyAccountPage user={this.state.user} logout={this.logout} />
|
<MyAccountPage
|
||||||
|
user={this.state.user}
|
||||||
|
updateUser={this.updateUser}
|
||||||
|
logout={this.logout}
|
||||||
|
/>
|
||||||
</Route>
|
</Route>
|
||||||
<Route component={NotFound} />
|
<Route component={NotFound} />
|
||||||
</Switch>
|
</Switch>
|
||||||
|
@ -9,10 +9,11 @@ class MyAccountPage extends Component {
|
|||||||
this.state = {
|
this.state = {
|
||||||
error: undefined
|
error: undefined
|
||||||
};
|
};
|
||||||
this.handleSubmit = this.handleSubmit.bind(this);
|
this.handleLogout = this.handleLogout.bind(this);
|
||||||
|
this.handleGenerateKey = this.handleGenerateKey.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleSubmit(event) {
|
handleLogout(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
this.setState({error: undefined});
|
this.setState({error: undefined});
|
||||||
|
|
||||||
@ -32,24 +33,66 @@ class MyAccountPage extends Component {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleGenerateKey(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
this.setState({error: undefined});
|
||||||
|
|
||||||
|
fetch('/api/key', {
|
||||||
|
method: 'POST',
|
||||||
|
credentials: 'same-origin'
|
||||||
|
}).then(
|
||||||
|
res => res.json()
|
||||||
|
).then(function(res){
|
||||||
|
if (res.error) {
|
||||||
|
this.setState({error: res.error})
|
||||||
|
} else {
|
||||||
|
this.props.updateUser(res);
|
||||||
|
}
|
||||||
|
}.bind(this)).catch(
|
||||||
|
(err) => this.setState({error: err})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
if (this.props.user && !this.props.user.error) {
|
if (this.props.user && !this.props.user.error) {
|
||||||
return (
|
return (
|
||||||
<article>
|
<article>
|
||||||
<section className="main-col">
|
<section className="main-col">
|
||||||
<h1 className="h1">Welcome, {this.props.user.username}!</h1>
|
<h1 className="h1">Welcome, {this.props.user.username}!</h1>
|
||||||
<p className="lead">
|
<p>
|
||||||
|
|
||||||
Colouring London is under active development, please report any
|
Colouring London is under active development, please report any
|
||||||
bugs on <a href="http://github.com/tomalrussell/colouring-london/issues">
|
bugs on <a href="http://github.com/tomalrussell/colouring-london/issues">
|
||||||
GitHub</a>.
|
GitHub</a>.
|
||||||
|
|
||||||
</p>
|
</p>
|
||||||
<Link to="/map/age.html" className="btn btn-primary">Start colouring</Link>
|
|
||||||
<ErrorBox msg={this.state.error} />
|
<ErrorBox msg={this.state.error} />
|
||||||
<form method="POST" action="/logout" onSubmit={this.handleSubmit}>
|
<form method="POST" action="/logout" onSubmit={this.handleLogout}>
|
||||||
|
<div className="buttons-container">
|
||||||
|
<Link to="/map/age.html" className="btn btn-primary">Start colouring</Link>
|
||||||
<input className="btn btn-secondary" type="submit" value="Log out"/>
|
<input className="btn btn-secondary" type="submit" value="Log out"/>
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
<hr/>
|
||||||
|
|
||||||
|
<h2 className="h2">My Details</h2>
|
||||||
|
<h3 className="h3">Username</h3>
|
||||||
|
<p>{this.props.user.username}</p>
|
||||||
|
<h3 className="h3">Email Address</h3>
|
||||||
|
<p>{this.props.user.email? this.props.user.email : '-'}</p>
|
||||||
|
<h3 className="h3">Registered</h3>
|
||||||
|
<p>{this.props.user.registered.toString()}</p>
|
||||||
|
|
||||||
|
<hr/>
|
||||||
|
|
||||||
|
<h2 className="h2">Experimental features</h2>
|
||||||
|
<h3 className="h3">API key</h3>
|
||||||
|
<p>{this.props.user.api_key? this.props.user.api_key : '-'}</p>
|
||||||
|
<form method="POST" action="/api/key" onSubmit={this.handleGenerateKey}>
|
||||||
|
<input className="btn btn-primary" type="submit" value="Generate API key"/>
|
||||||
|
</form>
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
</article>
|
</article>
|
||||||
);
|
);
|
||||||
|
@ -16,7 +16,7 @@ import pgConnect from 'connect-pg-simple';
|
|||||||
|
|
||||||
import App from './frontend/app';
|
import App from './frontend/app';
|
||||||
import db from './db';
|
import db from './db';
|
||||||
import { authUser, createUser, getUserById } from './user';
|
import { authUser, createUser, getUserById, getNewUserAPIKey } from './user';
|
||||||
import { queryBuildingsAtPoint, queryBuildingsByReference, getBuildingById,
|
import { queryBuildingsAtPoint, queryBuildingsByReference, getBuildingById,
|
||||||
saveBuilding } from './building';
|
saveBuilding } from './building';
|
||||||
import tileserver from './tileserver';
|
import tileserver from './tileserver';
|
||||||
@ -281,4 +281,18 @@ server.get('/users/me', function(req, res){
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// POST generate API key
|
||||||
|
server.post('/api/key', function(req, res){
|
||||||
|
if (!req.session.user_id) {
|
||||||
|
res.send({error: 'Must be logged in'});
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
getNewUserAPIKey(req.session.user_id).then(function(api_key){
|
||||||
|
res.send(api_key);
|
||||||
|
}).catch(function(error){
|
||||||
|
res.send(error);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
export default server;
|
export default server;
|
||||||
|
@ -73,7 +73,7 @@ function authUser(username, password) {
|
|||||||
function getUserById(user_id) {
|
function getUserById(user_id) {
|
||||||
return db.one(
|
return db.one(
|
||||||
`SELECT
|
`SELECT
|
||||||
username, email, registered
|
username, email, registered, api_key
|
||||||
FROM users
|
FROM users
|
||||||
WHERE
|
WHERE
|
||||||
user_id = $1
|
user_id = $1
|
||||||
@ -86,4 +86,23 @@ function getUserById(user_id) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export { getUserById, createUser, authUser }
|
function getNewUserAPIKey(user_id) {
|
||||||
|
return db.one(
|
||||||
|
`UPDATE
|
||||||
|
users
|
||||||
|
SET
|
||||||
|
api_key = gen_random_uuid()
|
||||||
|
WHERE
|
||||||
|
user_id = $1
|
||||||
|
RETURNING
|
||||||
|
api_key
|
||||||
|
`, [
|
||||||
|
user_id
|
||||||
|
]
|
||||||
|
).catch(function(error){
|
||||||
|
console.error('Error:', error)
|
||||||
|
return {error: 'Failed to generate new API key.'};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export { getUserById, createUser, authUser, getNewUserAPIKey }
|
||||||
|
@ -89,7 +89,9 @@ CREATE TABLE IF NOT EXISTS users (
|
|||||||
-- user category (optional, self-selected)
|
-- user category (optional, self-selected)
|
||||||
category integer REFERENCES user_categories NOT NULL DEFAULT 1,
|
category integer REFERENCES user_categories NOT NULL DEFAULT 1,
|
||||||
-- user access level (essential, default untrusted)
|
-- user access level (essential, default untrusted)
|
||||||
access_level integer REFERENCES user_access_levels NOT NULL DEFAULT 1
|
access_level integer REFERENCES user_access_levels NOT NULL DEFAULT 1,
|
||||||
|
-- user API key - to give limited query/edit access
|
||||||
|
api_key uuid UNIQUE default NULL
|
||||||
);
|
);
|
||||||
ALTER TABLE users ADD CONSTRAINT users_username_len CHECK (length(username) < 30);
|
ALTER TABLE users ADD CONSTRAINT users_username_len CHECK (length(username) < 30);
|
||||||
ALTER TABLE users ADD CONSTRAINT users_email_len CHECK (length(email) < 50);
|
ALTER TABLE users ADD CONSTRAINT users_email_len CHECK (length(email) < 50);
|
||||||
|
Loading…
Reference in New Issue
Block a user