-
Notifications
You must be signed in to change notification settings - Fork 288
External invitation calendar #11756
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
External invitation calendar #11756
Changes from 3 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -157,6 +157,22 @@ function findAttendee(vEvent, email) { | |
| return undefined | ||
| } | ||
|
|
||
| function findAttendeeByEmails(vEvent, emails) { | ||
| if (!vEvent || !Array.isArray(emails) || emails.length === 0) { | ||
| return undefined | ||
| } | ||
|
|
||
| const emailSet = new Set(emails.map(e => removeMailtoPrefix(e).toLowerCase())) | ||
| for (const attendee of [...vEvent.getPropertyIterator('ORGANIZER'), ...vEvent.getAttendeeIterator()]) { | ||
| const normalized = removeMailtoPrefix(attendee.email).toLowerCase() | ||
| if (emailSet.has(normalized)) { | ||
| return attendee | ||
| } | ||
| } | ||
|
|
||
| return undefined | ||
| } | ||
|
|
||
| export default { | ||
| name: 'Imip', | ||
| components: { | ||
|
|
@@ -173,6 +189,10 @@ export default { | |
| type: Object, | ||
| required: true, | ||
| }, | ||
| message: { | ||
| type: Object, | ||
| required: true, | ||
| }, | ||
| }, | ||
| data() { | ||
| return { | ||
|
|
@@ -197,6 +217,7 @@ export default { | |
| currentUserPrincipalEmail: 'getCurrentUserPrincipalEmail', | ||
| clonedWriteableCalendars: 'getClonedWriteableCalendars', | ||
| currentUserPrincipal: 'getCurrentUserPrincipal', | ||
| accounts: 'getAccounts', | ||
| }), | ||
|
|
||
| /** | ||
|
|
@@ -208,6 +229,14 @@ export default { | |
| return this.scheduling.method | ||
| }, | ||
|
|
||
| isFromDigikala() { | ||
| if (!this.message.from || !this.message.from[0]) { | ||
| return false | ||
| } | ||
| const fromEmail = this.message.from[0].email?.toLowerCase() || '' | ||
| return fromEmail.endsWith('@digikala.com') | ||
| }, | ||
|
|
||
| /** | ||
| * @return {boolean} | ||
| */ | ||
|
|
@@ -305,7 +334,7 @@ export default { | |
| * @return {boolean} | ||
| */ | ||
| userIsAttendee() { | ||
| return !!findAttendee(this.attachedVEvent, this.currentUserPrincipalEmail) | ||
| return !!findAttendeeByEmails(this.attachedVEvent, this.allUserEmails) | ||
| }, | ||
|
|
||
| /** | ||
|
|
@@ -314,10 +343,38 @@ export default { | |
| * @return {string|undefined} | ||
| */ | ||
| existingParticipationStatus() { | ||
| const attendee = findAttendee(this.existingVEvent, this.currentUserPrincipalEmail) | ||
| const attendee = findAttendeeByEmails(this.existingVEvent, this.allUserEmails) | ||
| return attendee?.participationStatus ?? undefined | ||
| }, | ||
|
|
||
| /** | ||
| * All user's email addresses (principal + all mail account addresses and aliases) | ||
| * | ||
| * @return {string[]} | ||
| */ | ||
| allUserEmails() { | ||
| const emails = new Set() | ||
| if (this.currentUserPrincipalEmail) { | ||
| emails.add(this.currentUserPrincipalEmail.toLowerCase()) | ||
| } | ||
| if (Array.isArray(this.accounts)) { | ||
| for (const account of this.accounts) { | ||
| if (account?.emailAddress) { | ||
| emails.add(String(account.emailAddress).toLowerCase()) | ||
| } | ||
| if (Array.isArray(account?.aliases)) { | ||
| for (const alias of account.aliases) { | ||
| const address = alias?.alias || alias?.emailAddress | ||
| if (address) { | ||
| emails.add(String(address).toLowerCase()) | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
| return Array.from(emails) | ||
| }, | ||
|
|
||
| /** | ||
| * The status message to show in case of REPLY messages. | ||
| * | ||
|
|
@@ -352,6 +409,14 @@ export default { | |
| }) | ||
| }, | ||
|
|
||
| existingEventFetched: { | ||
| immediate: false, | ||
| async handler(fetched) { | ||
| if (!fetched) return | ||
| await this.autoCreateTentativeIfNeeded() | ||
| }, | ||
| }, | ||
|
|
||
| /** | ||
| * List of calendar options for the target calendar picker. | ||
| * | ||
|
|
@@ -410,6 +475,14 @@ export default { | |
| }, | ||
| }, | ||
| }, | ||
|
|
||
| async mounted() { | ||
| // If data already fetched on mount, attempt auto-create once | ||
| if (this.existingEventFetched) { | ||
| await this.autoCreateTentativeIfNeeded() | ||
| } | ||
| }, | ||
|
|
||
| methods: { | ||
| async accept() { | ||
| await this.saveEventWithParticipationStatus(ACCEPTED) | ||
|
|
@@ -420,6 +493,22 @@ export default { | |
| async decline() { | ||
| await this.saveEventWithParticipationStatus(DECLINED) | ||
| }, | ||
| async autoCreateTentativeIfNeeded() { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd say that approach isn’t ideal from a conceptual standpoint. Creating the tentative event during the mounting of the frontend component requires the user to open the email. It should be done in the imip background job and only for contacts listed as internal addresses or trusted sender. |
||
| try { | ||
| if ( | ||
| this.isRequest | ||
| && !this.wasProcessed | ||
| && this.userIsAttendee | ||
| && this.eventIsInFuture | ||
| && this.existingEventFetched | ||
| && !this.isExistingEvent | ||
| ) { | ||
| await this.saveEventWithParticipationStatus(TENTATIVE) | ||
| } | ||
| } catch (e) { | ||
| // ignore auto-create failures | ||
|
||
| } | ||
| }, | ||
| async saveEventWithParticipationStatus(status) { | ||
| let vCalendar | ||
| if (this.isExistingEvent) { | ||
|
|
@@ -428,7 +517,7 @@ export default { | |
| vCalendar = this.attachedVCalendar | ||
| } | ||
| const vEvent = vCalendar.getFirstComponent('VEVENT') | ||
| const attendee = findAttendee(vEvent, this.currentUserPrincipalEmail) | ||
| const attendee = findAttendeeByEmails(vEvent, this.allUserEmails) | ||
| if (!attendee) { | ||
| return | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This has to be generalized