* [MM-69863] Add external source picker (AD/LDAP, SAML) to New attribute
Adds a "Link to external source" control to the Definition card, letting
an admin link AD/LDAP and/or SAML to a new attribute (both may be linked
at once, matching Custom Profile Attributes' own dot-menu behavior).
Each linked source renders as its own removable/editable chip; the "add"
trigger's menu only offers not-yet-linked sources and disappears once
both are linked. Reuses the existing AttributeModal component and
ModalIdentifiers unmodified -- no new modal code.
No server-side changes: the access_control property group's existing
AccessControlAttributeValidationHook already validates, persists, and
strips attrs.ldap/attrs.saml for non-Text fields, and the Manage
Attributes list already renders a linked source's icon/label. The
client mirrors that server behavior by forcing the field's type to Text
whenever a link is set, and clearing any links if the type is manually
switched away from Text.
* Cap the Attribute column's width at 65ch on the Manage Attributes list
The table uses table-layout: auto, so this needs to live on the td/th
itself (mirroring the existing td.actions/th.actions rule) rather than
on the inner name span alone -- the column's rendered width is decided
by the auto-layout algorithm, not by max-width on a cell's content.
* Style the "Link to external source" trigger as a quaternary button
Adds the design's separator (margin-top/padding-top: 12px, border-top)
above the trigger, and swaps the ad-hoc link styling for
buttonClassNames({emphasis: 'quaternary'}) -- transparent/no-border at
rest, matching the Cancel button elsewhere on this page -- with the
hover tint overridden to --link-color-rgb per design, since the
quaternary default uses --button-bg-rgb instead.
* Fix trigger button sizing, extract a real Divider, reorder chips, and show the linked value
- The trigger was stretching full-width because display:flex (block-level)
fought .btn's own display:inline-flex, and its flex-column parent
defaults every child to align-self: stretch regardless of which display
wins -- fixed with align-self: flex-start and dropping the display
override entirely.
- The border-top/margin-top/padding-top separator was living on the
trigger button itself, so it only ever spanned the button's own
(now inline) width, not the full row. Extracted a small reusable
Divider component (webapp/channels/src/components/divider/) -- a
theme-CSS-var-based hairline <hr>, unlike Menu.Separator/MUI Divider
which needs a CompassDesignProvider ancestor -- and render it as its
own full-width element instead.
- Chips now render below the trigger, not above, and show the actual
linked value ("AD/LDAP: department"), not just the source name.
* [MM-69863] Add e2e coverage for dual-linking, chip edit/remove, and Type-switch clearing
Covers linking both AD/LDAP and SAML (menu exclusion, trigger disappearance,
chip label format), editing/removing a chip without a modal, the
type-mismatch warning, and the status announcement when Type is switched
away from Text.
* [MM-69863] Show "AD/LDAP, SAML" when an attribute is linked to both sources
getSourceKind previously collapsed a dual-linked field's Source cell to
just "AD/LDAP" since ldap was checked before saml. Add a dedicated
ldap_and_saml kind checked ahead of the individual branches, with its
own label and icon, and update the dual-linking e2e test's stale
assertion/comment to match.
* Fix prettier formatting in the dual-linking e2e spec
Pre-existing lines exceeded the project's 120-char printWidth;
prettier --write wraps the long test titles and toHaveText
assertions onto multiple lines with no behavior change.
* Gate AttributeExternalSource on saving/disabled, add chip action focus ring
A delegated (non-sysadmin) admin could still open the link modal and
mutate ldapAttr/samlAttr while every other control on the page was
disabled, and got stuck with an unclearable unsaved-changes prompt.
Thread disabled into the trigger and both chip action buttons.
Also add a :focus-visible style to the chip edit/remove buttons -- the
app's global *:focus{outline:none} reset left keyboard users with no
visible focus indicator on them.
* Clear stale focus-visible on the external source trigger
After linking a source, the modal restores focus to the trigger
programmatically, and because that restore comes from a keyboard-focused
input the trigger inherits :focus-visible. A later mouse click does not
clear it -- an already-focused element fires no new focus event -- so the
item MUI auto-focuses when the menu reopens inherits it in turn and gets
painted with the keyboard focus ring, on a menu opened with the mouse.
Blur the trigger on mousedown when it is already focused and matches
:focus-visible; the click's own default focus then re-evaluates the
interaction as a pointer one. Keyboard opens never fire mousedown, so
they keep their focus ring, and the first item still receives focus
either way so arrow-key navigation is unchanged.
Menu gets an opt-in onMouseDown passthrough on menuButton so the fix
stays scoped to this menu rather than changing every menu in the app.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Mattermost is an open core, self-hosted collaboration platform that offers chat, workflow automation, voice calling, screen sharing, and AI integration. This repo is the primary source for core development on the Mattermost platform; it's written in Go and React, runs as a single Linux binary, and relies on PostgreSQL. A new compiled version is released under an MIT license every month on the 16th.
Deploy Mattermost on-premises, or try it for free in the cloud.
Learn more about the following use cases with Mattermost:
Other useful resources:
- Download and Install Mattermost - Install, setup, and configure your own Mattermost instance.
- Product documentation - Learn how to run a Mattermost instance and take advantage of all the features.
- Developer documentation - Contribute code to Mattermost or build an integration via APIs, Webhooks, slash commands, Apps, and plugins.
Table of contents
- Install Mattermost
- Native mobile and desktop apps
- Get security bulletins
- Get involved
- Learn more
- License
- Get the latest news
- Contributing
Install Mattermost
- Download and Install Mattermost Self-Hosted - Deploy a Mattermost Self-hosted instance in minutes via Docker, Ubuntu, or tar.
- Get started in the cloud to try Mattermost today.
- Developer machine setup - Follow this guide if you want to write code for Mattermost.
Other install guides:
- Deploy Mattermost on Docker
- Mattermost Omnibus
- Install Mattermost from Tar
- Ubuntu 20.04 LTS
- Kubernetes
- Helm
- Debian Buster
- RHEL 8
- More server install guides
Native mobile and desktop apps
In addition to the web interface, you can also download Mattermost clients for Android, iOS, Windows PC, macOS, and Linux.
Get security bulletins
Receive notifications of critical security updates. The sophistication of online attackers is perpetually increasing. If you're deploying Mattermost it's highly recommended you subscribe to the Mattermost Security Bulletin mailing list for updates on critical security releases.
Get involved
- Contribute to Mattermost
- Find "Help Wanted" projects
- Join Developer Discussion on a Mattermost server for contributors
- Get Help With Mattermost
Learn more
- API options - webhooks, slash commands, drivers, and web service
- See who's using Mattermost
- Browse over 700 Mattermost integrations
License
See the LICENSE file for license rights and limitations.
Get the latest news
- X - Follow Mattermost on X, formerly Twitter.
- Blog - Get the latest updates from the Mattermost blog.
- Facebook - Follow Mattermost on Facebook.
- LinkedIn - Follow Mattermost on LinkedIn.
- Email - Subscribe to our newsletter (1 or 2 per month).
- Mattermost - Join the ~contributors channel on the Mattermost Community Server.
- IRC - Join the #matterbridge channel on Freenode (thanks to matterircd).
- YouTube - Subscribe to Mattermost.
Contributing
Please see CONTRIBUTING.md. Join the Mattermost Contributors server to join community discussions about contributions, development, and more.




