feat: integrate policy checks for feature enablement in calendar, folder, and plugins settings

This commit is contained in:
Linus Rath
2026-03-25 11:06:35 +01:00
parent 05f6d61cea
commit f64306be5e
4 changed files with 57 additions and 17 deletions
+17 -1
View File
@@ -129,8 +129,24 @@ export async function POST(request: NextRequest) {
const filteredSettings = { ...settings };
for (const key of Object.keys(filteredSettings)) {
const restriction = policy.restrictions[key];
if (restriction?.locked) {
if (!restriction) continue;
if (restriction.locked) {
delete filteredSettings[key];
continue;
}
const value = filteredSettings[key];
if (restriction.allowedValues && restriction.allowedValues.length > 0) {
if (!restriction.allowedValues.includes(value)) {
delete filteredSettings[key];
}
}
if (typeof value === 'number') {
if (restriction.min !== undefined && value < restriction.min) {
delete filteredSettings[key];
}
if (restriction.max !== undefined && value > restriction.max) {
delete filteredSettings[key];
}
}
}
@@ -3,6 +3,7 @@
import { useTranslations } from 'next-intl';
import { useCalendarStore, CalendarViewMode } from '@/stores/calendar-store';
import { useSettingsStore } from '@/stores/settings-store';
import { usePolicyStore } from '@/stores/policy-store';
import { SettingsSection, SettingItem, Select, RadioGroup, ToggleSwitch } from './settings-section';
export function CalendarSettings() {
@@ -20,6 +21,7 @@ export function CalendarSettings() {
showTasksOnCalendar,
updateSetting,
} = useSettingsStore();
const { isFeatureEnabled } = usePolicyStore();
return (
<SettingsSection title={t('title')}>
@@ -78,6 +80,8 @@ export function CalendarSettings() {
/>
</SettingItem>
{isFeatureEnabled('calendarTasksEnabled') && (
<>
<SettingItem
label={t('enable_tasks')}
description={t('enable_tasks_desc')}
@@ -99,6 +103,8 @@ export function CalendarSettings() {
/>
</SettingItem>
)}
</>
)}
</SettingsSection>
);
+28 -16
View File
@@ -5,6 +5,7 @@ import { useTranslations } from 'next-intl';
import { useEmailStore } from '@/stores/email-store';
import { useAuthStore } from '@/stores/auth-store';
import { useSettingsStore } from '@/stores/settings-store';
import { usePolicyStore } from '@/stores/policy-store';
import { toast } from '@/stores/toast-store';
import { SettingsSection, SettingItem, Select } from './settings-section';
import {
@@ -100,6 +101,8 @@ export function FolderSettings() {
const { client } = useAuthStore();
const { mailboxes, createMailbox, renameMailbox, deleteMailbox, setMailboxRole } = useEmailStore();
const { folderIcons, setFolderIcon } = useSettingsStore();
const { isFeatureEnabled } = usePolicyStore();
const folderIconsAllowed = isFeatureEnabled('folderIconsEnabled');
const [isCreating, setIsCreating] = useState(false);
const [creatingParentId, setCreatingParentId] = useState<string | null>(null);
@@ -380,22 +383,31 @@ export function FolderSettings() {
<span className="w-4.5 flex-shrink-0" />
)}
<div className="relative flex-shrink-0">
<button
onClick={() => setIconPickerId(iconPickerId === mb.id ? null : mb.id)}
className={cn(
"p-1 rounded-md transition-colors",
iconPickerId === mb.id
? "bg-accent"
: "hover:bg-accent"
)}
title={t('change_icon')}
>
<Icon className={cn(
"w-4 h-4",
mb.role ? "text-primary" : "text-muted-foreground"
)} />
</button>
{iconPickerId === mb.id && (
{folderIconsAllowed ? (
<button
onClick={() => setIconPickerId(iconPickerId === mb.id ? null : mb.id)}
className={cn(
"p-1 rounded-md transition-colors",
iconPickerId === mb.id
? "bg-accent"
: "hover:bg-accent"
)}
title={t('change_icon')}
>
<Icon className={cn(
"w-4 h-4",
mb.role ? "text-primary" : "text-muted-foreground"
)} />
</button>
) : (
<span className="p-1">
<Icon className={cn(
"w-4 h-4",
mb.role ? "text-primary" : "text-muted-foreground"
)} />
</span>
)}
{folderIconsAllowed && iconPickerId === mb.id && (
<IconPicker
currentIcon={getIconName(mb)}
onSelect={(iconName) => {
+6
View File
@@ -2,6 +2,7 @@
import { useState, useRef } from 'react';
import { usePluginStore } from '@/stores/plugin-store';
import { usePolicyStore } from '@/stores/policy-store';
import { SettingsSection, SettingItem, ToggleSwitch } from './settings-section';
import { cn } from '@/lib/utils';
import { Upload, Trash2, AlertTriangle, Puzzle } from 'lucide-react';
@@ -19,10 +20,15 @@ const STATUS_COLORS: Record<PluginStatus, string> = {
export function PluginsSettings() {
const { plugins, installPlugin, uninstallPlugin, enablePlugin, disablePlugin, updatePluginSettings } = usePluginStore();
const { isFeatureEnabled } = usePolicyStore();
const [isUploading, setIsUploading] = useState(false);
const [expandedPlugin, setExpandedPlugin] = useState<string | null>(null);
const fileInputRef = useRef<HTMLInputElement>(null);
if (!isFeatureEnabled('pluginsEnabled')) {
return null;
}
const handleUpload = async (e: React.ChangeEvent<HTMLInputElement>) => {
const file = e.target.files?.[0];
if (!file) return;