Skip to content

Conversation

@NeilRashbrook
Copy link
Collaborator

Although #404 claimed that UX mockups exist it doesn't actually help because I don't know where they are, so I wrote some basic UI.

  • When viewing an EWS account, it shows you the Exchange Delegation feature where you can assign delegates for your email, contatcs and calendar. You also get to assign basic permissions to your delegates. I can't remember whether this allows them to send mail as or on behalf of you or not.
  • When viewing an EWS folder, it shows you the Exchange permissions for that folder. It uses the easy permissions model, so you get to choose from 9 permission levels rather than 288 possible permission combinations.
  • When viewing an EWS calendar, it shows you the Exchange permissions for that calendar, again using the easy permissions model, although now there are 11 permission levels to choose from.

Permissions are entered using the autocomplete UI. You can add users using their email address and click on a user to edit their permissions. In the case of delegated users, each user is edited and saved separately using a button inside the popup, while in the case of folder and calendar permissions, these are all saved in one go using a separate button.

So that the easy permission UI can be slightly more easily understood, some of their effective permissions are shown as a group of checkboxes, but these are display only.

@NeilRashbrook NeilRashbrook self-assigned this Sep 10, 2025
@NeilRashbrook NeilRashbrook force-pushed the neil/ews-delegate-permissions-poc branch 2 times, most recently from 307f3cc to 8703d72 Compare September 11, 2025 20:20
@NeilRashbrook
Copy link
Collaborator Author

