added super admin restrictions for site settings
This commit is contained in:
parent
c35adf0498
commit
b02bbb2086
11 changed files with 130 additions and 57 deletions
|
|
@ -15,8 +15,24 @@ module.exports = (pool, query) => {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Verify API key and check admin status
|
// Verify API key and check admin status
|
||||||
|
// const result = await query(
|
||||||
|
// 'SELECT id, email, first_name, last_name, is_admin FROM users WHERE api_key = $1',
|
||||||
|
// [apiKey]
|
||||||
|
// );
|
||||||
const result = await query(
|
const result = await query(
|
||||||
'SELECT id, email, first_name, last_name, is_admin FROM users WHERE api_key = $1',
|
`SELECT
|
||||||
|
u.id,
|
||||||
|
u.email,
|
||||||
|
u.first_name,
|
||||||
|
u.last_name,
|
||||||
|
u.is_admin,
|
||||||
|
CASE WHEN s.user_id IS NOT NULL THEN TRUE ELSE FALSE END AS is_super_admin
|
||||||
|
FROM
|
||||||
|
users u
|
||||||
|
LEFT JOIN
|
||||||
|
superadmins s ON u.id = s.user_id
|
||||||
|
WHERE
|
||||||
|
u.api_key = $1`,
|
||||||
[apiKey]
|
[apiKey]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,10 @@ module.exports = (pool, query) => {
|
||||||
'UPDATE users SET is_admin = TRUE WHERE email = $1',
|
'UPDATE users SET is_admin = TRUE WHERE email = $1',
|
||||||
[email]
|
[email]
|
||||||
);
|
);
|
||||||
|
await query(
|
||||||
|
'INSERT INTO superadmins (user_id) values ($1) RETURNING id, created_at',
|
||||||
|
[result.rows[0].id]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
await emailService.sendWelcomeEmail({
|
await emailService.sendWelcomeEmail({
|
||||||
|
|
@ -205,15 +209,33 @@ module.exports = (pool, query) => {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Get user information including admin status
|
// Get user information including admin status
|
||||||
|
// const userInfo = await query(
|
||||||
|
// 'SELECT id, email, first_name, last_name, is_admin FROM users WHERE id = $1',
|
||||||
|
// [userId]
|
||||||
|
// );
|
||||||
const userInfo = await query(
|
const userInfo = await query(
|
||||||
'SELECT id, email, first_name, last_name, is_admin FROM users WHERE id = $1',
|
`SELECT
|
||||||
|
u.id,
|
||||||
|
u.email,
|
||||||
|
u.first_name,
|
||||||
|
u.last_name,
|
||||||
|
u.is_admin,
|
||||||
|
CASE WHEN s.user_id IS NOT NULL THEN TRUE ELSE FALSE END AS is_super_admin
|
||||||
|
FROM
|
||||||
|
users u
|
||||||
|
LEFT JOIN
|
||||||
|
superadmins s ON u.id = s.user_id
|
||||||
|
WHERE
|
||||||
|
u.id = $1`,
|
||||||
[userId]
|
[userId]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
res.json({
|
res.json({
|
||||||
message: 'Login successful',
|
message: 'Login successful',
|
||||||
userId: userId,
|
userId: userId,
|
||||||
isAdmin: userInfo.rows[0].is_admin,
|
isAdmin: userInfo.rows[0].is_admin,
|
||||||
|
isSuperAdmin: userInfo.rows[0].is_super_admin,
|
||||||
firstName: userInfo.rows[0].first_name,
|
firstName: userInfo.rows[0].first_name,
|
||||||
lastName: userInfo.rows[0].last_name,
|
lastName: userInfo.rows[0].last_name,
|
||||||
email: userInfo.rows[0].email,
|
email: userInfo.rows[0].email,
|
||||||
|
|
|
||||||
|
|
@ -113,7 +113,14 @@ module.exports = (pool, query, authMiddleware) => {
|
||||||
message: 'Value and category are required'
|
message: 'Value and category are required'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
const setting = await SystemSettings.getSetting(pool, query, key)
|
||||||
|
|
||||||
|
if(setting?.super_req && !req.user.is_super_admin){
|
||||||
|
return res.status(400).json({
|
||||||
|
error: true,
|
||||||
|
message: `Super Admin access required to modify ${key}`
|
||||||
|
});
|
||||||
|
}
|
||||||
const updatedSetting = await SystemSettings.updateSetting(pool, query, key, value, category);
|
const updatedSetting = await SystemSettings.updateSetting(pool, query, key, value, category);
|
||||||
|
|
||||||
// Update config in memory
|
// Update config in memory
|
||||||
|
|
@ -137,7 +144,7 @@ module.exports = (pool, query, authMiddleware) => {
|
||||||
router.post('/batch', async (req, res, next) => {
|
router.post('/batch', async (req, res, next) => {
|
||||||
try {
|
try {
|
||||||
const { settings } = req.body;
|
const { settings } = req.body;
|
||||||
|
console.log(req.user)
|
||||||
|
|
||||||
if (!req.user.is_admin) {
|
if (!req.user.is_admin) {
|
||||||
return res.status(403).json({
|
return res.status(403).json({
|
||||||
|
|
@ -152,7 +159,7 @@ module.exports = (pool, query, authMiddleware) => {
|
||||||
message: 'Settings array is required'
|
message: 'Settings array is required'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
const categorySettings = await SystemSettings.getSettingsByCategory(pool, query, settings[0]?.category)
|
||||||
// Validate all settings have required fields
|
// Validate all settings have required fields
|
||||||
for (const setting of settings) {
|
for (const setting of settings) {
|
||||||
if (!setting.key || setting.value === undefined || !setting.category) {
|
if (!setting.key || setting.value === undefined || !setting.category) {
|
||||||
|
|
@ -161,6 +168,12 @@ module.exports = (pool, query, authMiddleware) => {
|
||||||
message: 'Each setting must have key, value, and category fields'
|
message: 'Each setting must have key, value, and category fields'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if(categorySettings.find(item => item.key === setting.key)?.super_req && !req.user.is_super_admin){
|
||||||
|
return res.status(400).json({
|
||||||
|
error: true,
|
||||||
|
message: `Super Admin access required to modify ${setting.key}`
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const updatedSettings = await SystemSettings.updateSettings(pool, query, settings);
|
const updatedSettings = await SystemSettings.updateSettings(pool, query, settings);
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ CREATE TABLE IF NOT EXISTS system_settings (
|
||||||
key VARCHAR(255) NOT NULL UNIQUE,
|
key VARCHAR(255) NOT NULL UNIQUE,
|
||||||
value TEXT,
|
value TEXT,
|
||||||
category VARCHAR(100) NOT NULL,
|
category VARCHAR(100) NOT NULL,
|
||||||
|
super_req BOOLEAN DEFAULT FALSE,
|
||||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
||||||
);
|
);
|
||||||
|
|
@ -19,51 +20,50 @@ CREATE INDEX IF NOT EXISTS idx_system_settings_category ON system_settings(categ
|
||||||
INSERT INTO system_settings (key, value, category)
|
INSERT INTO system_settings (key, value, category)
|
||||||
VALUES
|
VALUES
|
||||||
-- SMTP Settings
|
-- SMTP Settings
|
||||||
('smtp_host', NULL, 'email'),
|
('smtp_host', NULL, 'email', TRUE),
|
||||||
('smtp_port', NULL, 'email'),
|
('smtp_port', NULL, 'email', TRUE),
|
||||||
('smtp_user', NULL, 'email'),
|
('smtp_user', NULL, 'email', TRUE),
|
||||||
('smtp_password', NULL, 'email'),
|
('smtp_password', NULL, 'email', TRUE),
|
||||||
('smtp_from_email', NULL, 'email'),
|
('smtp_from_email', NULL, 'email', TRUE),
|
||||||
('smtp_from_name', NULL, 'email'),
|
('smtp_from_name', NULL, 'email', FALSE),
|
||||||
|
|
||||||
-- Site Settings
|
-- Site Settings
|
||||||
-- ('site_name', NULL, 'site'),
|
('site_domain', NULL, 'site', TRUE),
|
||||||
('site_domain', NULL, 'site'),
|
('site_api_domain', NULL, 'site', TRUE),
|
||||||
('site_api_domain', NULL, 'site'),
|
('site_protocol', NULL, 'site', TRUE),
|
||||||
('site_protocol', NULL, 'site'),
|
('site_environment', NULL, 'site', TRUE),
|
||||||
('site_environment', NULL, 'site'),
|
('site_deployment', NULL, 'site', TRUE),
|
||||||
('site_deployment', NULL, 'site'),
|
('site_redis_host', NULL, 'site', TRUE),
|
||||||
('site_redis_host', NULL, 'site'),
|
('site_redis_tls', NULL, 'site', TRUE),
|
||||||
('site_redis_tls', NULL, 'site'),
|
('site_aws_region', NULL, 'site', TRUE),
|
||||||
('site_aws_region', NULL, 'site'),
|
('site_aws_s3_bucket', NULL, 'site', TRUE),
|
||||||
('site_aws_s3_bucket', NULL, 'site'),
|
('site_cdn_domain', NULL, 'site', TRUE),
|
||||||
('site_cdn_domain', NULL, 'site'),
|
('site_aws_queue_url', NULL, 'site', TRUE),
|
||||||
('site_aws_queue_url', NULL, 'site'),
|
('site_read_host', NULL, 'site', TRUE),
|
||||||
('site_read_host', NULL, 'site'),
|
('site_db_max_connections', NULL, 'site', TRUE),
|
||||||
('site_db_max_connections', NULL, 'site'),
|
('site_session_secret', NULL, 'site', TRUE),
|
||||||
('site_session_secret', NULL, 'site'),
|
('site_redis_port', NULL, 'site', TRUE),
|
||||||
('site_redis_port', NULL, 'site'),
|
('site_redis_password', NULL, 'site', TRUE),
|
||||||
('site_redis_password', NULL, 'site'),
|
|
||||||
|
|
||||||
-- Payment Settings
|
-- Payment Settings
|
||||||
('currency', 'CAD', 'payment'),
|
('currency', 'CAD', 'payment', FALSE),
|
||||||
('tax_rate', '0', 'payment'),
|
('tax_rate', '0', 'payment', FALSE),
|
||||||
|
|
||||||
-- Shipping Settings
|
-- Shipping Settings
|
||||||
('shipping_flat_rate', '10.00', 'shipping'),
|
('shipping_flat_rate', '10.00', 'shipping', FALSE),
|
||||||
('shipping_free_threshold', '50.00', 'shipping'),
|
('shipping_free_threshold', '50.00', 'shipping', FALSE),
|
||||||
('shipping_enabled', 'true', 'shipping'),
|
('shipping_enabled', 'true', 'shipping', FALSE),
|
||||||
('easypost_api_key', NULL, 'shipping'),
|
('easypost_api_key', NULL, 'shipping', TRUE),
|
||||||
('easypost_enabled', 'false', 'shipping'),
|
('easypost_enabled', 'false', 'shipping', FALSE),
|
||||||
('shipping_origin_street', '123 Main St', 'shipping'),
|
('shipping_origin_street', '123 Main St', 'shipping', FALSE),
|
||||||
('shipping_origin_city', 'Vancouver', 'shipping'),
|
('shipping_origin_city', 'Vancouver', 'shipping', FALSE),
|
||||||
('shipping_origin_state', 'BC', 'shipping'),
|
('shipping_origin_state', 'BC', 'shipping', FALSE),
|
||||||
('shipping_origin_zip', 'V6K 1V6', 'shipping'),
|
('shipping_origin_zip', 'V6K 1V6', 'shipping', FALSE),
|
||||||
('shipping_origin_country', 'CA', 'shipping'),
|
('shipping_origin_country', 'CA', 'shipping', FALSE),
|
||||||
('shipping_default_package_length', '15', 'shipping'),
|
('shipping_default_package_length', '15', 'shipping', FALSE),
|
||||||
('shipping_default_package_width', '12', 'shipping'),
|
('shipping_default_package_width', '12', 'shipping', FALSE),
|
||||||
('shipping_default_package_height', '10', 'shipping'),
|
('shipping_default_package_height', '10', 'shipping', FALSE),
|
||||||
('shipping_default_package_unit', 'cm', 'shipping'),
|
('shipping_default_package_unit', 'cm', 'shipping', FALSE),
|
||||||
('shipping_default_weight_unit', 'g', 'shipping'),
|
('shipping_default_package_weight_unit', 'g', 'shipping', FALSE),
|
||||||
('shipping_carriers_allowed', 'USPS,UPS,FedEx,DHL,Canada Post,Purolator', 'shipping')
|
('shipping_carriers_allowed', 'USPS,UPS,FedEx,DHL,Canada Post,Purolator', 'shipping', FALSE)
|
||||||
ON CONFLICT (key) DO NOTHING;
|
ON CONFLICT (key) DO NOTHING;
|
||||||
9
db/init/23-suparadmin.sql
Normal file
9
db/init/23-suparadmin.sql
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
-- Create superadmins table that links to the users table
|
||||||
|
CREATE TABLE superadmins (
|
||||||
|
user_id UUID PRIMARY KEY REFERENCES users(id) ON DELETE CASCADE,
|
||||||
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||||
|
description TEXT
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Create index for faster lookups
|
||||||
|
CREATE INDEX idx_superadmins_user_id ON superadmins(user_id);
|
||||||
|
|
@ -11,8 +11,8 @@ import {
|
||||||
Chip
|
Chip
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||||
import couponService from '../services/couponService';
|
import couponService from '@services/couponService';
|
||||||
import { useAuth } from '../hooks/reduxHooks';
|
import { useAuth } from '@hooks/reduxHooks';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Component for inputting and applying coupon codes to the cart
|
* Component for inputting and applying coupon codes to the cart
|
||||||
|
|
|
||||||
|
|
@ -28,17 +28,21 @@ export const authSlice = createSlice({
|
||||||
email: action.payload.email,
|
email: action.payload.email,
|
||||||
firstName: action.payload.firstName,
|
firstName: action.payload.firstName,
|
||||||
lastName: action.payload.lastName,
|
lastName: action.payload.lastName,
|
||||||
isAdmin: action.payload.isAdmin
|
isAdmin: action.payload.isAdmin,
|
||||||
|
isSuperAdmin: action.payload.isSuperAdmin
|
||||||
};
|
};
|
||||||
state.apiKey = action.payload.apiKey;
|
state.apiKey = action.payload.apiKey;
|
||||||
state.isAdmin = action.payload.isAdmin;
|
state.isAdmin = action.payload.isAdmin;
|
||||||
|
state.isSuperAdmin = action.payload.isSuperAdmin;
|
||||||
localStorage.setItem('apiKey', action.payload.apiKey);
|
localStorage.setItem('apiKey', action.payload.apiKey);
|
||||||
localStorage.setItem('isAdmin', action.payload.isAdmin);
|
localStorage.setItem('isAdmin', action.payload.isAdmin);
|
||||||
|
localStorage.setItem('isSuperAdmin', action.payload.isSuperAdmin);
|
||||||
localStorage.setItem('user', JSON.stringify(action.payload.user));
|
localStorage.setItem('user', JSON.stringify(action.payload.user));
|
||||||
localStorage.setItem('userData', JSON.stringify({
|
localStorage.setItem('userData', JSON.stringify({
|
||||||
id: action.payload.user,
|
id: action.payload.user,
|
||||||
apiKey: action.payload.apiKey,
|
apiKey: action.payload.apiKey,
|
||||||
isAdmin: action.payload.isAdmin
|
isAdmin: action.payload.isAdmin,
|
||||||
|
isSuperAdmin: action.payload.isSuperAdmin
|
||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
loginFailed: (state, action) => {
|
loginFailed: (state, action) => {
|
||||||
|
|
@ -51,8 +55,10 @@ export const authSlice = createSlice({
|
||||||
state.userData = null;
|
state.userData = null;
|
||||||
state.apiKey = null;
|
state.apiKey = null;
|
||||||
state.isAdmin = false;
|
state.isAdmin = false;
|
||||||
|
state.isSuperAdmin = false;
|
||||||
localStorage.removeItem('apiKey');
|
localStorage.removeItem('apiKey');
|
||||||
localStorage.removeItem('isAdmin');
|
localStorage.removeItem('isAdmin');
|
||||||
|
localStorage.removeItem('isSuperAdmin');
|
||||||
localStorage.removeItem('user');
|
localStorage.removeItem('user');
|
||||||
localStorage.removeItem('userData');
|
localStorage.removeItem('userData');
|
||||||
},
|
},
|
||||||
|
|
@ -67,6 +73,7 @@ export const { loginStart, loginSuccess, loginFailed, logout, clearError } = aut
|
||||||
// Selectors
|
// Selectors
|
||||||
export const selectIsAuthenticated = (state) => state.auth.isAuthenticated;
|
export const selectIsAuthenticated = (state) => state.auth.isAuthenticated;
|
||||||
export const selectIsAdmin = (state) => state.auth.isAdmin;
|
export const selectIsAdmin = (state) => state.auth.isAdmin;
|
||||||
|
export const selectIsSuperAdmin = (state) => state.auth.isSuperAdmin;
|
||||||
export const selectCurrentUser = (state) => state.auth.user;
|
export const selectCurrentUser = (state) => state.auth.user;
|
||||||
export const selectApiKey = (state) => state.auth.apiKey;
|
export const selectApiKey = (state) => state.auth.apiKey;
|
||||||
export const selectAuthLoading = (state) => state.auth.loading;
|
export const selectAuthLoading = (state) => state.auth.loading;
|
||||||
|
|
|
||||||
|
|
@ -144,7 +144,7 @@ export const useVerifyCode = () => {
|
||||||
return useMutation({
|
return useMutation({
|
||||||
mutationFn: (verifyData) => authService.verifyCode(verifyData),
|
mutationFn: (verifyData) => authService.verifyCode(verifyData),
|
||||||
onSuccess: (data) => {
|
onSuccess: (data) => {
|
||||||
login(data.userId, data.apiKey, data.isAdmin, data.email, data?.firstName, data?.lastName);
|
login(data.userId, data.apiKey, data.isAdmin, data.isSuperAdmin, data.email, data?.firstName, data?.lastName);
|
||||||
notification.showNotification('Login successful', 'success');
|
notification.showNotification('Login successful', 'success');
|
||||||
Clarity.identify(data.userId, data.apiKey);
|
Clarity.identify(data.userId, data.apiKey);
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,7 @@ export const useDarkMode = () => {
|
||||||
export const useAuth = () => {
|
export const useAuth = () => {
|
||||||
const isAuthenticated = useAppSelector((state) => state.auth.isAuthenticated);
|
const isAuthenticated = useAppSelector((state) => state.auth.isAuthenticated);
|
||||||
const isAdmin = useAppSelector((state) => state.auth.isAdmin);
|
const isAdmin = useAppSelector((state) => state.auth.isAdmin);
|
||||||
|
const isSuperAdmin = useAppSelector((state) => state.auth.isSuperAdmin);
|
||||||
const user = useAppSelector((state) => state.auth.user);
|
const user = useAppSelector((state) => state.auth.user);
|
||||||
const userData = useAppSelector((state) => state.auth.userData);
|
const userData = useAppSelector((state) => state.auth.userData);
|
||||||
const apiKey = useAppSelector((state) => state.auth.apiKey);
|
const apiKey = useAppSelector((state) => state.auth.apiKey);
|
||||||
|
|
@ -67,15 +68,16 @@ export const useAuth = () => {
|
||||||
return {
|
return {
|
||||||
isAuthenticated,
|
isAuthenticated,
|
||||||
isAdmin,
|
isAdmin,
|
||||||
|
isSuperAdmin,
|
||||||
user,
|
user,
|
||||||
userData,
|
userData,
|
||||||
apiKey,
|
apiKey,
|
||||||
loading,
|
loading,
|
||||||
error,
|
error,
|
||||||
login: (user, apiKey, isAdmin, email, firstName = "", lastName = "") =>
|
login: (user, apiKey, isAdmin, isSuperAdmin, email, firstName = "", lastName = "") =>
|
||||||
dispatch({
|
dispatch({
|
||||||
type: 'auth/loginSuccess',
|
type: 'auth/loginSuccess',
|
||||||
payload: { user, apiKey, isAdmin, email, firstName, lastName}}),
|
payload: { user, apiKey, isAdmin, isSuperAdmin, email, firstName, lastName}}),
|
||||||
logout: () => dispatch({ type: 'auth/logout' }),
|
logout: () => dispatch({ type: 'auth/logout' }),
|
||||||
clearError: () => dispatch({ type: 'auth/clearError' }),
|
clearError: () => dispatch({ type: 'auth/clearError' }),
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,9 @@ import {
|
||||||
Add as AddIcon,
|
Add as AddIcon,
|
||||||
Delete as DeleteIcon
|
Delete as DeleteIcon
|
||||||
} from '@mui/icons-material';
|
} from '@mui/icons-material';
|
||||||
import { useAdminSettings, useUpdateSettings, useUpdateSetting, useDeleteSetting } from '../../hooks/settingsAdminHooks';
|
import { useAdminSettings, useUpdateSettings, useUpdateSetting, useDeleteSetting } from '@hooks/settingsAdminHooks';
|
||||||
|
import { useAuth } from '@hooks/reduxHooks';
|
||||||
|
|
||||||
|
|
||||||
function TabPanel({ children, value, index, ...other }) {
|
function TabPanel({ children, value, index, ...other }) {
|
||||||
return (
|
return (
|
||||||
|
|
@ -69,9 +71,9 @@ const AdminSettingsPage = () => {
|
||||||
const [settingToDelete, setSettingToDelete] = useState(null);
|
const [settingToDelete, setSettingToDelete] = useState(null);
|
||||||
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
|
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
|
||||||
|
|
||||||
|
const { isSuperAdmin } = useAuth();
|
||||||
// Fetch settings
|
// Fetch settings
|
||||||
const { data: settingsData, isLoading, error, refetch } = useAdminSettings();
|
const { data: settingsData, isLoading, error, refetch } = useAdminSettings();
|
||||||
|
|
||||||
// Update settings mutation
|
// Update settings mutation
|
||||||
const updateSettings = useUpdateSettings();
|
const updateSettings = useUpdateSettings();
|
||||||
const updateSetting = useUpdateSetting();
|
const updateSetting = useUpdateSetting();
|
||||||
|
|
@ -372,11 +374,11 @@ const AdminSettingsPage = () => {
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
{setting.key.includes('password') || setting.key.includes('secret') || setting.key.includes('key') ? (
|
{setting.key.includes('password') || setting.key.includes('secret') || setting.key.includes('key') ? (
|
||||||
<TextField
|
<TextField
|
||||||
fullWidth
|
fullWidth
|
||||||
name={setting.key}
|
name={setting.key}
|
||||||
|
disabled={setting.super_req ? !isSuperAdmin : false}
|
||||||
label="Value"
|
label="Value"
|
||||||
type={showPasswords[setting.key] ? 'text' : 'password'}
|
type={showPasswords[setting.key] ? 'text' : 'password'}
|
||||||
value={formData[setting.key] || ''}
|
value={formData[setting.key] || ''}
|
||||||
|
|
@ -399,6 +401,7 @@ const AdminSettingsPage = () => {
|
||||||
<FormControlLabel
|
<FormControlLabel
|
||||||
control={
|
control={
|
||||||
<Switch
|
<Switch
|
||||||
|
disabled={setting.super_req ? !isSuperAdmin : false}
|
||||||
checked={formData[setting.key] === 'true'}
|
checked={formData[setting.key] === 'true'}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
name={setting.key}
|
name={setting.key}
|
||||||
|
|
@ -412,6 +415,7 @@ const AdminSettingsPage = () => {
|
||||||
fullWidth
|
fullWidth
|
||||||
name={setting.key}
|
name={setting.key}
|
||||||
label="Value"
|
label="Value"
|
||||||
|
disabled={setting.super_req ? !isSuperAdmin : false}
|
||||||
value={formData[setting.key] || ''}
|
value={formData[setting.key] || ''}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
|
|
|
||||||
|
|
@ -59,10 +59,10 @@ export const applyConsentSettings = (level) => {
|
||||||
|
|
||||||
if (allowAnalytics) {
|
if (allowAnalytics) {
|
||||||
// Enable Clarity tracking
|
// Enable Clarity tracking
|
||||||
Clarity.consent();
|
Clarity?.consent();
|
||||||
} else {
|
} else {
|
||||||
// Disable Clarity tracking
|
// Disable Clarity tracking
|
||||||
Clarity.consent({ clarity: false });
|
Clarity?.consent({ clarity: false });
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`Applied consent level: ${level}, analytics ${allowAnalytics ? 'enabled' : 'disabled'}`);
|
console.log(`Applied consent level: ${level}, analytics ${allowAnalytics ? 'enabled' : 'disabled'}`);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue