implement Move activities #26

Merged
floatingghost merged 5 commits from :move into develop 2022-07-04 16:38:59 +00:00
5 changed files with 225 additions and 1 deletions

View file

@ -37,6 +37,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Media modal now also displays description and counter position in gallery (i.e. 1/5) - Media modal now also displays description and counter position in gallery (i.e. 1/5)
- Ability to rearrange order of attachments when uploading - Ability to rearrange order of attachments when uploading
- Enabled users to zoom and pan images in media viewer with mouse and touch - Enabled users to zoom and pan images in media viewer with mouse and touch
- Added frontend ui for account migration
## [2.4.2] - 2022-01-09 ## [2.4.2] - 2022-01-09

View file

@ -15,11 +15,21 @@ const SecurityTab = {
deleteAccountError: false, deleteAccountError: false,
changePasswordInputs: [ '', '', '' ], changePasswordInputs: [ '', '', '' ],
changedPassword: false, changedPassword: false,
changePasswordError: false changePasswordError: false,
moveAccountTarget: '',
moveAccountPassword: '',
movedAccount: false,
moveAccountError: false,
aliases: [],
listAliasesError: false,
addAliasTarget: '',
addedAlias: false,
addAliasError: false
} }
}, },
created () { created () {
this.$store.dispatch('fetchTokens') this.$store.dispatch('fetchTokens')
this.fetchAliases()
}, },
components: { components: {
ProgressButton, ProgressButton,
@ -92,6 +102,49 @@ const SecurityTab = {
} }
}) })
}, },
moveAccount () {
const params = {
targetAccount: this.moveAccountTarget,
password: this.moveAccountPassword
}
this.$store.state.api.backendInteractor.moveAccount(params)
.then((res) => {
if (res.status === 'success') {
this.movedAccount = true
this.moveAccountError = false
} else {
this.movedAccount = false
this.moveAccountError = res.error
}
})
},
removeAlias (alias) {
this.$store.state.api.backendInteractor.deleteAlias({ alias })
.then(() => this.fetchAliases())
},
addAlias () {
this.$store.state.api.backendInteractor.addAlias({ alias: this.addAliasTarget })
.then((res) => {
this.addedAlias = true
this.addAliasError = false
this.addAliasTarget = ''
})
.catch((error) => {
this.addedAlias = false
this.addAliasError = error
})
.then(() => this.fetchAliases())
},
fetchAliases () {
this.$store.state.api.backendInteractor.listAliases()
.then((res) => {
this.aliases = res.aliases
this.listAliasesError = false
})
.catch((error) => {
this.listAliasesError = error.error
})
},
logout () { logout () {
this.$store.dispatch('logout') this.$store.dispatch('logout')
this.$router.replace('/') this.$router.replace('/')

View file

@ -103,6 +103,114 @@
</table> </table>
</div> </div>
<mfa /> <mfa />
<div class="setting-item">
<h2>{{ $t('settings.account_alias') }}</h2>
<table>
<thead>
<tr>
<th>{{ $t('settings.account_alias_table_head') }}</th>
<th />
</tr>
</thead>
<tbody>
<tr
v-for="alias in aliases"
:key="alias"
>
<td>{{ alias }}</td>
<td class="actions">
<button
class="btn button-default"
@click="removeAlias(alias)"
>
{{ $t('settings.remove_alias') }}
</button>
</td>
</tr>
</tbody>
</table>
<div
v-if="listAliasesError"
class="alert error"
>
{{ $t('settings.list_aliases_error', { error }) }}
<FAIcon
class="fa-scale-110 fa-old-padding"
icon="times"
:title="$t('settings.hide_list_aliases_error_action')"
@click="listAliasesError = false"
/>
</div>
<div>
<i18n
path="settings.new_alias_target"
tag="p"
>
<code
place="example"
>
foo@example.org
</code>
</i18n>
<input
v-model="addAliasTarget"
>
</div>
<button
class="btn button-default"
@click="addAlias"
>
{{ $t('settings.save') }}
</button>
<p v-if="addedAlias">
{{ $t('settings.added_alias') }}
</p>
<template v-if="addAliasError !== false">
<p>{{ $t('settings.add_alias_error', { error: addAliasError }) }}</p>
</template>
</div>
<div class="setting-item">
<h2>{{ $t('settings.move_account') }}</h2>
<p>{{ $t('settings.move_account_notes') }}</p>
<div>
<i18n
path="settings.move_account_target"
tag="p"
>
<code
place="example"
>
foo@example.org
</code>
</i18n>
<input
v-model="moveAccountTarget"
>
</div>
<div>
<p>{{ $t('settings.current_password') }}</p>
<input
v-model="moveAccountPassword"
type="password"
autocomplete="current-password"
>
</div>
<button
class="btn button-default"
@click="moveAccount"
>
{{ $t('settings.save') }}
</button>
<p v-if="movedAccount">
{{ $t('settings.moved_account') }}
</p>
<template v-if="moveAccountError !== false">
<p>{{ $t('settings.move_account_error', { error: moveAccountError }) }}</p>
</template>
</div>
<div class="setting-item"> <div class="setting-item">
<h2>{{ $t('settings.delete_account') }}</h2> <h2>{{ $t('settings.delete_account') }}</h2>
<p v-if="!deletingAccount"> <p v-if="!deletingAccount">

View file

@ -349,6 +349,19 @@
"delete_account_description": "Permanently delete your data and deactivate your account.", "delete_account_description": "Permanently delete your data and deactivate your account.",
"delete_account_error": "There was an issue deleting your account. If this persists please contact your instance administrator.", "delete_account_error": "There was an issue deleting your account. If this persists please contact your instance administrator.",
"delete_account_instructions": "Type your password in the input below to confirm account deletion.", "delete_account_instructions": "Type your password in the input below to confirm account deletion.",
"account_alias": "Account aliases",
"account_alias_table_head": "Alias",
"list_aliases_error": "Error fetching aliases: {error}",
"hide_list_aliases_error_action": "Close",
"remove_alias": "Remove this alias",
"new_alias_target": "Add a new alias (e.g. {example})",
"added_alias": "Alias is added.",
"add_alias_error": "Error adding alias: {error}",
"move_account": "Move account",
"move_account_notes": "If you want to move the account somewhere else, you must go to your target account and add an alias pointing here.",
"move_account_target": "Target account (e.g. {example})",
"moved_account": "Account is moved.",
"move_account_error": "Error moving account: {error}",
"discoverable": "Allow discovery of this account in search results and other services", "discoverable": "Allow discovery of this account in search results and other services",
"domain_mutes": "Domains", "domain_mutes": "Domains",
"avatar_size_instruction": "The recommended minimum size for avatar images is 150x150 pixels.", "avatar_size_instruction": "The recommended minimum size for avatar images is 150x150 pixels.",

View file

@ -9,6 +9,8 @@ const FOLLOW_IMPORT_URL = '/api/pleroma/follow_import'
const DELETE_ACCOUNT_URL = '/api/pleroma/delete_account' const DELETE_ACCOUNT_URL = '/api/pleroma/delete_account'
const CHANGE_EMAIL_URL = '/api/pleroma/change_email' const CHANGE_EMAIL_URL = '/api/pleroma/change_email'
const CHANGE_PASSWORD_URL = '/api/pleroma/change_password' const CHANGE_PASSWORD_URL = '/api/pleroma/change_password'
const MOVE_ACCOUNT_URL = '/api/pleroma/move_account'
const ALIASES_URL = '/api/pleroma/aliases'
const TAG_USER_URL = '/api/pleroma/admin/users/tag' const TAG_USER_URL = '/api/pleroma/admin/users/tag'
const PERMISSION_GROUP_URL = (screenName, right) => `/api/pleroma/admin/users/${screenName}/permission_group/${right}` const PERMISSION_GROUP_URL = (screenName, right) => `/api/pleroma/admin/users/${screenName}/permission_group/${right}`
const ACTIVATE_USER_URL = '/api/pleroma/admin/users/activate' const ACTIVATE_USER_URL = '/api/pleroma/admin/users/activate'
@ -897,6 +899,49 @@ const changeEmail = ({ credentials, email, password }) => {
.then((response) => response.json()) .then((response) => response.json())
} }
const moveAccount = ({ credentials, password, targetAccount }) => {
const form = new FormData()
form.append('password', password)
form.append('target_account', targetAccount)
return fetch(MOVE_ACCOUNT_URL, {
body: form,
method: 'POST',
headers: authHeaders(credentials)
})
.then((response) => response.json())
}
const addAlias = ({ credentials, alias }) => {
return promisedRequest({
url: ALIASES_URL,
method: 'PUT',
credentials,
payload: { alias }
})
}
const deleteAlias = ({ credentials, alias }) => {
return promisedRequest({
url: ALIASES_URL,
method: 'DELETE',
credentials,
payload: { alias }
})
}
const listAliases = ({ credentials }) => {
return promisedRequest({
url: ALIASES_URL,
method: 'GET',
credentials,
params: {
_cacheBooster: (new Date()).getTime()
}
})
}
const changePassword = ({ credentials, password, newPassword, newPasswordConfirmation }) => { const changePassword = ({ credentials, password, newPassword, newPasswordConfirmation }) => {
const form = new FormData() const form = new FormData()
@ -1461,6 +1506,10 @@ const apiService = {
importFollows, importFollows,
deleteAccount, deleteAccount,
changeEmail, changeEmail,
moveAccount,
addAlias,
deleteAlias,
listAliases,
changePassword, changePassword,
settingsMFA, settingsMFA,
mfaDisableOTP, mfaDisableOTP,