Merge pull request #338 from Coffey-Labs/feat/admin-trusted-device-only
Offer administration only on a device marked as your own
This commit is contained in:
@@ -39,8 +39,13 @@ export interface JmapSession {
|
||||
/** "oss" | "community" | "enterprise". Stalwart publishes no version. */
|
||||
edition?: string | null;
|
||||
};
|
||||
/** False when the operator has turned in-app administration off. */
|
||||
/**
|
||||
* False when this session may not administer: the operator turned it off,
|
||||
* or the session was signed in without "This is my own device".
|
||||
*/
|
||||
administration?: boolean;
|
||||
/** An administrator on a device not marked as their own; the menu says so. */
|
||||
administrationNeedsOwnDevice?: boolean;
|
||||
/**
|
||||
* The account's effective permissions on that server, as Stalwart reports
|
||||
* them. What the client offers is shaped by these; what is allowed is
|
||||
|
||||
@@ -113,6 +113,7 @@ export const catalog: Catalog = {
|
||||
"also {names}": "auch {names}",
|
||||
"The server did not say whether the domain was created.": "Der Server hat nicht mitgeteilt, ob die Domain angelegt wurde.",
|
||||
// ── Administration: accounts ───────────────────────────────────
|
||||
"Only on a device you've marked as your own. Sign in again with \u201cThis is my own device\u201d ticked.": "Nur auf einem Gerät, das Sie als Ihr eigenes markiert haben. Melden Sie sich erneut an und setzen Sie das Häkchen bei „Das ist mein eigenes Gerät“.",
|
||||
"Change your own password in {settings}.": "Ihr eigenes Passwort ändern Sie unter {settings}.",
|
||||
"Administration": "Verwaltung",
|
||||
"Directory": "Verzeichnis",
|
||||
|
||||
@@ -105,6 +105,7 @@ export const catalog: Catalog = {
|
||||
"also {names}": "también {names}",
|
||||
"The server did not say whether the domain was created.": "El servidor no indicó si el dominio se creó.",
|
||||
// ── Administration: accounts ───────────────────────────────────
|
||||
"Only on a device you've marked as your own. Sign in again with \u201cThis is my own device\u201d ticked.": "Solo en un dispositivo que haya marcado como suyo. Vuelva a iniciar sesión con «Este es mi propio dispositivo» marcado.",
|
||||
"Change your own password in {settings}.": "Cambie su propia contraseña en {settings}.",
|
||||
"Administration": "Administración",
|
||||
"Directory": "Directorio",
|
||||
|
||||
@@ -110,6 +110,7 @@ export const catalog: Catalog = {
|
||||
"also {names}": "aussi {names}",
|
||||
"The server did not say whether the domain was created.": "Le serveur n’a pas indiqué si le domaine a été créé.",
|
||||
// ── Administration: accounts ───────────────────────────────────
|
||||
"Only on a device you've marked as your own. Sign in again with \u201cThis is my own device\u201d ticked.": "Uniquement sur un appareil que vous avez indiqué comme le vôtre. Reconnectez-vous en cochant « Cet appareil est le mien ».",
|
||||
"Change your own password in {settings}.": "Modifiez votre propre mot de passe dans {settings}.",
|
||||
"Administration": "Administration",
|
||||
"Directory": "Annuaire",
|
||||
|
||||
@@ -104,6 +104,7 @@ export const catalog: Catalog = {
|
||||
"also {names}": "別名: {names}",
|
||||
"The server did not say whether the domain was created.": "ドメインが作成されたかどうか、サーバーから応答がありませんでした。",
|
||||
// ── Administration: accounts ───────────────────────────────────
|
||||
"Only on a device you've marked as your own. Sign in again with \u201cThis is my own device\u201d ticked.": "自分のデバイスとして指定した端末でのみ使えます。「これは自分のデバイスです」にチェックを入れて、もう一度サインインしてください。",
|
||||
"Change your own password in {settings}.": "ご自身のパスワードは{settings}で変更してください。",
|
||||
"Administration": "管理",
|
||||
"Directory": "ディレクトリ",
|
||||
|
||||
@@ -101,6 +101,7 @@ export const catalog: Catalog = {
|
||||
"also {names}": "ook {names}",
|
||||
"The server did not say whether the domain was created.": "De server heeft niet gemeld of het domein is aangemaakt.",
|
||||
// ── Administration: accounts ───────────────────────────────────
|
||||
"Only on a device you've marked as your own. Sign in again with \u201cThis is my own device\u201d ticked.": "Alleen op een apparaat dat u als uw eigen apparaat hebt aangemerkt. Log opnieuw in met ‘Dit is mijn eigen apparaat’ aangevinkt.",
|
||||
"Change your own password in {settings}.": "Wijzig uw eigen wachtwoord bij {settings}.",
|
||||
"Administration": "Beheer",
|
||||
"Directory": "Adreslijst",
|
||||
|
||||
@@ -108,6 +108,7 @@ export const catalog: Catalog = {
|
||||
"also {names}": "também {names}",
|
||||
"The server did not say whether the domain was created.": "O servidor não informou se o domínio foi criado.",
|
||||
// ── Administration: accounts ───────────────────────────────────
|
||||
"Only on a device you've marked as your own. Sign in again with \u201cThis is my own device\u201d ticked.": "Só em um dispositivo que você marcou como seu. Entre novamente com “Este dispositivo é meu” marcado.",
|
||||
"Change your own password in {settings}.": "Altere sua própria senha em {settings}.",
|
||||
"Administration": "Administração",
|
||||
"Directory": "Diretório",
|
||||
|
||||
@@ -107,6 +107,7 @@ export const catalog: Catalog = {
|
||||
"also {names}": "также {names}",
|
||||
"The server did not say whether the domain was created.": "Сервер не сообщил, создан ли домен.",
|
||||
// ── Administration: accounts ───────────────────────────────────
|
||||
"Only on a device you've marked as your own. Sign in again with \u201cThis is my own device\u201d ticked.": "Только на устройстве, отмеченном как ваше. Войдите снова, отметив «Это моё личное устройство».",
|
||||
"Change your own password in {settings}.": "Свой пароль можно изменить в разделе {settings}.",
|
||||
"Administration": "Администрирование",
|
||||
"Directory": "Каталог",
|
||||
|
||||
@@ -101,6 +101,7 @@ export const catalog: Catalog = {
|
||||
"also {names}": "також {names}",
|
||||
"The server did not say whether the domain was created.": "Сервер не повідомив, чи створено домен.",
|
||||
// ── Administration: accounts ───────────────────────────────────
|
||||
"Only on a device you've marked as your own. Sign in again with \u201cThis is my own device\u201d ticked.": "Лише на пристрої, позначеному як ваш. Увійдіть знову, позначивши «Це мій власний пристрій».",
|
||||
"Change your own password in {settings}.": "Власний пароль можна змінити в розділі {settings}.",
|
||||
"Administration": "Адміністрування",
|
||||
"Directory": "Каталог",
|
||||
|
||||
@@ -103,6 +103,7 @@ export const catalog: Catalog = {
|
||||
"also {names}": "别名:{names}",
|
||||
"The server did not say whether the domain was created.": "服务器没有说明域名是否已创建。",
|
||||
// ── Administration: accounts ───────────────────────────────────
|
||||
"Only on a device you've marked as your own. Sign in again with \u201cThis is my own device\u201d ticked.": "仅限在您标记为自己设备的设备上使用。请勾选「这是我自己的设备」后重新登录。",
|
||||
"Change your own password in {settings}.": "请在{settings}中更改您自己的密码。",
|
||||
"Administration": "管理",
|
||||
"Directory": "目录",
|
||||
|
||||
@@ -46,6 +46,7 @@ export function AppShell({ children }: { children: ReactNode }) {
|
||||
const appName = useSession((s) => s.session?.ihasmail?.appName) || DEFAULT_APP_NAME;
|
||||
const acctMenu = useMenu();
|
||||
const administers = hasAdministration(usePermissions());
|
||||
const needsOwnDevice = useSession((s) => Boolean(s.session?.ihasmail?.administrationNeedsOwnDevice));
|
||||
/*
|
||||
* "Go to folder" (#233), hosted here rather than in the mail view because
|
||||
* the `g` shortcuts are global: pressing it from the calendar should still
|
||||
@@ -163,6 +164,21 @@ export function AppShell({ children }: { children: ReactNode }) {
|
||||
{/* Only for an account whose Stalwart role manages other accounts.
|
||||
Nobody else is shown an entry that would open onto refusals. */}
|
||||
{administers && <MenuItem icon={<ShieldCheck size={16} />} label={t("Administration")} active={section === "admin"} onClick={() => navigate("/admin")} />}
|
||||
{/* An administrator who signed in without "This is my own device". The
|
||||
server withholds administration from that session, so the entry is
|
||||
shown dead with the reason, rather than gone without one. */}
|
||||
{!administers && needsOwnDevice && (
|
||||
<MenuItem
|
||||
icon={<ShieldCheck size={16} />}
|
||||
disabled
|
||||
label={
|
||||
<>
|
||||
<span style={{ display: "block" }}>{t("Administration")}</span>
|
||||
<span className="hint" style={{ display: "block", whiteSpace: "normal" }}>{t("Only on a device you've marked as your own. Sign in again with “This is my own device” ticked.")}</span>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
)}
|
||||
<MenuItem icon={<RefreshCw size={16} />} label={t("Refresh")} onClick={() => window.location.reload()} />
|
||||
<MenuItem icon={<LogOut size={16} />} label={t("Sign out")} onClick={() => void logout()} />
|
||||
</Popover>
|
||||
|
||||
Reference in New Issue
Block a user