diff --git a/app/assets/javascripts/admin/controllers/admin-user-index.js.es6 b/app/assets/javascripts/admin/controllers/admin-user-index.js.es6 index b232d5bc288..770d5588b06 100644 --- a/app/assets/javascripts/admin/controllers/admin-user-index.js.es6 +++ b/app/assets/javascripts/admin/controllers/admin-user-index.js.es6 @@ -19,6 +19,11 @@ export default Ember.Controller.extend(CanCheckEmails, { primaryGroupDirty: propertyNotEqual('originalPrimaryGroupId', 'model.primary_group_id'), + canDisableSecondFactor: Ember.computed.and( + 'model.second_factor_enabled', + 'model.can_disable_second_factor' + ), + automaticGroups: function() { return this.get("model.automaticGroups").map((g) => g.name).join(", "); }.property("model.automaticGroups"), @@ -41,11 +46,6 @@ export default Ember.Controller.extend(CanCheckEmails, { return userPath(`${username}/preferences`); }, - @computed('model.second_factor_enabled','model.can_disable_second_factor') - canDisableSecondFactor(secondFactorEnabled, canDisableSecondFactor) { - return secondFactorEnabled && canDisableSecondFactor; - }, - actions: { impersonate() { return this.get("model").impersonate(); }, diff --git a/app/assets/javascripts/admin/models/admin-user.js.es6 b/app/assets/javascripts/admin/models/admin-user.js.es6 index 52348e4019e..99aec6aaf71 100644 --- a/app/assets/javascripts/admin/models/admin-user.js.es6 +++ b/app/assets/javascripts/admin/models/admin-user.js.es6 @@ -169,7 +169,7 @@ const AdminUser = Discourse.User.extend({ }, disableSecondFactor() { - return ajax("/admin/users/" + this.get('id') + "/disable_second_factor", { + return ajax(`/admin/users/${this.get('id')}/disable_second_factor`, { type: 'PUT' }).then(() => { this.set('second_factor_enabled', false); diff --git a/app/assets/javascripts/discourse/controllers/login.js.es6 b/app/assets/javascripts/discourse/controllers/login.js.es6 index 51033172214..31d339b7c05 100644 --- a/app/assets/javascripts/discourse/controllers/login.js.es6 +++ b/app/assets/javascripts/discourse/controllers/login.js.es6 @@ -4,6 +4,7 @@ import showModal from 'discourse/lib/show-modal'; import { setting } from 'discourse/lib/computed'; import { findAll } from 'discourse/models/login-method'; import { escape } from 'pretty-text/sanitizer'; +import computed from 'ember-addons/ember-computed-decorators'; // This is happening outside of the app via popup const AuthErrors = [ @@ -41,9 +42,10 @@ export default Ember.Controller.extend(ModalFunctionality, { return findAll(this.siteSettings).length > 0; }.property(), - loginButtonText: function() { - return this.get('loggingIn') ? I18n.t('login.logging_in') : I18n.t('login.title'); - }.property('loggingIn'), + @computed('loggingIn') + loginButtonLabel(loggingIn) { + return loggingIn ? 'login.logging_in' : 'login.title'; + }, loginDisabled: Em.computed.or('loggingIn', 'loggedIn'), @@ -70,20 +72,24 @@ export default Ember.Controller.extend(ModalFunctionality, { this.set('loggingIn', true); ajax("/session", { - data: { login: this.get('loginName'), password: this.get('loginPassword'), second_factor_token: this.get('loginSecondFactor') }, - type: 'POST' + type: 'POST', + data: { + login: this.get('loginName'), + password: this.get('loginPassword'), + second_factor_token: this.get('loginSecondFactor') + }, }).then(function (result) { // Successful login if (result && result.error) { self.set('loggingIn', false); - if(result.reason === 'invalid_second_factor' && !self.get('secondFactorRequired')) { + + if (result.reason === 'invalid_second_factor' && !self.get('secondFactorRequired')) { $('#modal-alert').hide(); self.set('secondFactorRequired', true); $("#credentials").hide(); $("#second-factor").show(); return; - } - if (result.reason === 'not_activated') { + } else if (result.reason === 'not_activated') { self.send('showNotActivated', { username: self.get('loginName'), sentTo: escape(result.sent_to_email), diff --git a/app/assets/javascripts/discourse/controllers/password-reset.js.es6 b/app/assets/javascripts/discourse/controllers/password-reset.js.es6 index 0c1a9e0faf5..bcf40ca88cf 100644 --- a/app/assets/javascripts/discourse/controllers/password-reset.js.es6 +++ b/app/assets/javascripts/discourse/controllers/password-reset.js.es6 @@ -47,22 +47,22 @@ export default Ember.Controller.extend(PasswordValidation, { DiscourseURL.redirectTo(result.redirect_to || '/'); } } else { - if (result.errors && result.errors.second_factor) { + if (result.errors && result.errors.user_second_factor) { this.setProperties({ secondFactorRequired: true, password: null, errorMessage: result.message }); - } - else if (this.get('secondFactorRequired')) { - //ok 2factor - this.set('secondFactorRequired',false); - this.set('errorMessage', null); - } - else if (result.errors && result.errors.password && result.errors.password.length > 0) { + } else if (this.get('secondFactorRequired')) { + this.setProperties({ + secondFactorRequired: false, + errorMessage: null + }); + } else if (result.errors && result.errors.password && result.errors.password.length > 0) { this.get('rejectedPasswords').pushObject(this.get('accountPassword')); this.get('rejectedPasswordsMessages').set(this.get('accountPassword'), result.errors.password[0]); } + if (result.message) { this.set('errorMessage', result.message); } diff --git a/app/assets/javascripts/discourse/controllers/preferences/second-factor.js.es6 b/app/assets/javascripts/discourse/controllers/preferences/second-factor.js.es6 index 4365bdd1688..990d2eb6f9b 100644 --- a/app/assets/javascripts/discourse/controllers/preferences/second-factor.js.es6 +++ b/app/assets/javascripts/discourse/controllers/preferences/second-factor.js.es6 @@ -1,70 +1,71 @@ import { default as computed } from 'ember-addons/ember-computed-decorators'; -import DiscourseURL from 'discourse/lib/url'; -import { userPath } from 'discourse/lib/url'; +import { default as DiscourseURL, userPath } from 'discourse/lib/url'; import { popupAjaxError } from 'discourse/lib/ajax-error'; export default Ember.Controller.extend({ - loading: false, password: null, secondFactorImage: null, secondFactorKey: null, showSecondFactorKey: false, - errorMessage: null, newUsername: null, - @computed('secondFactorImage','secondFactorKey') - loaded(secondFactorImage, secondFactorKey) { - return secondFactorImage && secondFactorKey; - }, + loaded: Ember.computed.and('secondFactorImage', 'secondFactorKey'), @computed('loading') submitButtonText(loading) { - if (loading) return I18n.t('loading'); - return I18n.t('submit'); + return loading ? 'loading' : 'submit'; }, toggleSecondFactor(enable) { - if(!this.get('second_factor_token')) { - return; - } + if (!this.get('second_factor_token')) return; this.set('loading', true); - this.get('content').toggleSecondFactor(this.get('second_factor_token'), enable).then((resp) => { - if(resp.error) { - this.set('errorMessage',resp.error); - return; - } - this.set('errorMessage',null); - DiscourseURL.redirectTo(userPath(this.get('content').username.toLowerCase() + "/preferences")); - }) + + this.get('content').toggleSecondFactor(this.get('second_factor_token'), enable) + .then(response => { + if (response.error) { + this.set('errorMessage', response.error); + return; + } + + this.set('errorMessage',null); + DiscourseURL.redirectTo(userPath(`${this.get('content').username.toLowerCase()}/preferences`)); + }) .catch(popupAjaxError) .finally(() => this.set('loading', false)); }, actions: { confirmPassword() { - if(!this.get('password')) { - return; - } + if (!this.get('password')) return; this.set('loading', true); - this.get('content').loadSecondFactorCodes(this.get('password')).then((resp) => { - if(resp.error) { - this.set('errorMessage',resp.error); - return; - } - this.set('errorMessage',null); - this.set('secondFactorKey', resp.key); - this.set('secondFactorImage', resp.qr); - }).catch(popupAjaxError) + + this.get('content').loadSecondFactorCodes(this.get('password')) + .then(response => { + if(response.error) { + this.set('errorMessage', response.error); + return; + } + + this.setProperties({ + errorMessage: null, + secondFactorKey: response.key, + secondFactorImage: response.qr, + }); + }) + .catch(popupAjaxError) .finally(() => this.set('loading', false)); }, + showSecondFactorKey() { this.set('showSecondFactorKey', true); }, + enableSecondFactor() { this.toggleSecondFactor(true); }, + disableSecondFactor() { this.toggleSecondFactor(false); } diff --git a/app/assets/javascripts/discourse/models/user.js.es6 b/app/assets/javascripts/discourse/models/user.js.es6 index ad06bb36e4d..eef39aa8acc 100644 --- a/app/assets/javascripts/discourse/models/user.js.es6 +++ b/app/assets/javascripts/discourse/models/user.js.es6 @@ -305,19 +305,16 @@ const User = RestModel.extend({ }, loadSecondFactorCodes(password) { - return ajax("/second_factor/create", { - dataType: 'json', - data: { login: this.get('username'), - password: password}, + return ajax("/u/second_factors.json", { + data: { password }, type: 'POST' }); }, toggleSecondFactor(token, enable) { - return ajax(userPath(`${this.get('username_lower')}/preferences/second-factor`), { - dataType: 'json', - data: { token, enable }, - type: 'POST' + return ajax("/u/second_factor.json", { + data: { second_factor_token: token, enable }, + type: 'PUT' }); }, diff --git a/app/assets/javascripts/discourse/routes/preferences-second-factor.js.es6 b/app/assets/javascripts/discourse/routes/preferences-second-factor.js.es6 index fdc9a5fac75..b688ec813bc 100644 --- a/app/assets/javascripts/discourse/routes/preferences-second-factor.js.es6 +++ b/app/assets/javascripts/discourse/routes/preferences-second-factor.js.es6 @@ -9,13 +9,7 @@ export default RestrictedUserRoute.extend({ return this.render({ into: 'user' }); }, - // A bit odd, but if we leave to /preferences we need to re-render that outlet - deactivate() { - this._super(); - this.render('preferences', { into: 'user', controller: 'preferences' }); - }, - - setupController(controller, user) { - controller.setProperties({ model: user, newUsername: user.get('username') }); + setupController(controller, model) { + controller.setProperties({ model, newUsername: model.get('username') }); } }); diff --git a/app/assets/javascripts/discourse/routes/preferences.js.es6 b/app/assets/javascripts/discourse/routes/preferences.js.es6 index ef42132ddcf..128a3017315 100644 --- a/app/assets/javascripts/discourse/routes/preferences.js.es6 +++ b/app/assets/javascripts/discourse/routes/preferences.js.es6 @@ -18,6 +18,7 @@ export default RestrictedUserRoute.extend({ showTwoFactorModal() { showModal('second-factor-intro'); }, + showAvatarSelector() { showModal('avatar-selector'); diff --git a/app/assets/javascripts/discourse/templates/components/second-factor-form.hbs b/app/assets/javascripts/discourse/templates/components/second-factor-form.hbs index 0535a9578cd..a1d5e033405 100644 --- a/app/assets/javascripts/discourse/templates/components/second-factor-form.hbs +++ b/app/assets/javascripts/discourse/templates/components/second-factor-form.hbs @@ -1,6 +1,7 @@
{{#second-factor-form}} - {{text-field value=loginSecondFactor id="login-second-factor" autocorrect="off" autocapitalize="off" autofocus="autofocus"}} + {{text-field value=loginSecondFactor + id="login-second-factor" + autocorrect="off" + autocapitalize="off" + autofocus="autofocus"}} {{/second-factor-form}} {{/if}} @@ -44,11 +48,11 @@ {{/if}} {{#if canLoginLocal}} - + {{d-button action="login" + icon="unlock" + label=loginButtonLabel + disabled=loginDisabled + class='btn btn-large btn-primary'}} {{#if showSignupLink}}