Merge pull request #28855 from nextcloud/backport/28840/stable22

[stable22] let user choose notification email in user settings
This commit is contained in:
blizzz 2021-09-16 12:58:10 +02:00 committed by GitHub
commit 9888b05970
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
27 changed files with 183 additions and 79 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -204,7 +204,7 @@ class PersonalInfo implements ISettings {
* @return array
*/
private function getEmails(IAccount $account): array {
$primaryEmail = [
$systemEmail = [
'value' => $account->getProperty(IAccountManager::PROPERTY_EMAIL)->getValue(),
'scope' => $account->getProperty(IAccountManager::PROPERTY_EMAIL)->getScope(),
'verified' => $account->getProperty(IAccountManager::PROPERTY_EMAIL)->getVerified(),
@ -216,14 +216,16 @@ class PersonalInfo implements ISettings {
'value' => $property->getValue(),
'scope' => $property->getScope(),
'verified' => $property->getVerified(),
'locallyVerified' => $property->getLocallyVerified(),
];
},
$account->getPropertyCollection(IAccountManager::COLLECTION_EMAIL)->getProperties()
);
$emails = [
'primaryEmail' => $primaryEmail,
'primaryEmail' => $systemEmail,
'additionalEmails' => $additionalEmails,
'notificationEmail' => (string)$account->getUser()->getPrimaryEMailAddress(),
];
return $emails;

View file

@ -59,11 +59,19 @@
@click.stop.prevent="deleteEmail">
{{ deleteEmailLabel }}
</ActionButton>
<ActionButton v-if="!primary || !isNotificationEmail"
:aria-label="setNotificationMailLabel"
:close-after-click="true"
:disabled="setNotificationMailDisabled"
icon="icon-favorite"
@click.stop.prevent="setNotificationMail">
{{ setNotificationMailLabel }}
</ActionButton>
</Actions>
</div>
</div>
<em v-if="primary">
<em v-if="isNotificationEmail">
{{ t('settings', 'Primary email for password reset and notifications') }}
</em>
</div>
@ -76,7 +84,8 @@ import { showError } from '@nextcloud/dialogs'
import debounce from 'debounce'
import FederationControl from './FederationControl'
import { savePrimaryEmail, saveAdditionalEmail, updateAdditionalEmail, removeAdditionalEmail } from '../../../service/PersonalInfoService'
import { VERIFICATION_ENUM } from '../../../constants/AccountPropertyConstants'
import { savePrimaryEmail, saveAdditionalEmail, saveNotificationEmail, updateAdditionalEmail, removeAdditionalEmail } from '../../../service/PersonalInfoService'
export default {
name: 'Email',
@ -104,6 +113,14 @@ export default {
type: Number,
default: 0,
},
activeNotificationEmail: {
type: String,
default: '',
},
localVerificationState: {
type: Number,
default: VERIFICATION_ENUM.NOT_VERIFIED,
},
},
data() {
@ -130,6 +147,19 @@ export default {
return t('settings', 'Additional email address {index}', { index: this.index + 1 })
},
setNotificationMailDisabled() {
return !this.primary && this.localVerificationState !== VERIFICATION_ENUM.VERIFIED
},
setNotificationMailLabel() {
if (this.isNotificationEmail) {
return t('settings', 'Unset as primary email')
} else if (!this.primary && this.localVerificationState !== VERIFICATION_ENUM.VERIFIED) {
return t('settings', 'This address is not confirmed')
}
return t('settings', 'Set as primary mail')
},
federationDisabled() {
return !this.initialEmail
},
@ -147,6 +177,11 @@ export default {
}
return t('settings', 'Delete email')
},
isNotificationEmail() {
return (this.email === this.activeNotificationEmail)
|| (this.primary && this.activeNotificationEmail === '')
},
},
mounted() {
@ -209,6 +244,22 @@ export default {
}
},
async setNotificationMail() {
try {
const newNotificationMailValue = (this.primary || this.isNotificationEmail) ? '' : this.initialEmail
const responseData = await saveNotificationEmail(newNotificationMailValue)
this.handleSetNotificationMailResponse({
notificationEmail: newNotificationMailValue,
status: responseData.ocs?.meta?.status,
})
} catch (e) {
this.handleSetNotificationMailResponse({
errorMessage: 'Unable to choose this email for notifications',
error: e,
})
}
},
async updateAdditionalEmail() {
try {
const responseData = await updateAdditionalEmail(this.initialEmail, this.email)
@ -239,6 +290,19 @@ export default {
}
},
handleSetNotificationMailResponse({ notificationEmail, status, errorMessage, error }) {
if (status === 'ok') {
this.$emit('update:notification-email', notificationEmail)
this.showCheckmarkIcon = true
setTimeout(() => { this.showCheckmarkIcon = false }, 2000)
} else {
showError(t('settings', errorMessage))
this.logger.error(errorMessage, error)
this.showErrorIcon = true
setTimeout(() => { this.showErrorIcon = false }, 2000)
}
},
handleResponse(status, errorMessage, error) {
if (status === 'ok') {
// Ensure that local initialEmail state reflects server state

View file

@ -34,7 +34,9 @@
:primary="true"
:scope.sync="primaryEmail.scope"
:email.sync="primaryEmail.value"
@update:email="onUpdateEmail" />
:active-notification-email.sync="notificationEmail"
@update:email="onUpdateEmail"
@update:notification-email="onUpdateNotificationEmail" />
</template>
<span v-else>
{{ primaryEmail.value || t('settings', 'No email address set') }}
@ -44,7 +46,10 @@
:index="index"
:scope.sync="additionalEmail.scope"
:email.sync="additionalEmail.value"
:local-verification-state="parseInt(additionalEmail.locallyVerified, 10)"
:active-notification-email.sync="notificationEmail"
@update:email="onUpdateEmail"
@update:notification-email="onUpdateNotificationEmail"
@deleteAdditionalEmail="onDeleteAdditionalEmail(index)" />
</form>
</template>
@ -59,7 +64,7 @@ import Email from './Email'
import { savePrimaryEmail, removeAdditionalEmail } from '../../../service/PersonalInfoService'
import { DEFAULT_ADDITIONAL_EMAIL_SCOPE } from '../../../constants/AccountPropertyConstants'
const { additionalEmails, primaryEmail } = loadState('settings', 'emails', {})
const { additionalEmails, primaryEmail, notificationEmail } = loadState('settings', 'emails', {})
const { displayNameChangeSupported } = loadState('settings', 'accountParameters', {})
export default {
@ -76,6 +81,7 @@ export default {
displayNameChangeSupported,
primaryEmail,
isValidForm: true,
notificationEmail,
}
},
@ -126,6 +132,10 @@ export default {
}
},
async onUpdateNotificationEmail(email) {
this.notificationEmail = email
},
async updatePrimaryEmail() {
try {
const responseData = await savePrimaryEmail(this.primaryEmailValue)

View file

@ -30,6 +30,7 @@ export const ACCOUNT_PROPERTY_ENUM = Object.freeze({
DISPLAYNAME: 'displayname',
PHONE: 'phone',
EMAIL: 'email',
NOTIFICATION_EMAIL: 'notify_email',
WEBSITE: 'website',
ADDRESS: 'address',
TWITTER: 'twitter',
@ -50,6 +51,13 @@ export const SCOPE_SUFFIX = 'Scope'
/** Default additional email scope */
export const DEFAULT_ADDITIONAL_EMAIL_SCOPE = SCOPE_ENUM.LOCAL
/** Enum of verification constants, according to IAccountManager */
export const VERIFICATION_ENUM = Object.freeze({
NOT_VERIFIED: 0,
VERIFICATION_IN_PROGRESS: 1,
VERIFIED: 2,
})
/**
* Enum of scope names to properties
*

View file

@ -70,6 +70,26 @@ export const saveAdditionalEmail = async(email) => {
return res.data
}
/**
* Save the notification email of the user
*
* @param {string} email the notification email
* @returns {object}
*/
export const saveNotificationEmail = async(email) => {
const userId = getCurrentUser().uid
const url = generateOcsUrl(`cloud/users/${userId}`, 2).slice(0, -1)
await confirmPassword()
const res = await axios.put(url, {
key: ACCOUNT_PROPERTY_ENUM.NOTIFICATION_EMAIL,
value: email,
})
return res.data
}
/**
* Remove an additional email of the user
*