A card above the tenant form: whether legacy mail protocols are on or off
for the organization, a one-click "Turn legacy protocols back on", and
"Turn off legacy protocols…", which opens -- before anything can change --
the impact panel with the tenant's own people (LP-15), the statement at
tenant scope and the typed confirmation (LP-16, LP-17). The statement reads
"everyone in {organization}" and names no ports and no firewall: a
tenant's switch closes nothing, other tenants share the ports (LP-13).
It reads and turns inbuxa:TenantProtocolPolicy, with the domain
permissions the server checks for it. It shows on the read-only tenant page
too: a tenant administrator reads its tenant without changing it (MT-12)
and may still turn the switch. Turning it back on while the server has
legacy protocols off is refused by the server, and the refusal is shown.
The banner (LP-18) falls back to the tenant's switch where the server's
can't be read -- inside a tenant -- and reads "off for your
organization".
The impact panel, statement and confirmation move to parts.tsx, shared by
Hardening and the tenant card; the statement takes its scope.
Checked by hand against a local server with a tenant, two of its users and
the admin signed in over IMAP: the tenant card's panel lists the tenant's
two users and not the admin; the statement reads "everyone in Example Co"
with no ports or firewall; turning it off makes the tenant's user get "NO
[ALERT] Your organization allows only INBUXA webmail and JMAP apps" over
IMAP; one click turns it back on; Hardening's panel lists all three. Not
checked by hand: the banner as a tenant administrator sees it.
79 lines
2.9 KiB
TypeScript
79 lines
2.9 KiB
TypeScript
/*
|
|
* SPDX-FileCopyrightText: 2026 Coffey Labs
|
|
*
|
|
* SPDX-License-Identifier: AGPL-3.0-only
|
|
*/
|
|
|
|
/**
|
|
* INBUXA: the banner while legacy mail protocols are off (LP-18), on the
|
|
* Security settings and the dashboard. It says nothing when the switch is on,
|
|
* when the reader may not see the policy, or when the server has no policy.
|
|
*/
|
|
|
|
import { useEffect, useState } from 'react';
|
|
import { Link } from 'react-router-dom';
|
|
import { useTranslation } from 'react-i18next';
|
|
import { ShieldCheck } from 'lucide-react';
|
|
import { useAccountStore } from '@/stores/accountStore';
|
|
import { fetchProtocolPolicy, fetchTenantPolicy } from './protocolPolicy';
|
|
|
|
export const LEGACY_PROTOCOLS_VIEW = 'CustomComponent/LegacyProtocols';
|
|
|
|
export function LegacyProtocolsBanner() {
|
|
const { t } = useTranslation();
|
|
const canGetServer = useAccountStore((s) => s.hasObjectPermission('sysNetworkListener', 'Get'));
|
|
const canGetTenant = useAccountStore((s) => s.hasObjectPermission('sysDomain', 'Get'));
|
|
const [off, setOff] = useState<null | 'server' | 'tenant'>(null);
|
|
|
|
useEffect(() => {
|
|
if (!canGetServer && !canGetTenant) return;
|
|
const controller = new AbortController();
|
|
const signal = controller.signal;
|
|
(async () => {
|
|
// The server's switch first. Inside a tenant it can't be read, and the
|
|
// tenant's own is the one to report (LP-18 at tenant scope).
|
|
try {
|
|
if (canGetServer) {
|
|
const policy = await fetchProtocolPolicy(signal);
|
|
if (!signal.aborted) setOff(policy.legacyProtocols === 'disabled' ? 'server' : null);
|
|
return;
|
|
}
|
|
} catch {
|
|
// Fall through to the tenant's.
|
|
}
|
|
try {
|
|
if (canGetTenant) {
|
|
const policy = await fetchTenantPolicy(null, signal);
|
|
if (!signal.aborted) setOff(policy.legacyProtocols === 'disabled' ? 'tenant' : null);
|
|
}
|
|
} catch {
|
|
// A banner is not worth an error: an older server simply has no switch.
|
|
}
|
|
})();
|
|
return () => controller.abort();
|
|
}, [canGetServer, canGetTenant]);
|
|
|
|
if (!off) return null;
|
|
|
|
return (
|
|
<div className="flex flex-wrap items-center gap-x-3 gap-y-1 rounded-xl border border-emerald-500/30 bg-emerald-500/5 px-4 py-3 text-sm">
|
|
<ShieldCheck className="h-4 w-4 shrink-0 text-emerald-600" />
|
|
<span>
|
|
{t('legacyProtocols.bannerLead', 'Legacy mail protocols are')}{' '}
|
|
<strong>{t('legacyProtocols.bannerOff', 'off')}</strong>{' '}
|
|
{off === 'server'
|
|
? t('legacyProtocols.bannerTail', 'on this server. Only INBUXA webmail and JMAP apps can sign in.')
|
|
: t(
|
|
'legacyProtocols.bannerTailTenant',
|
|
'for your organization. Only INBUXA webmail and JMAP apps can sign in.',
|
|
)}
|
|
</span>
|
|
{off === 'server' && (
|
|
<Link to={`/Settings/${LEGACY_PROTOCOLS_VIEW}`} className="font-medium text-primary hover:underline">
|
|
{t('legacyProtocols.review', 'Review')}
|
|
</Link>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|