Now with OWA support for folder and calendar permissions (OWA doesn't seem to support delegates).

@NeilRashbrook NeilRashbrook force-pushed the neil/ews-delegate-permissions-poc branch from 8703d72 to 17c0c7e Compare September 11, 2025 21:10
@NeilRashbrook
Copy link
Collaborator Author

Now with support for addressbook permissions. Unfortunately due to a typo on my part I've had to work around a bug in #780...

@benbucksch
Copy link
Collaborator

Although #404 claimed that UX mockups exist it doesn't actually help because I don't know where they are

Sorry:
https://parula.cloud.xwiki.com/xwiki/bin/view/Main/Settings/Calendar/Share/

But the UI doesn't have to be perfect, I can fix it later.

@benbucksch
Copy link
Collaborator

benbucksch commented Sep 12, 2025

  • Please priotize protocol (e.g. OWA, ActiveSync) implementations over settings UI changes (despite my review comments)

<ParticipantConfirmText {participant} />
</hbox>
<hbox slot="result-bottom-row" let:person>
<PersonAvailability {person} />
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please explain why you change this? It removes the Availability display.

Copy link
Collaborator Author

@NeilRashbrook NeilRashbrook Sep 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, this doesn't belong in this PR; I was just putting in {person.emailAddress} everywhere, since it really frustrates me to see 10 contacts named "Ben" without knowing which one is the email address I want.

As it happens, <PersonAvailability> is just a stub. Instead Availability is shown further down using <AvailabilityGrid>.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it really frustrates me to see 10 contacts named "Ben" without knowing which one is the email address I want.

Yes, I discussed that with @elenaux and we plan to add the email address to the results.

export let tabindex = null;
export let autofocus = false;
export let typedText: string = ""; /* in/out */
export let onAddPerson: (person: PersonUID) => void | Promise<void>;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please make these Autocomplete event handlers changes a separate PR with its own justification.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, I think this is a better solution for #826, so I'll switch that PR over to this method. (But it would need to land before I could rebase the changes away.)

<hbox slot="result-bottom-row" class="recipient-email-address font-small" let:person>
{person.emailAddress}
</hbox>
<CalendarExchangePermissions slot="person-popup-bottom" let:person {person}/>
Copy link
Collaborator

@benbucksch benbucksch Sep 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UI should be independent of Exchange. We need the same feature and UI in JMAP and even in IMAP accounts. IMAP supports this, and we have a specific request to implement that for Dovecot.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually this section is for account permissions i.e. who has access to your Exchange Calendar "account" or Addressbook "account". The folder permissions are inapp/frontend/Settings/Mail/Account/ but I'd have to look at how folder permissions work in IMAP and JMAP to see whether I could unify the UI at all.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMAP rights work differently to Exchange folder permissions, so I can't really unify them. (They work more like Exchange delegate permissions, in that for instance the "Remove" action is immediate.) I tried to find out how JMAP mailbox permissions work, but I failed.

@NeilRashbrook NeilRashbrook force-pushed the neil/ews-delegate-permissions-poc branch from 17c0c7e to e20494e Compare September 15, 2025 13:48
@NeilRashbrook NeilRashbrook force-pushed the neil/ews-delegate-permissions-poc branch 2 times, most recently from e2f25c4 to 03715b0 Compare September 15, 2025 21:12
@NeilRashbrook
Copy link
Collaborator Author

I have written some shaky IMAP code to handle folder permissions.

  • If the connection doesn't provide the ACL capability, getPermissions just returns undefined, and so the permissions block is never created in the UI.
  • ImapFlow doesn't directly support ACLs, so I have used conn.exec to fake it out. This probably works for SETACL and DELETEACL but GETACL need extra work because of the untagged response, and I have no idea whether I have specified the option correctly.
  • I should really UTF-7 escape the folder path like the ImapFlow library does (conn.exec assumes you've done this already). I don't know whether this can be done in the front end.
  • I have written the UI along the same lines as all of the other UI that I have added. Because it lives inside a <grid>, I don't even know whether it even can be split up into a separate file.
  • The code compiles but is otherwise completely untested.

@benbucksch
Copy link
Collaborator

benbucksch commented Sep 24, 2025

UI screenshots, as-is:

Calendar, in Settings | Calendar | | Main:

image

Addressbook:

image

@NeilRashbrook
Copy link
Collaborator Author

You asked how folder permissions compare between IMAP and Exchange.

IMAP

You either change the permissions as you go, or you calculate the changes between the original permissions and the permissions you want although this may require multiple commands. The following permissions are available:

  • a Set permissions on the folder
  • e Permanently delete messages from the folder
  • i Create or copy messages into the folder
  • k Create subfolders
  • l See the folder
  • r List messages
  • s Mark messages as (un)read
  • t Mark messages as IMAP deleted
  • w Flag messages
  • x Delete the folder

Exchange

You just set the final permissions for all permitted users in one go, overwriting all previous permission settings for that folder. (But I guess you could do that at every change the user makes instead of having a "Save Permissions" button.) I used the simple permissions model, but extended permissions are also available:

  • CanCreateItems: boolean
  • CanCreateSubfolders: boolean
  • DeleteItems: "None" | "Owned" | "All"
  • EditItems: "None" | "Owned" | "All"
  • IsFolderOwner: boolean (I don't know what this does, if anything)
  • IsFolderVisible: boolean
  • IsFolderContact: boolean (I'm not sure what this does either)
  • ReadItems: "None" | "FullDetails" (for Calendars, this can also be "TimeOnly" or "TimeAndSubjectAndLocation")

There is a table that maps the simple permissions to extended permissions:

Permission level Can create items Can create subfolders Is folder owner Is folder visible Is folder contact Edit items Delete items Read items
None False False False False False None None None
Owner True True True True True All All FullDetails
PublishingEditor True True False True False All All FullDetails
Editor True False False True False All All FullDetails
PublishingAuthor True True False True False Owned Owned FullDetails
Author True False False True False Owned Owned FullDetails
NoneditingAuthor True False False True False None Owned FullDetails
Reviewer False False False True False None None FullDetails
Contributor True False False True False None None None

(for Calendars, you can also have FreeBusyTimeOnly and FreeBusyTimeAndSubjectAndLocation which work like Reviewer but at a lower ReadItems permission)

@benbucksch benbucksch force-pushed the master branch 2 times, most recently from 7d2a658 to 3640c13 Compare November 6, 2025 15:51
benbucksch pushed a commit that referenced this pull request Dec 5, 2025
This fixes a bug "introduced" by eaf6fe3.

This PR now uses the approach from PR #885 of switching from an event to a
callback. The default callback simply adds or removes the person from the
collection, but Calendar can override the `onAddPerson()` to add a
`Participant` instead, thus preserving type safety.
Meanwhile PR #885 also wants to be able to override the `onRemovePerson()`
callback as removing delegates happens immediately (as opposed to removing
permissions which happens once editing of the permissions is complete).
@benbucksch
Copy link
Collaborator

@NeilRashbrook Now that #826 landed, this now conflicts. Could you please resolve them? Shouldn't be difficult for you: Just a few lines, and you know what you intended here.

@NeilRashbrook NeilRashbrook force-pushed the neil/ews-delegate-permissions-poc branch from 03715b0 to 3b751dd Compare December 8, 2025 17:06
@benbucksch benbucksch changed the title EWS: PoC of delegating permissions #404 IMAP, EWS, OWA: Allow others to access my mail folders #404 Dec 10, 2025
let permissions = new ArrayColl<IMAPPermission>();
await conn.exec('GETACL', [{ type: 'ATOM', value: this.path }], { untagged: { async ACL(untagged) { attributes = untagged.attributes; } } });
for (let i = 0; i < attributes.length; i += 2) {
let name = attributes[i].value;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sanitize() everything

a = "owner",
}

export class IMAPPermission extends PersonUID {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An IMAPPermission should have a person, not be a person.

Suggested change
export class IMAPPermission extends PersonUID {
export class IMAPPermission {
for: PersonUID;

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, we'll see what what your final UI does, but for now, I'm using PersonsAutocomplete to hold the permitted users, and that needs the permissions to derive from, not aggregate, PersonUID.

return permissions;
}

async setPermission(permission: IMAPPermission, right: keyof typeof IMAPACL) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

left: is missing, right?

FreeBusyTimeAndSubjectAndLocation = 1 << 6,
}

export class ExchangePermission extends PersonUID {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See IMAP: for: PersonUID. It is not a Person.

Suggested change
export class ExchangePermission extends PersonUID {
export class ExchangePermission {
for: PersonUID;

}
}

export enum ExchangePermissions {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to find a way to unify that with IMAPPermissions

}
}

export enum IMAPACL {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to find a way to unify that with ExchangePermissions

@NeilRashbrook NeilRashbrook force-pushed the neil/ews-delegate-permissions-poc branch from 3b751dd to 9739c37 Compare December 12, 2025 22:39
@NeilRashbrook NeilRashbrook force-pushed the neil/ews-delegate-permissions-poc branch from 9739c37 to cf0ee4c Compare December 12, 2025 22:40
@NeilRashbrook
Copy link
Collaborator Author

Now updated to present six of the Exchange folder permissions for individual editing.

}, { t$CalendarPermissionLevel: "Custom" }, this.exchangePermissions.toEWS());
}

toOWAFolderPermission() {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OWA code in EWS?

The general direction is a generic API for permissions that works across all protocols.

@NeilRashbrook
Copy link
Collaborator Author

I've just noticed that my UI has a bug - it will try to display delegates of delegated accounts, which doesn't work.

@NeilRashbrook
Copy link
Collaborator Author

More bugs in my UI:

  • Removing IMAP users doesn't update the folder UI
  • Too much copy and paste in my IMAP permissions UI - right hand checkboxes are bound to the wrong properties

@NeilRashbrook
Copy link
Collaborator Author

  • kolabnow: ACL, read works, write fails silently
  • fastmail: ACL, read works, write fails*
  • xmox: no ACL support

*UI doesn't report errors reporting setting IMAP permissions, also connection becomes unusable if an error occurs, but I don't know why

@benbucksch
Copy link
Collaborator

Thanks, Neil, for your work on this.

FWIW, the individual permissions should reflect the protocol level as closely as possible, after abstracting the different protocols. The options in the UI for the individual permissions were incomplete. It should have "create subfolder", "rename folder" etc.

Just please unify them between Exchange, IMAP and JMAP, as we discussed, so that the individual flags work across the protocols. We don't need to reflect admin nor owner access levels. And for Exchange, we accept that "edit flags" also means "can rewrite message content" and just document that in the JSDoc (and I'll add something to the UI later).

@NeilRashbrook NeilRashbrook force-pushed the neil/ews-delegate-permissions-poc branch from 3cbc792 to 9abd046 Compare December 22, 2025 21:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants