mirror of
https://github.com/nextcloud/server.git
synced 2026-06-08 00:02:54 -04:00
Merge pull request #28840 from nextcloud/enh/noid/notification-email-chooser
let user choose notification email in user settings
This commit is contained in:
commit
e26664ba42
23 changed files with 166 additions and 65 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
|
|
@ -231,7 +231,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(),
|
||||
|
|
@ -243,14 +243,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;
|
||||
|
|
|
|||
|
|
@ -65,11 +65,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>
|
||||
|
|
@ -83,8 +91,15 @@ import debounce from 'debounce'
|
|||
|
||||
import FederationControl from '../shared/FederationControl'
|
||||
|
||||
import { ACCOUNT_PROPERTY_READABLE_ENUM } from '../../../constants/AccountPropertyConstants'
|
||||
import { savePrimaryEmail, saveAdditionalEmail, saveAdditionalEmailScope, updateAdditionalEmail, removeAdditionalEmail } from '../../../service/PersonalInfo/EmailService'
|
||||
import { ACCOUNT_PROPERTY_READABLE_ENUM, VERIFICATION_ENUM } from '../../../constants/AccountPropertyConstants'
|
||||
import {
|
||||
removeAdditionalEmail,
|
||||
saveAdditionalEmail,
|
||||
saveAdditionalEmailScope,
|
||||
saveNotificationEmail,
|
||||
savePrimaryEmail,
|
||||
updateAdditionalEmail,
|
||||
} from '../../../service/PersonalInfo/EmailService'
|
||||
import { validateEmail } from '../../../utils/validate'
|
||||
|
||||
export default {
|
||||
|
|
@ -113,6 +128,14 @@ export default {
|
|||
type: String,
|
||||
required: true,
|
||||
},
|
||||
activeNotificationEmail: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
localVerificationState: {
|
||||
type: Number,
|
||||
default: VERIFICATION_ENUM.NOT_VERIFIED,
|
||||
},
|
||||
},
|
||||
|
||||
data() {
|
||||
|
|
@ -145,6 +168,19 @@ export default {
|
|||
return t('settings', 'Delete email')
|
||||
},
|
||||
|
||||
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
|
||||
},
|
||||
|
|
@ -162,6 +198,11 @@ export default {
|
|||
}
|
||||
return t('settings', 'Additional email address {index}', { index: this.index + 1 })
|
||||
},
|
||||
|
||||
isNotificationEmail() {
|
||||
return (this.email === this.activeNotificationEmail)
|
||||
|| (this.primary && this.activeNotificationEmail === '')
|
||||
},
|
||||
},
|
||||
|
||||
mounted() {
|
||||
|
|
@ -239,6 +280,22 @@ export default {
|
|||
}
|
||||
},
|
||||
|
||||
async setNotificationMail() {
|
||||
try {
|
||||
const newNotificationMailValue = (this.primary || this.isNotificationEmail) ? '' : this.initialEmail
|
||||
const responseData = await saveNotificationEmail(newNotificationMailValue)
|
||||
this.handleResponse({
|
||||
notificationEmail: newNotificationMailValue,
|
||||
status: responseData.ocs?.meta?.status,
|
||||
})
|
||||
} catch (e) {
|
||||
this.handleResponse({
|
||||
errorMessage: 'Unable to choose this email for notifications',
|
||||
error: e,
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
async updateAdditionalEmail(email) {
|
||||
try {
|
||||
const responseData = await updateAdditionalEmail(this.initialEmail, email)
|
||||
|
|
@ -276,10 +333,14 @@ export default {
|
|||
}
|
||||
},
|
||||
|
||||
handleResponse({ email, status, errorMessage, error }) {
|
||||
handleResponse({ email, notificationEmail, status, errorMessage, error }) {
|
||||
if (status === 'ok') {
|
||||
// Ensure that local state reflects server state
|
||||
this.initialEmail = email
|
||||
if (email) {
|
||||
this.initialEmail = email
|
||||
} else if (notificationEmail !== undefined) {
|
||||
this.$emit('update:notification-email', notificationEmail)
|
||||
}
|
||||
this.showCheckmarkIcon = true
|
||||
setTimeout(() => { this.showCheckmarkIcon = false }, 2000)
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -36,7 +36,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') }}
|
||||
|
|
@ -46,7 +48,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"
|
||||
@delete-additional-email="onDeleteAdditionalEmail(index)" />
|
||||
</section>
|
||||
</template>
|
||||
|
|
@ -62,7 +67,7 @@ import { ACCOUNT_PROPERTY_READABLE_ENUM, DEFAULT_ADDITIONAL_EMAIL_SCOPE } from '
|
|||
import { savePrimaryEmail, savePrimaryEmailScope, removeAdditionalEmail } from '../../../service/PersonalInfo/EmailService'
|
||||
import { validateEmail } from '../../../utils/validate'
|
||||
|
||||
const { emails: { additionalEmails, primaryEmail } } = loadState('settings', 'personalInfoParameters', {})
|
||||
const { emails: { additionalEmails, primaryEmail, notificationEmail } } = loadState('settings', 'personalInfoParameters', {})
|
||||
const { displayNameChangeSupported } = loadState('settings', 'accountParameters', {})
|
||||
|
||||
export default {
|
||||
|
|
@ -80,6 +85,7 @@ export default {
|
|||
displayNameChangeSupported,
|
||||
primaryEmail,
|
||||
savePrimaryEmailScope,
|
||||
notificationEmail,
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -126,6 +132,10 @@ export default {
|
|||
}
|
||||
},
|
||||
|
||||
async onUpdateNotificationEmail(email) {
|
||||
this.notificationEmail = email
|
||||
},
|
||||
|
||||
async updatePrimaryEmail() {
|
||||
try {
|
||||
const responseData = await savePrimaryEmail(this.primaryEmailValue)
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ export const ACCOUNT_PROPERTY_ENUM = Object.freeze({
|
|||
DISPLAYNAME: 'displayname',
|
||||
EMAIL: 'email',
|
||||
EMAIL_COLLECTION: 'additional_mail',
|
||||
NOTIFICATION_EMAIL: 'notify_email',
|
||||
PHONE: 'phone',
|
||||
TWITTER: 'twitter',
|
||||
WEBSITE: 'website',
|
||||
|
|
@ -118,6 +119,13 @@ export const SCOPE_PROPERTY_ENUM = Object.freeze({
|
|||
/** 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,
|
||||
})
|
||||
|
||||
/**
|
||||
* Email validation regex
|
||||
*
|
||||
|
|
|
|||
|
|
@ -69,6 +69,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}', { userId })
|
||||
|
||||
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
|
||||
*
|
||||
|
|
|
|||
Loading…
Reference in a new issue