From 8956e68fa16d29d4d0712b7ded7b51d052a80776 Mon Sep 17 00:00:00 2001 From: Maxim Filippov Date: Fri, 27 Sep 2019 18:32:14 +0300 Subject: [PATCH 1/2] `mailerEnabled` must be set to `true` in order to require password reset (password reset currently only works via email) --- CHANGELOG.md | 4 ++++ src/api/nodeInfo.js | 10 ++++++++++ src/api/utils.js | 2 +- src/lang/en.js | 1 + src/store/modules/user.js | 11 ++++++++++- src/store/modules/users.js | 3 ++- src/views/users/components/MultipleUsersMenu.vue | 8 ++++++++ src/views/users/index.vue | 8 ++++++++ 8 files changed, 44 insertions(+), 3 deletions(-) create mode 100644 src/api/nodeInfo.js diff --git a/CHANGELOG.md b/CHANGELOG.md index ac8ad270..be0fb971 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## Unreleased +### Changed + +- `mailerEnabled` must be set to `true` in order to require password reset (password reset currently only works via email) + ## [1.2.0] - 2019-09-27 ### Added diff --git a/src/api/nodeInfo.js b/src/api/nodeInfo.js new file mode 100644 index 00000000..c67df01b --- /dev/null +++ b/src/api/nodeInfo.js @@ -0,0 +1,10 @@ +import request from '@/utils/request' +import { baseName } from './utils' + +export async function getNodeInfo(authHost) { + return await request({ + baseURL: baseName(authHost), + url: `/nodeinfo/2.0.json`, + method: 'get' + }) +} diff --git a/src/api/utils.js b/src/api/utils.js index 1346a204..9f47a1f8 100644 --- a/src/api/utils.js +++ b/src/api/utils.js @@ -1,7 +1,7 @@ const isLocalhost = (instanceName) => instanceName.startsWith('localhost:') || instanceName.startsWith('127.0.0.1:') -export const baseName = (instanceName) => { +export const baseName = (instanceName = 'localhost') => { if (instanceName.match(/https?:\/\//)) { return instanceName } else { diff --git a/src/lang/en.js b/src/lang/en.js index 5d705cdf..8088e441 100644 --- a/src/lang/en.js +++ b/src/lang/en.js @@ -215,6 +215,7 @@ export default { addTagForMultipleUsersConfirmation: 'Are you sure you want to apply tag to all selected users?', removeTagFromMultipleUsersConfirmation: 'Are you sure you want to remove tag from all selected users?', requirePasswordResetConfirmation: 'Are you sure you want to require password reset for all selected users?', + mailerMustBeEnabled: 'To require user\'s password reset you must enable mailer.', ok: 'Okay', completed: 'Completed', cancel: 'Cancel', diff --git a/src/store/modules/user.js b/src/store/modules/user.js index 18ff5419..3ab9339d 100644 --- a/src/store/modules/user.js +++ b/src/store/modules/user.js @@ -1,4 +1,5 @@ import { loginByUsername, getUserInfo } from '@/api/login' +import { getNodeInfo } from '@/api/nodeInfo' import { getToken, setToken, removeToken, getAuthHost, setAuthHost, removeAuthHost } from '@/utils/auth' const user = { @@ -15,7 +16,8 @@ const user = { roles: [], setting: { articlePlatform: [] - } + }, + nodeInfo: {} }, mutations: { @@ -48,6 +50,9 @@ const user = { }, SET_AUTH_HOST: (state, authHost) => { state.authHost = authHost + }, + SET_NODE_INFO: (state, nodeInfo) => { + state.nodeInfo = nodeInfo } }, @@ -67,7 +72,11 @@ const user = { }) }) }, + async GetNodeInfo({ commit, state }) { + const nodeInfo = await getNodeInfo(state.authHost) + commit('SET_NODE_INFO', nodeInfo.data) + }, GetUserInfo({ commit, state }) { return new Promise((resolve, reject) => { getUserInfo(state.token, state.authHost).then(response => { diff --git a/src/store/modules/users.js b/src/store/modules/users.js index 36a7f507..b3d35108 100644 --- a/src/store/modules/users.js +++ b/src/store/modules/users.js @@ -98,10 +98,11 @@ const users = { async RequirePasswordReset({ commit, getters, state }, user) { await requirePasswordReset(user.nickname, getters.authHost, getters.token) }, - async FetchUsers({ commit, state, getters }, { page }) { + async FetchUsers({ commit, state, getters, dispatch }, { page }) { commit('SET_LOADING', true) const filters = Object.keys(state.filters).filter(filter => state.filters[filter]).join() const response = await fetchUsers(filters, getters.authHost, getters.token, page) + await dispatch('GetNodeInfo') loadUsers(commit, page, response.data) }, async GetPasswordResetToken({ commit, state, getters }, nickname) { diff --git a/src/views/users/components/MultipleUsersMenu.vue b/src/views/users/components/MultipleUsersMenu.vue index ff016f51..ecd2baf2 100644 --- a/src/views/users/components/MultipleUsersMenu.vue +++ b/src/views/users/components/MultipleUsersMenu.vue @@ -273,6 +273,14 @@ export default { ) }, requirePasswordReset() { + const mailerEnabled = this.$store.state.user.nodeInfo.metadata.mailerEnabled + + if (!mailerEnabled) { + this.$alert(this.$t('users.mailerMustBeEnabled'), 'Error', { type: 'error' }) + + return + } + const { requirePasswordReset } = this.mappers() this.confirmMessage( this.$t('users.requirePasswordResetConfirmation'), diff --git a/src/views/users/index.vue b/src/views/users/index.vue index 16160a97..062b23c8 100644 --- a/src/views/users/index.vue +++ b/src/views/users/index.vue @@ -265,6 +265,14 @@ export default { this.$store.dispatch('GetPasswordResetToken', nickname) }, requirePasswordReset(nickname) { + const mailerEnabled = this.$store.state.user.nodeInfo.metadata.mailerEnabled + + if (!mailerEnabled) { + this.$alert(this.$t('users.mailerMustBeEnabled'), 'Error', { type: 'error' }) + + return + } + this.$store.dispatch('RequirePasswordReset', { nickname }) }, handleDeactivation({ nickname }) { From 3daf35d0b0c583837a8e96a765d54d3880aaff99 Mon Sep 17 00:00:00 2001 From: Maxim Filippov Date: Fri, 27 Sep 2019 19:40:25 +0300 Subject: [PATCH 2/2] Fix tests --- src/api/__mocks__/nodeInfo.js | 9 +++++++++ src/utils/request.js | 2 +- test/views/login/index.test.js | 1 + test/views/users/index.test.js | 1 + test/views/users/multipleUsersMenu.test.js | 1 + test/views/users/usersFilters.test.js | 1 + 6 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 src/api/__mocks__/nodeInfo.js diff --git a/src/api/__mocks__/nodeInfo.js b/src/api/__mocks__/nodeInfo.js new file mode 100644 index 00000000..6daf074e --- /dev/null +++ b/src/api/__mocks__/nodeInfo.js @@ -0,0 +1,9 @@ +export async function getNodeInfo(authHost) { + const data = { + metadata: { + mailerEnabled: true + } + } + + return Promise.resolve({ data }) +} diff --git a/src/utils/request.js b/src/utils/request.js index 271fe591..bbed6501 100644 --- a/src/utils/request.js +++ b/src/utils/request.js @@ -10,7 +10,7 @@ const service = axios.create({ service.interceptors.response.use( response => response, error => { - console.log('Error ' + error) + console.log(`Error ${error}`) console.log(error.response.data) // If there's an "error" property in the json, use it diff --git a/test/views/login/index.test.js b/test/views/login/index.test.js index b2986b5d..03e45667 100644 --- a/test/views/login/index.test.js +++ b/test/views/login/index.test.js @@ -16,6 +16,7 @@ localVue.use(Vuex) localVue.use(VueRouter) localVue.use(Element) +jest.mock('@/api/nodeInfo') jest.mock('@/api/login') describe('Login', () => { diff --git a/test/views/users/index.test.js b/test/views/users/index.test.js index 863186f3..d435e1ce 100644 --- a/test/views/users/index.test.js +++ b/test/views/users/index.test.js @@ -14,6 +14,7 @@ const localVue = createLocalVue() localVue.use(Vuex) localVue.use(Element) +jest.mock('@/api/nodeInfo') jest.mock('@/api/users') describe('Search and filter users', () => { diff --git a/test/views/users/multipleUsersMenu.test.js b/test/views/users/multipleUsersMenu.test.js index 355430e1..c92232bf 100644 --- a/test/views/users/multipleUsersMenu.test.js +++ b/test/views/users/multipleUsersMenu.test.js @@ -13,6 +13,7 @@ const localVue = createLocalVue() localVue.use(Vuex) localVue.use(Element) +jest.mock('@/api/nodeInfo') jest.mock('@/api/users') describe('Apply users actions to multiple users', () => { diff --git a/test/views/users/usersFilters.test.js b/test/views/users/usersFilters.test.js index 9cf14c66..e56822ca 100644 --- a/test/views/users/usersFilters.test.js +++ b/test/views/users/usersFilters.test.js @@ -13,6 +13,7 @@ const localVue = createLocalVue() localVue.use(Vuex) localVue.use(Element) +jest.mock('@/api/nodeInfo') jest.mock('@/api/users') describe('Filters users', () => {