Implemented api key deletion
This commit is contained in:
@ -6,6 +6,7 @@ import { Input, ButtonOutline, InlineForm } from 'rebass';
|
|||||||
import Layout, { Title } from 'components/Layout';
|
import Layout, { Title } from 'components/Layout';
|
||||||
import CenteredContent from 'components/CenteredContent';
|
import CenteredContent from 'components/CenteredContent';
|
||||||
import SlackAuthLink from 'components/SlackAuthLink';
|
import SlackAuthLink from 'components/SlackAuthLink';
|
||||||
|
import ApiKeyRow from './components/ApiKeyRow';
|
||||||
|
|
||||||
import styles from './Settings.scss';
|
import styles from './Settings.scss';
|
||||||
|
|
||||||
@ -65,13 +66,12 @@ class Settings extends React.Component {
|
|||||||
{ this.store.apiKeys && (
|
{ this.store.apiKeys && (
|
||||||
<table className={ styles.apiKeyTable }>
|
<table className={ styles.apiKeyTable }>
|
||||||
{ this.store.apiKeys.map(key => (
|
{ this.store.apiKeys.map(key => (
|
||||||
<tr>
|
<ApiKeyRow
|
||||||
<td>{ key.name }</td>
|
id={ key.id }
|
||||||
<td><code>{ key.secret }</code></td>
|
name={ key.name }
|
||||||
{/* <td>
|
secret={ key.secret }
|
||||||
<span className={ styles.deleteAction }>Delete</span>
|
onDelete={ this.store.deleteApiKey }
|
||||||
</td> */}
|
/>
|
||||||
</tr>
|
|
||||||
)) }
|
)) }
|
||||||
</table>
|
</table>
|
||||||
) }
|
) }
|
||||||
|
@ -17,9 +17,3 @@
|
|||||||
color: #969696;
|
color: #969696;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.deleteAction {
|
|
||||||
font-size: 14px;
|
|
||||||
cursor: pointer;
|
|
||||||
color: $textColor;
|
|
||||||
}
|
|
||||||
|
@ -40,6 +40,22 @@ class SearchStore {
|
|||||||
this.isFetching = false;
|
this.isFetching = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@action deleteApiKey = async (id) => {
|
||||||
|
this.isFetching = true;
|
||||||
|
|
||||||
|
try {
|
||||||
|
await client.post('/apiKeys.delete', {
|
||||||
|
id,
|
||||||
|
});
|
||||||
|
runInAction('deleteApiKey', () => {
|
||||||
|
this.fetchApiKeys();
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Something went wrong");
|
||||||
|
}
|
||||||
|
this.isFetching = false;
|
||||||
|
}
|
||||||
|
|
||||||
@action setKeyName = (value) => {
|
@action setKeyName = (value) => {
|
||||||
this.keyName = value.target.value;
|
this.keyName = value.target.value;
|
||||||
}
|
}
|
||||||
|
50
frontend/scenes/Settings/components/ApiKeyRow/ApiKeyRow.js
Normal file
50
frontend/scenes/Settings/components/ApiKeyRow/ApiKeyRow.js
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
import React, { PropTypes } from 'react';
|
||||||
|
|
||||||
|
import styles from './ApiKeyRow.scss';
|
||||||
|
import classNames from 'classnames/bind';
|
||||||
|
const cx = classNames.bind(styles);
|
||||||
|
|
||||||
|
class ApiKeyRow extends React.Component {
|
||||||
|
static propTypes = {
|
||||||
|
id: PropTypes.string.isRequired,
|
||||||
|
name: PropTypes.string.isRequired,
|
||||||
|
secret: PropTypes.string.isRequired,
|
||||||
|
onDelete: PropTypes.func.isRequired,
|
||||||
|
}
|
||||||
|
|
||||||
|
state = {
|
||||||
|
disabled: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
onClick = () => {
|
||||||
|
this.props.onDelete(this.props.id);
|
||||||
|
this.setState({ disabled: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const {
|
||||||
|
name,
|
||||||
|
secret,
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
|
const {
|
||||||
|
disabled,
|
||||||
|
} = this.state;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<tr>
|
||||||
|
<td>{ name }</td>
|
||||||
|
<td><code>{ secret }</code></td>
|
||||||
|
<td>
|
||||||
|
<span
|
||||||
|
role="button"
|
||||||
|
onClick={ this.onClick }
|
||||||
|
className={ cx(styles.deleteAction, { disabled }) }
|
||||||
|
>Delete</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ApiKeyRow;
|
10
frontend/scenes/Settings/components/ApiKeyRow/ApiKeyRow.scss
Normal file
10
frontend/scenes/Settings/components/ApiKeyRow/ApiKeyRow.scss
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
@import '~styles/constants.scss';
|
||||||
|
|
||||||
|
.deleteAction {
|
||||||
|
font-size: 14px;
|
||||||
|
color: $textColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
.disabled {
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
2
frontend/scenes/Settings/components/ApiKeyRow/index.js
Normal file
2
frontend/scenes/Settings/components/ApiKeyRow/index.js
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
import ApiKeyRow from './ApiKeyRow';
|
||||||
|
export default ApiKeyRow;
|
@ -93,6 +93,9 @@ hr {
|
|||||||
border-bottom-style: solid;
|
border-bottom-style: solid;
|
||||||
border-bottom-color: #ccc;
|
border-bottom-color: #ccc;
|
||||||
}
|
}
|
||||||
|
*[role=button] {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
:global {
|
:global {
|
||||||
.hljs {
|
.hljs {
|
||||||
|
@ -50,4 +50,27 @@ router.post('apiKeys.list', auth(), pagination(), async (ctx) => {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
router.post('apiKeys.delete', auth(), async (ctx) => {
|
||||||
|
const {
|
||||||
|
id,
|
||||||
|
} = ctx.body;
|
||||||
|
ctx.assertPresent(id, 'id is required');
|
||||||
|
|
||||||
|
const user = ctx.state.user;
|
||||||
|
const key = await ApiKey.findById(id);
|
||||||
|
|
||||||
|
if (!key || key.userId !== user.id) throw httpErrors.BadRequest();
|
||||||
|
|
||||||
|
// Delete the actual document
|
||||||
|
try {
|
||||||
|
await key.destroy();
|
||||||
|
} catch (e) {
|
||||||
|
throw httpErrors.BadRequest('Error while deleting key');
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.body = {
|
||||||
|
success: true,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
export default router;
|
export default router;
|
||||||
|
@ -232,7 +232,7 @@ router.post('documents.delete', auth(), async (ctx) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ctx.body = {
|
ctx.body = {
|
||||||
ok: true,
|
success: true,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user