feat: integrate policy checks for feature enablement in calendar, folder, and plugins settings
This commit is contained in:
@@ -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>
|
||||
);
|
||||
|
||||
@@ -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) => {
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user