diff --git a/frontend/scenes/Settings/Settings.js b/frontend/scenes/Settings/Settings.js index dda64d68e..8b75a4c9c 100644 --- a/frontend/scenes/Settings/Settings.js +++ b/frontend/scenes/Settings/Settings.js @@ -6,6 +6,7 @@ import { Input, ButtonOutline, InlineForm } from 'rebass'; import Layout, { Title } from 'components/Layout'; import CenteredContent from 'components/CenteredContent'; import SlackAuthLink from 'components/SlackAuthLink'; +import ApiKeyRow from './components/ApiKeyRow'; import styles from './Settings.scss'; @@ -65,13 +66,12 @@ class Settings extends React.Component { { this.store.apiKeys && ( { this.store.apiKeys.map(key => ( - - - - {/* */} - + )) }
{ key.name }{ key.secret } - Delete -
) } diff --git a/frontend/scenes/Settings/Settings.scss b/frontend/scenes/Settings/Settings.scss index 64f268ed4..20a48ff8a 100644 --- a/frontend/scenes/Settings/Settings.scss +++ b/frontend/scenes/Settings/Settings.scss @@ -17,9 +17,3 @@ color: #969696; } } - -.deleteAction { - font-size: 14px; - cursor: pointer; - color: $textColor; -} diff --git a/frontend/scenes/Settings/SettingsStore.js b/frontend/scenes/Settings/SettingsStore.js index 67b9940c3..4f96050be 100644 --- a/frontend/scenes/Settings/SettingsStore.js +++ b/frontend/scenes/Settings/SettingsStore.js @@ -40,6 +40,22 @@ class SearchStore { 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) => { this.keyName = value.target.value; } diff --git a/frontend/scenes/Settings/components/ApiKeyRow/ApiKeyRow.js b/frontend/scenes/Settings/components/ApiKeyRow/ApiKeyRow.js new file mode 100644 index 000000000..7d21ab8df --- /dev/null +++ b/frontend/scenes/Settings/components/ApiKeyRow/ApiKeyRow.js @@ -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 ( + + { name } + { secret } + + Delete + + + ); + } +} + +export default ApiKeyRow; diff --git a/frontend/scenes/Settings/components/ApiKeyRow/ApiKeyRow.scss b/frontend/scenes/Settings/components/ApiKeyRow/ApiKeyRow.scss new file mode 100644 index 000000000..18496088d --- /dev/null +++ b/frontend/scenes/Settings/components/ApiKeyRow/ApiKeyRow.scss @@ -0,0 +1,10 @@ +@import '~styles/constants.scss'; + +.deleteAction { + font-size: 14px; + color: $textColor; +} + +.disabled { + opacity: 0.5; +} diff --git a/frontend/scenes/Settings/components/ApiKeyRow/index.js b/frontend/scenes/Settings/components/ApiKeyRow/index.js new file mode 100644 index 000000000..5a4a1f59a --- /dev/null +++ b/frontend/scenes/Settings/components/ApiKeyRow/index.js @@ -0,0 +1,2 @@ +import ApiKeyRow from './ApiKeyRow'; +export default ApiKeyRow; diff --git a/frontend/styles/base.scss b/frontend/styles/base.scss index 50ab3a658..9221a07cc 100644 --- a/frontend/styles/base.scss +++ b/frontend/styles/base.scss @@ -93,6 +93,9 @@ hr { border-bottom-style: solid; border-bottom-color: #ccc; } +*[role=button] { + cursor: pointer; +} :global { .hljs { diff --git a/server/api/apiKeys.js b/server/api/apiKeys.js index efafe6164..1dda17fc2 100644 --- a/server/api/apiKeys.js +++ b/server/api/apiKeys.js @@ -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; diff --git a/server/api/documents.js b/server/api/documents.js index f528bfe0e..5b4e15fb7 100644 --- a/server/api/documents.js +++ b/server/api/documents.js @@ -232,7 +232,7 @@ router.post('documents.delete', auth(), async (ctx) => { } ctx.body = { - ok: true, + success: true, }; });