From 732c9b62a2bdcbe26b374b12f69aa0707d5428ed Mon Sep 17 00:00:00 2001 From: Stas Vilchik Date: Fri, 15 Jan 2016 11:05:03 +0100 Subject: [PATCH] SONAR-7184 Add the token management to the 'My Profile' page --- .../sonar-web/src/main/js/apps/account/app.js | 11 ++ .../apps/account/templates/account-tokens.hbs | 75 +++++++++++++ .../src/main/js/apps/account/tokens-view.js | 105 ++++++++++++++++++ .../WEB-INF/app/views/account/index.html.erb | 2 + 4 files changed, 193 insertions(+) create mode 100644 server/sonar-web/src/main/js/apps/account/templates/account-tokens.hbs create mode 100644 server/sonar-web/src/main/js/apps/account/tokens-view.js diff --git a/server/sonar-web/src/main/js/apps/account/app.js b/server/sonar-web/src/main/js/apps/account/app.js index ace384412e0..f2f87052d5e 100644 --- a/server/sonar-web/src/main/js/apps/account/app.js +++ b/server/sonar-web/src/main/js/apps/account/app.js @@ -18,7 +18,9 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import $ from 'jquery'; +import Backbone from 'backbone'; import ChangePasswordView from './change-password-view'; +import TokensView from './tokens-view'; import avatarHelper from '../../helpers/handlebars/avatarHelper'; var shouldShowAvatars = window.SS && window.SS.lf && window.SS.lf.enableGravatar; @@ -47,6 +49,15 @@ class App { e.preventDefault(); new ChangePasswordView().render(); }); + + const account = new Backbone.Model({ + id: window.SS.user + }); + + new TokensView({ + el: '#account-tokens', + model: account + }).render(); } } diff --git a/server/sonar-web/src/main/js/apps/account/templates/account-tokens.hbs b/server/sonar-web/src/main/js/apps/account/templates/account-tokens.hbs new file mode 100644 index 00000000000..3b0d29d938b --- /dev/null +++ b/server/sonar-web/src/main/js/apps/account/templates/account-tokens.hbs @@ -0,0 +1,75 @@ +

Tokens

+ +{{#notNull tokens}} +
+ + + + + + + + + + {{#each tokens}} + + + + + + {{else}} + + + + {{/each}} + +
NameCreated 
+ {{name}} + + {{d createdAt}} + +
+
+ {{#if deleting}} + + {{else}} + + {{/if}} +
+
+
+ No tokens +
+
+{{/notNull}} + +

Generate Tokens

+ +{{#each errors}} +
{{msg}}
+{{/each}} + +
+ + +
+ +{{#if newToken}} +
+
+ Make sure you copy the token now. You won’t be able to see it again! +
+ + + + + + + +
+ + + {{newToken}} +
+
+{{/if}} diff --git a/server/sonar-web/src/main/js/apps/account/tokens-view.js b/server/sonar-web/src/main/js/apps/account/tokens-view.js new file mode 100644 index 00000000000..55beb5689bd --- /dev/null +++ b/server/sonar-web/src/main/js/apps/account/tokens-view.js @@ -0,0 +1,105 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import $ from 'jquery'; +import _ from 'underscore'; +import Marionette from 'backbone.marionette'; +import Clipboard from 'clipboard'; + +import Template from './templates/account-tokens.hbs'; +import { getTokens, generateToken, revokeToken } from '../../api/user-tokens'; + + +export default Marionette.ItemView.extend({ + template: Template, + + events () { + return { + 'submit .js-generate-token-form': 'onGenerateTokenFormSubmit', + 'submit .js-revoke-token-form': 'onRevokeTokenFormSubmit' + }; + }, + + initialize () { + this.tokens = null; + this.newToken = null; + this.errors = []; + this.requestTokens(); + }, + + requestTokens () { + return getTokens(this.model.id).then(tokens => { + this.tokens = tokens; + this.render(); + }); + }, + + onGenerateTokenFormSubmit (e) { + e.preventDefault(); + this.errors = []; + this.newToken = null; + let tokenName = this.$('.js-generate-token-form input').val(); + generateToken(this.model.id, tokenName) + .then(response => { + this.newToken = response.token; + this.requestTokens(); + }) + .catch(error => { + error.response.json().then(response => { + this.errors = response.errors; + this.render(); + }); + }); + }, + + onRevokeTokenFormSubmit(e) { + e.preventDefault(); + let tokenName = $(e.currentTarget).data('token'); + let token = _.findWhere(this.tokens, { name: `${tokenName}` }); + if (token) { + if (token.deleting) { + revokeToken(this.model.id, tokenName).then(this.requestTokens.bind(this)); + } else { + token.deleting = true; + this.render(); + } + } + }, + + onRender () { + let copyButton = this.$('.js-copy-to-clipboard'); + if (copyButton.length) { + let clipboard = new Clipboard(copyButton.get(0)); + clipboard.on('success', () => { + copyButton.tooltip({ title: 'Copied!', placement: 'bottom', trigger: 'manual' }).tooltip('show'); + setTimeout(() => copyButton.tooltip('hide'), 1000); + }); + } + this.newToken = null; + }, + + serializeData() { + return _.extend(Marionette.ItemView.prototype.serializeData.apply(this, arguments), { + tokens: this.tokens, + newToken: this.newToken, + errors: this.errors + }); + } + +}); diff --git a/server/sonar-web/src/main/webapp/WEB-INF/app/views/account/index.html.erb b/server/sonar-web/src/main/webapp/WEB-INF/app/views/account/index.html.erb index bbc906a0f3d..0c38691c0bf 100644 --- a/server/sonar-web/src/main/webapp/WEB-INF/app/views/account/index.html.erb +++ b/server/sonar-web/src/main/webapp/WEB-INF/app/views/account/index.html.erb @@ -65,6 +65,8 @@ + +
-- 2.39.5