diff --git a/src/api/users.js b/src/api/users.js index fb168d6c..3755ee7c 100644 --- a/src/api/users.js +++ b/src/api/users.js @@ -136,4 +136,24 @@ export async function fetchUserStatuses(id, authHost, godmode, token) { }) } +export async function confirmUserEmail(nicknames, authHost, token) { + return await request({ + baseURL: baseName(authHost), + url: '/api/pleroma/admin/users/confirm_email', + method: 'patch', + headers: authHeaders(token), + data: { nicknames } + }) +} + +export async function resendConfirmationEmail(nicknames, authHost, token) { + return await request({ + baseURL: baseName(authHost), + url: '/api/pleroma/admin/users/resend_confirmation_email', + method: 'patch', + headers: authHeaders(token), + data: { nicknames } + }) +} + const authHeaders = (token) => token ? { 'Authorization': `Bearer ${getToken()}` } : {} diff --git a/src/lang/en.js b/src/lang/en.js index 29ba5eb3..dd3326e5 100644 --- a/src/lang/en.js +++ b/src/lang/en.js @@ -175,6 +175,7 @@ export default { external: 'external', deactivated: 'deactivated', active: 'active', + unconfirmed: 'unconfirmed', actions: 'Actions', activate: 'Activate', deactivate: 'Deactivate', @@ -213,6 +214,8 @@ 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?', + confirmAccountsConfirmation: 'Are you sure you want to confirm emails for all selected users?', + resendEmailConfirmation: 'Are you sure you want to resend confirmation email for all selected users?', mailerMustBeEnabled: 'To require user\'s password reset you must enable mailer.', ok: 'Okay', completed: 'Completed', @@ -230,7 +233,11 @@ export default { invalidNicknameError: 'Username can include "a-z", "A-Z" and "0-9" characters', getPasswordResetToken: 'Get password reset token', passwordResetTokenCreated: 'Password reset token was created', - accountCreated: 'New account was created!' + accountCreated: 'New account was created!', + unconfirmedEmail: 'User didn\'t confirm the email', + confirmAccount: 'Confirm account', + confirmAccounts: 'Confirm accounts', + resendConfirmation: 'Resend confirmation email' }, statuses: { statuses: 'Statuses', diff --git a/src/store/modules/users.js b/src/store/modules/users.js index 0290b888..160b4ff2 100644 --- a/src/store/modules/users.js +++ b/src/store/modules/users.js @@ -12,7 +12,9 @@ import { searchUsers, tagUser, untagUser, - requirePasswordReset + requirePasswordReset, + confirmUserEmail, + resendConfirmationEmail } from '@/api/users' const users = { @@ -151,6 +153,31 @@ const users = { } dispatch('SuccessMessage') }, + async ConfirmUsersEmail({ commit, dispatch, getters, state }, users) { + const updatedUsers = users.map(user => { + return { ...user, confirmation_pending: false } + }) + commit('SWAP_USERS', updatedUsers) + + const usersNicknames = users.map(user => user.nickname) + try { + await confirmUserEmail(usersNicknames, getters.authHost, getters.token) + } catch (_e) { + return + } finally { + dispatch('SearchUsers', { query: state.searchQuery, page: state.currentPage }) + } + dispatch('SuccessMessage') + }, + async ResendConfirmationEmail({ dispatch, getters }, users) { + const usersNicknames = users.map(user => user.nickname) + try { + await resendConfirmationEmail(usersNicknames, getters.authHost, getters.token) + } catch (_e) { + return + } + dispatch('SuccessMessage') + }, async DeleteRight({ commit, dispatch, getters, state }, { users, right }) { const updatedUsers = users.map(user => { return user.local ? { ...user, roles: { ...user.roles, [right]: false }} : user diff --git a/src/views/users/components/MultipleUsersMenu.vue b/src/views/users/components/MultipleUsersMenu.vue index f3be52cf..1fdc029b 100644 --- a/src/views/users/components/MultipleUsersMenu.vue +++ b/src/views/users/components/MultipleUsersMenu.vue @@ -26,6 +26,15 @@ @click.native="revokeRightFromMultipleUsers('moderator')"> {{ $t('users.revokeModerator') }} + + {{ $t('users.confirmAccounts') }} + + + {{ $t('users.resendConfirmation') }} + @@ -209,6 +218,18 @@ export default { const filtered = this.selectedUsers.filter(user => user.local) filtered.map(user => this.$store.dispatch('RequirePasswordReset', user)) this.$emit('apply-action') + }, + confirmAccounts: () => { + const filtered = this.selectedUsers.filter(user => user.local && user.confirmation_pending) + const confirmAccountFn = async(users) => await this.$store.dispatch('ConfirmUsersEmail', users) + + applyAction(filtered, confirmAccountFn) + }, + resendConfirmation: () => { + const filtered = this.selectedUsers.filter(user => user.local && user.confirmation_pending) + const resendConfirmationFn = async(users) => await this.$store.dispatch('ResendConfirmationEmail', users) + + applyAction(filtered, resendConfirmationFn) } } }, @@ -276,6 +297,20 @@ export default { removeTag(tag) ) }, + confirmAccountsForMultipleUsers() { + const { confirmAccounts } = this.mappers() + this.confirmMessage( + this.$t('users.confirmAccountsConfirmation'), + confirmAccounts + ) + }, + resendConfirmationForMultipleUsers() { + const { resendConfirmation } = this.mappers() + this.confirmMessage( + this.$t('users.resendEmailConfirmation'), + resendConfirmation + ) + }, confirmMessage(message, applyAction) { this.$confirm(message, { confirmButtonText: this.$t('users.ok'), diff --git a/src/views/users/index.vue b/src/views/users/index.vue index f9b5e10f..93b6a7f1 100644 --- a/src/views/users/index.vue +++ b/src/views/users/index.vue @@ -57,6 +57,11 @@ {{ isDesktop ? $t('users.moderator') : getFirstLetter($t('users.moderator')) }} + + + {{ isDesktop ? $t('users.unconfirmed') : getFirstLetter($t('users.unconfirmed')) }} + + @@ -88,6 +93,17 @@ @click.native="handleDeletion(scope.row)"> {{ $t('users.deleteAccount') }} + + {{ $t('users.confirmAccount') }} + + + {{ $t('users.resendConfirmation') }} +