diff --git a/pages/Settings.tsx b/pages/Settings.tsx index dcfe311..c6d84fb 100644 --- a/pages/Settings.tsx +++ b/pages/Settings.tsx @@ -6,12 +6,13 @@ import { Save, Building, Coins, Plus, Pencil, Trash2, X, CalendarCheck, AlertTri export const SettingsPage: React.FC = () => { const currentUser = CondoService.getCurrentUser(); - const isAdmin = currentUser?.role === 'admin'; + const isSuperAdmin = currentUser?.role === 'admin'; + const isPrivileged = currentUser?.role === 'admin' || currentUser?.role === 'poweruser'; // Tab configuration - type TabType = 'profile' | 'features' | 'general' | 'condos' | 'families' | 'users' | 'notices' | 'alerts' | 'smtp'; + type TabType = 'profile' | 'features' | 'general' | 'condos' | 'families' | 'users' | 'notices' | 'alerts'; - const [activeTab, setActiveTab] = useState(isAdmin ? 'general' : 'profile'); + const [activeTab, setActiveTab] = useState(isPrivileged ? 'general' : 'profile'); const [loading, setLoading] = useState(true); // Profile State @@ -87,6 +88,9 @@ export const SettingsPage: React.FC = () => { sendHour: 9, active: true }); + + // SMTP Modal State + const [showSmtpModal, setShowSmtpModal] = useState(false); // Notices (Bacheca) State const [notices, setNotices] = useState([]); @@ -116,7 +120,7 @@ export const SettingsPage: React.FC = () => { useEffect(() => { const fetchData = async () => { try { - if (isAdmin) { + if (isPrivileged) { // First fetch global/structural data const condoList = await CondoService.getCondos(); const activeC = await CondoService.getActiveCondo(); @@ -165,7 +169,7 @@ export const SettingsPage: React.FC = () => { } }; fetchData(); - }, [isAdmin]); + }, [isPrivileged]); // --- Profile Handlers --- const handleProfileSubmit = async (e: React.FormEvent) => { @@ -223,7 +227,7 @@ export const SettingsPage: React.FC = () => { try { await CondoService.updateSettings(globalSettings); setSuccessMsg('Configurazione SMTP salvata!'); - setTimeout(() => setSuccessMsg(''), 3000); + setTimeout(() => { setSuccessMsg(''); setShowSmtpModal(false); }, 2000); } catch (e) { console.error(e); } finally { @@ -492,9 +496,15 @@ export const SettingsPage: React.FC = () => { const tabs: {id: TabType, label: string, icon: React.ReactNode}[] = [ { id: 'profile', label: 'Profilo', icon: }, ]; - if (isAdmin) { + + // "Funzionalità" visible ONLY to SuperAdmin + if (isSuperAdmin) { + tabs.push({ id: 'features', label: 'Funzionalità', icon: }); + } + + // Other tabs visible to Privileged (Admin + PowerUser) + if (isPrivileged) { tabs.push( - { id: 'features', label: 'Funzionalità', icon: }, { id: 'general', label: 'Condominio', icon: } ); @@ -512,8 +522,7 @@ export const SettingsPage: React.FC = () => { } tabs.push( - { id: 'alerts', label: 'Avvisi Email', icon: }, - { id: 'smtp', label: 'SMTP', icon: } + { id: 'alerts', label: 'Avvisi Email', icon: } ); } @@ -560,8 +569,8 @@ export const SettingsPage: React.FC = () => { )} - {/* Features Tab */} - {isAdmin && activeTab === 'features' && globalSettings && ( + {/* Features Tab (SUPER ADMIN ONLY) */} + {isSuperAdmin && activeTab === 'features' && globalSettings && (

@@ -627,7 +636,7 @@ export const SettingsPage: React.FC = () => { )} {/* General Tab */} - {isAdmin && activeTab === 'general' && ( + {isPrivileged && activeTab === 'general' && (
{!activeCondo ? (
Nessun condominio selezionato.
@@ -688,7 +697,7 @@ export const SettingsPage: React.FC = () => { )} {/* Condos List Tab */} - {isAdmin && activeTab === 'condos' && ( + {isPrivileged && activeTab === 'condos' && (

I Tuoi Condomini

@@ -714,7 +723,7 @@ export const SettingsPage: React.FC = () => { )} {/* Families Tab */} - {isAdmin && activeTab === 'families' && ( + {isPrivileged && activeTab === 'families' && (
{!activeCondo ? (
@@ -764,7 +773,7 @@ export const SettingsPage: React.FC = () => { )} {/* Users Tab */} - {isAdmin && activeTab === 'users' && ( + {isPrivileged && activeTab === 'users' && (
+
+

Avvisi Automatici

Configura email automatiche per scadenze.

@@ -875,26 +896,6 @@ export const SettingsPage: React.FC = () => {
)} - {/* SMTP TAB */} - {isAdmin && activeTab === 'smtp' && ( -
-

Configurazione SMTP

-
-
-
setGlobalSettings(prev => prev ? {...prev, smtpConfig: {...(prev.smtpConfig || {}), host: e.target.value} as any} : null)} className="w-full border p-2.5 rounded-lg text-slate-700"/>
-
setGlobalSettings(prev => prev ? {...prev, smtpConfig: {...(prev.smtpConfig || {}), port: parseInt(e.target.value)} as any} : null)} className="w-full border p-2.5 rounded-lg text-slate-700"/>
-
-
-
setGlobalSettings(prev => prev ? {...prev, smtpConfig: {...(prev.smtpConfig || {}), user: e.target.value} as any} : null)} className="w-full border p-2.5 rounded-lg text-slate-700"/>
-
setGlobalSettings(prev => prev ? {...prev, smtpConfig: {...(prev.smtpConfig || {}), pass: e.target.value} as any} : null)} className="w-full border p-2.5 rounded-lg text-slate-700"/>
-
-
setGlobalSettings(prev => prev ? {...prev, smtpConfig: {...(prev.smtpConfig || {}), fromEmail: e.target.value} as any} : null)} className="w-full border p-2.5 rounded-lg text-slate-700"/>
-
setGlobalSettings(prev => prev ? {...prev, smtpConfig: {...(prev.smtpConfig || {}), secure: e.target.checked} as any} : null)} className="w-4 h-4"/>
-
{successMsg}
-
-
- )} - {/* ALERT MODAL (Existing) */} {showAlertModal && (
@@ -931,6 +932,59 @@ export const SettingsPage: React.FC = () => {
)} + + {/* SMTP CONFIG MODAL */} + {showSmtpModal && ( +
+
+
+

+ Configurazione SMTP +

+ +
+ +
+
+
+ + setGlobalSettings(prev => prev ? {...prev, smtpConfig: {...(prev.smtpConfig || {}), host: e.target.value} as any} : null)} className="w-full border p-2.5 rounded-lg text-slate-700" placeholder="smtp.gmail.com"/> +
+
+ + setGlobalSettings(prev => prev ? {...prev, smtpConfig: {...(prev.smtpConfig || {}), port: parseInt(e.target.value)} as any} : null)} className="w-full border p-2.5 rounded-lg text-slate-700" placeholder="587"/> +
+
+
+
+ + setGlobalSettings(prev => prev ? {...prev, smtpConfig: {...(prev.smtpConfig || {}), user: e.target.value} as any} : null)} className="w-full border p-2.5 rounded-lg text-slate-700"/> +
+
+ + setGlobalSettings(prev => prev ? {...prev, smtpConfig: {...(prev.smtpConfig || {}), pass: e.target.value} as any} : null)} className="w-full border p-2.5 rounded-lg text-slate-700"/> +
+
+
+ + setGlobalSettings(prev => prev ? {...prev, smtpConfig: {...(prev.smtpConfig || {}), fromEmail: e.target.value} as any} : null)} className="w-full border p-2.5 rounded-lg text-slate-700" placeholder="no-reply@condominio.it"/> +
+
+ setGlobalSettings(prev => prev ? {...prev, smtpConfig: {...(prev.smtpConfig || {}), secure: e.target.checked} as any} : null)} className="w-4 h-4 text-blue-600"/> + +
+ +
+ {successMsg} +
+ + +
+
+
+
+
+ )} {/* NOTICE MODAL (Existing) */} {showNoticeModal && ( @@ -1194,4 +1248,4 @@ export const SettingsPage: React.FC = () => { )}
); -}; \ No newline at end of file +}; diff --git a/server/server.js b/server/server.js index c19835b..39c0ecd 100644 --- a/server/server.js +++ b/server/server.js @@ -89,11 +89,12 @@ const authenticateToken = (req, res, next) => { }; const requireAdmin = (req, res, next) => { - if (req.user && req.user.role === 'admin') { + // Allow both 'admin' and 'poweruser' to access administrative routes + if (req.user && (req.user.role === 'admin' || req.user.role === 'poweruser')) { next(); } else { console.warn(`Access denied for user ${req.user?.email} with role ${req.user?.role}`); - res.status(403).json({ message: 'Access denied: Admins only' }); + res.status(403).json({ message: 'Access denied: Privileged users only' }); } };