From ada2de97330496b0be50d5aa4b710b469f3b41cc Mon Sep 17 00:00:00 2001 From: Maxim Filippov Date: Tue, 24 Sep 2019 22:55:42 +0000 Subject: [PATCH] Ability to require user's password reset --- CHANGELOG.md | 3 ++- src/api/users.js | 9 +++++++++ src/lang/en.js | 2 ++ src/store/modules/users.js | 17 ++++++++++++++++- .../users/components/MultipleUsersMenu.vue | 14 ++++++++++++++ src/views/users/index.vue | 8 ++++++++ test/views/users/multipleUsersMenu.test.js | 12 ++++++------ 7 files changed, 57 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 75553acf..ef27fb4b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ### Added - Emoji pack configuration +- Ability to require user's password reset ## [1.1.0] - 2019-09-15 @@ -26,7 +27,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - removes "Dashboard" from dropdown menu - makes all single selects clearable and allow to enter custom values in all multiple selects -- removes legacy activitypub accept_blocks setting +- removes legacy activitypub accept_blocks setting ### Fixed diff --git a/src/api/users.js b/src/api/users.js index 0f8e4a41..1e97da92 100644 --- a/src/api/users.js +++ b/src/api/users.js @@ -66,6 +66,15 @@ export async function getPasswordResetToken(nickname, authHost, token) { }) } +export async function requirePasswordReset(nickname, authHost, token) { + return await request({ + baseURL: baseName(authHost), + url: `/api/pleroma/admin/users/${nickname}/force_password_reset`, + method: 'patch', + headers: authHeaders(token) + }) +} + export async function searchUsers(query, filters, authHost, token, page = 1) { return await request({ baseURL: baseName(authHost), diff --git a/src/lang/en.js b/src/lang/en.js index f2c6c137..eed40f5f 100644 --- a/src/lang/en.js +++ b/src/lang/en.js @@ -200,6 +200,7 @@ export default { disableRemoteSubscriptionForMultiple: 'Disallow following users from remote instances', disableAnySubscription: 'Disallow following user at all', disableAnySubscriptionForMultiple: 'Disallow following users at all', + requirePasswordReset: 'Require password reset on next login', selectUsers: 'Select users to apply actions to multiple users', moderateUsers: 'Moderate multiple users', createAccount: 'Create new account', @@ -212,6 +213,7 @@ export default { deleteMultipleUsersConfirmation: 'Are you sure you want to delete accounts of all selected users?', 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?', ok: 'Okay', completed: 'Completed', cancel: 'Cancel', diff --git a/src/store/modules/users.js b/src/store/modules/users.js index f732c810..36a7f507 100644 --- a/src/store/modules/users.js +++ b/src/store/modules/users.js @@ -1,4 +1,16 @@ -import { addRight, createNewAccount, deleteRight, deleteUser, fetchUsers, getPasswordResetToken, searchUsers, tagUser, toggleUserActivation, untagUser } from '@/api/users' +import { + addRight, + createNewAccount, + deleteRight, + deleteUser, + fetchUsers, + getPasswordResetToken, + searchUsers, + tagUser, + toggleUserActivation, + untagUser, + requirePasswordReset +} from '@/api/users' const users = { state: { @@ -83,6 +95,9 @@ const users = { const users = state.fetchedUsers.filter(user => user.nickname !== data) commit('SET_USERS', users) }, + async RequirePasswordReset({ commit, getters, state }, user) { + await requirePasswordReset(user.nickname, getters.authHost, getters.token) + }, async FetchUsers({ commit, state, getters }, { page }) { commit('SET_LOADING', true) const filters = Object.keys(state.filters).filter(filter => state.filters[filter]).join() diff --git a/src/views/users/components/MultipleUsersMenu.vue b/src/views/users/components/MultipleUsersMenu.vue index 02eb7cd5..ff016f51 100644 --- a/src/views/users/components/MultipleUsersMenu.vue +++ b/src/views/users/components/MultipleUsersMenu.vue @@ -39,6 +39,10 @@ @click.native="deleteMultipleUsers"> {{ $t('users.deleteAccounts') }} + + {{ $t('users.requirePasswordReset') }} +
{{ $t('users.forceNsfw') }} @@ -227,6 +231,9 @@ export default { message: this.$t('users.completed') }) this.$emit('apply-action') + }, + requirePasswordReset: () => { + this.selectedUsers.map(user => this.$store.dispatch('RequirePasswordReset', user)) } } }, @@ -265,6 +272,13 @@ export default { remove ) }, + requirePasswordReset() { + const { requirePasswordReset } = this.mappers() + this.confirmMessage( + this.$t('users.requirePasswordResetConfirmation'), + requirePasswordReset + ) + }, addTagForMultipleUsers(tag) { const { addTag } = this.mappers() this.confirmMessage( diff --git a/src/views/users/index.vue b/src/views/users/index.vue index fd26a993..16160a97 100644 --- a/src/views/users/index.vue +++ b/src/views/users/index.vue @@ -133,6 +133,11 @@ @click.native="getPasswordResetToken(scope.row.nickname)"> {{ $t('users.getPasswordResetToken') }} + + {{ $t('users.requirePasswordReset') }} + @@ -259,6 +264,9 @@ export default { this.resetPasswordDialogOpen = true this.$store.dispatch('GetPasswordResetToken', nickname) }, + requirePasswordReset(nickname) { + this.$store.dispatch('RequirePasswordReset', { nickname }) + }, handleDeactivation({ nickname }) { this.$store.dispatch('ToggleUserActivation', nickname) }, diff --git a/test/views/users/multipleUsersMenu.test.js b/test/views/users/multipleUsersMenu.test.js index b4388716..355430e1 100644 --- a/test/views/users/multipleUsersMenu.test.js +++ b/test/views/users/multipleUsersMenu.test.js @@ -251,15 +251,15 @@ describe('Apply users actions to multiple users', () => { const addTagForMultipleUsersStub = jest.fn() wrapper.setMethods({ addTagForMultipleUsers: addTagForMultipleUsersStub }) - wrapper.find(`.el-dropdown-menu__item:nth-child(8) button:nth-child(1)`).trigger('click') + wrapper.find(`.el-dropdown-menu__item:nth-child(9) button:nth-child(1)`).trigger('click') expect(wrapper.vm.addTagForMultipleUsers).toHaveBeenCalled() expect(wrapper.vm.addTagForMultipleUsers).toHaveBeenCalledWith('force_nsfw') - wrapper.find(`.el-dropdown-menu__item:nth-child(10) button:nth-child(1)`).trigger('click') + wrapper.find(`.el-dropdown-menu__item:nth-child(11) button:nth-child(1)`).trigger('click') expect(wrapper.vm.addTagForMultipleUsers).toHaveBeenCalled() expect(wrapper.vm.addTagForMultipleUsers).toHaveBeenCalledWith('force_unlisted') - wrapper.find(`.el-dropdown-menu__item:nth-child(12) button:nth-child(1)`).trigger('click') + wrapper.find(`.el-dropdown-menu__item:nth-child(13) button:nth-child(1)`).trigger('click') expect(wrapper.vm.addTagForMultipleUsers).toHaveBeenCalled() expect(wrapper.vm.addTagForMultipleUsers).toHaveBeenCalledWith('disable_remote_subscription') @@ -292,15 +292,15 @@ describe('Apply users actions to multiple users', () => { const removeTagFromMultipleUsersStub = jest.fn() wrapper.setMethods({ removeTagFromMultipleUsers: removeTagFromMultipleUsersStub }) - wrapper.find(`.el-dropdown-menu__item:nth-child(9) button:nth-child(2)`).trigger('click') + wrapper.find(`.el-dropdown-menu__item:nth-child(10) button:nth-child(2)`).trigger('click') expect(wrapper.vm.removeTagFromMultipleUsers).toHaveBeenCalled() expect(wrapper.vm.removeTagFromMultipleUsers).toHaveBeenCalledWith('strip_media') - wrapper.find(`.el-dropdown-menu__item:nth-child(11) button:nth-child(2)`).trigger('click') + wrapper.find(`.el-dropdown-menu__item:nth-child(12) button:nth-child(2)`).trigger('click') expect(wrapper.vm.removeTagFromMultipleUsers).toHaveBeenCalled() expect(wrapper.vm.removeTagFromMultipleUsers).toHaveBeenCalledWith('sandbox') - wrapper.find(`.el-dropdown-menu__item:nth-child(13) button:nth-child(2)`).trigger('click') + wrapper.find(`.el-dropdown-menu__item:nth-child(14) button:nth-child(2)`).trigger('click') expect(wrapper.vm.removeTagFromMultipleUsers).toHaveBeenCalled() expect(wrapper.vm.removeTagFromMultipleUsers).toHaveBeenCalledWith('disable_any_subscription')