Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cipp",
"version": "7.1.3",
"version": "8.0.2",
"author": "CIPP Contributors",
"homepage": "https://cipp.app/",
"bugs": {
Expand Down Expand Up @@ -112,4 +112,4 @@
"eslint": "9.22.0",
"eslint-config-next": "15.2.2"
}
}
}
2 changes: 1 addition & 1 deletion public/version.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"version": "8.0.2"
"version": "8.0.3"
}
13 changes: 7 additions & 6 deletions src/components/CippComponents/CippMailboxPermissionsDialog.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const CippMailboxPermissionsDialog = ({ formHook }) => {
});

return (
<Stack spacing={3} sx={{ mt: 1 }}>
<Stack spacing={2} sx={{ mt: 1 }}>
<Box>
<CippFormComponent
type="autoComplete"
Expand All @@ -40,16 +40,17 @@ const CippMailboxPermissionsDialog = ({ formHook }) => {
})) || []
}
/>
{fullAccess && (
</Box>
{fullAccess?.length > 0 && (
<Box sx={{ pl: 0.5 }}>
<CippFormComponent
type="switch"
label="Enable Automapping"
name="permissions.AutoMapping"
name="permissions.AutoMap"
formControl={formHook}
sx={{ mt: 0.5, ml: 0.5 }}
/>
)}
</Box>
</Box>
)}
<Box>
<CippFormComponent
type="autoComplete"
Expand Down
84 changes: 45 additions & 39 deletions src/components/CippStandards/CippStandardAccordion.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ const CippStandardAccordion = ({
handleRemoveStandard,
handleAddMultipleStandard,
formControl,
editMode = false,
}) => {
const [configuredState, setConfiguredState] = useState({});
const [filter, setFilter] = useState("all");
Expand Down Expand Up @@ -188,46 +189,48 @@ const CippStandardAccordion = ({

// Initialize when watchedValues are available
useEffect(() => {
// Only run initialization if we have watchedValues and they contain data
if (!watchedValues || Object.keys(watchedValues).length === 0) {
return;
}

// Prevent re-initialization if we already have configuration state
const hasConfigState = Object.keys(configuredState).length > 0;
if (hasConfigState) {
return;
}

console.log("Initializing configuration state from template values");
const initial = {};
const initialConfigured = {};

// For each standard, get its current values and determine if it's configured
Object.keys(selectedStandards).forEach((standardName) => {
const currentValues = _.get(watchedValues, standardName);
if (!currentValues) return;

initial[standardName] = _.cloneDeep(currentValues);
if (editMode) {
// Only run initialization if we have watchedValues and they contain data
if (!watchedValues || Object.keys(watchedValues).length === 0) {
return;
}

const baseStandardName = standardName.split("[")[0];
const standard = providedStandards.find((s) => s.name === baseStandardName);
if (standard) {
initialConfigured[standardName] = isStandardConfigured(
standardName,
standard,
currentValues
);
// Prevent re-initialization if we already have configuration state
const hasConfigState = Object.keys(configuredState).length > 0;
if (hasConfigState) {
return;
}
});

// Store both the initial values and set them as current saved values
setOriginalValues(initial);
setSavedValues(initial);
setConfiguredState(initialConfigured);
// Only depend on watchedValues and selectedStandards to avoid infinite loops
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [watchedValues, selectedStandards]);
console.log("Initializing configuration state from template values");
const initial = {};
const initialConfigured = {};

// For each standard, get its current values and determine if it's configured
Object.keys(selectedStandards).forEach((standardName) => {
const currentValues = _.get(watchedValues, standardName);
if (!currentValues) return;

initial[standardName] = _.cloneDeep(currentValues);

const baseStandardName = standardName.split("[")[0];
const standard = providedStandards.find((s) => s.name === baseStandardName);
if (standard) {
initialConfigured[standardName] = isStandardConfigured(
standardName,
standard,
currentValues
);
}
});

// Store both the initial values and set them as current saved values
setOriginalValues(initial);
setSavedValues(initial);
setConfiguredState(initialConfigured);
// Only depend on watchedValues and selectedStandards to avoid infinite loops
// eslint-disable-next-line react-hooks/exhaustive-deps
}
}, [watchedValues, selectedStandards, editMode]);

// Save changes for a standard
const handleSave = (standardName, standard, current) => {
Expand Down Expand Up @@ -519,6 +522,9 @@ const CippStandardAccordion = ({
// Get current values and check if they differ from saved values
const current = _.get(watchedValues, standardName);
const saved = _.get(savedValues, standardName) || {};
console.log(`Current values for ${standardName}:`, current);
console.log(`Saved values for ${standardName}:`, saved);

const hasUnsaved = !_.isEqual(current, saved);

// Check if all required fields are filled
Expand Down Expand Up @@ -609,7 +615,7 @@ const CippStandardAccordion = ({
const canSave = hasAction && requiredFieldsFilled && hasUnsaved;

console.log(
`Standard: ${standardName}, Action Required: ${actionRequired}, Has Action: ${hasAction}, Required Fields Filled: ${requiredFieldsFilled}, Can Save: ${canSave}`
`Standard: ${standardName}, Action Required: ${actionRequired}, Has Action: ${hasAction}, Required Fields Filled: ${requiredFieldsFilled}, Unsaved Changes: ${hasUnsaved}, Can Save: ${canSave}`
);

return (
Expand Down Expand Up @@ -760,7 +766,7 @@ const CippStandardAccordion = ({
</Grid>
</Box>
<Divider sx={{ mt: 2 }} />
<Box sx={{ px: 3 , py: 2 }}>
<Box sx={{ px: 3, py: 2 }}>
<Stack direction="row" justifyContent="flex-end" spacing={1}>
<Button
variant="outlined"
Expand Down
14 changes: 14 additions & 0 deletions src/components/CippStandards/CippStandardsSideBar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,24 @@ const CippStandardsSideBar = ({
formControl,
createDialog,
edit,
onSaveSuccess,
}) => {
const [currentStep, setCurrentStep] = useState(0);
const [savedItem, setSavedItem] = useState(null);
const dialogAfterEffect = (id) => {
setSavedItem(id);

// Reset form's dirty state to prevent unsaved changes warning
if (formControl && formControl.reset) {
// Get current values and reset the form with them to clear dirty state
const currentValues = formControl.getValues();
formControl.reset(currentValues);
}

// Call the onSaveSuccess callback if provided
if (typeof onSaveSuccess === "function") {
onSaveSuccess();
}
};

const watchForm = useWatch({ control: formControl.control });
Expand Down Expand Up @@ -276,6 +289,7 @@ CippStandardsSideBar.propTypes = {
).isRequired,
updatedAt: PropTypes.string,
formControl: PropTypes.object.isRequired,
onSaveSuccess: PropTypes.func,
};

export default CippStandardsSideBar;
6 changes: 5 additions & 1 deletion src/components/PrivateRoute.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,11 @@ export const PrivateRoute = ({ children, routeType }) => {
});

// Check if the session is still loading before determining authentication status
if (session.isLoading || apiRoles.isLoading) {
if (
session.isLoading ||
apiRoles.isLoading ||
(apiRoles.isFetching && (apiRoles.data === null || apiRoles.data === undefined))
) {
return <LoadingPage />;
}

Expand Down
96 changes: 96 additions & 0 deletions src/data/GDAPRoles.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,22 @@
"Name": "Attribute Definition Reader",
"ObjectId": "1d336d2c-4ae8-42ef-9711-b3604ce3fc2c"
},
{
"ExtensionData": {},
"Description": "Read audit logs and configure diagnostic settings for events related to custom security attributes.",
"IsEnabled": true,
"IsSystem": true,
"Name": "Attribute Log Administrator",
"ObjectId": "5b784334-f94b-471a-a387-e7219fc49ca2"
},
{
"ExtensionData": {},
"Description": "Read audit logs related to custom security attributes.",
"IsEnabled": true,
"IsSystem": true,
"Name": "Attribute Log Reader",
"ObjectId": "9c99539d-8186-4804-835f-fd51ef9e2dcd"
},
{
"ExtensionData": {},
"Description": "Allowed to view, set and reset authentication method information for any non-admin user.",
Expand All @@ -79,6 +95,14 @@
"Name": "Authentication Policy Administrator",
"ObjectId": "0526716b-113d-4c15-b2c8-68e3c22b9f80"
},
{
"ExtensionData": {},
"Description": "Customize sign in and sign up experiences for users by creating and managing custom authentication extensions.",
"IsEnabled": true,
"IsSystem": true,
"Name": "Authentication Extensibility Administrator",
"ObjectId": "25a516ed-2fa0-40ea-a2d0-12923a21473a"
},
{
"ExtensionData": {},
"Description": "Users assigned to this role are added to the local administrators group on Azure AD-joined devices.",
Expand Down Expand Up @@ -311,6 +335,14 @@
"Name": "Global Reader",
"ObjectId": "f2ef992c-3afb-46b9-b7cf-a126ee74c451"
},
{
"ExtensionData": {},
"Description": "Create and manage all aspects of Microsoft Entra Internet Access and Microsoft Entra Private Access, including managing access to public and private endpoints.",
"IsEnabled": true,
"IsSystem": true,
"Name": "Global Secure Access Administrator",
"ObjectId": "ac434307-12b9-4fa1-a708-88bf58caabc1"
},
{
"ExtensionData": {},
"Description": "Members of this role can create/manage groups, create/manage groups settings like naming and expiration policies, and view groups activity and audit reports.",
Expand Down Expand Up @@ -439,6 +471,30 @@
"Name": "Message Center Reader",
"ObjectId": "790c1fb9-7f7d-4f88-86a1-ef1f95c05c1b"
},
{
"ExtensionData": {},
"Description": "Perform all migration functionality to migrate content to Microsoft 365 using Migration Manager.",
"IsEnabled": true,
"IsSystem": true,
"Name": "Microsoft 365 Migration Administrator",
"ObjectId": "8c8b803f-96e1-4129-9349-20738d9f9652"
},
{
"ExtensionData": {},
"Description": "Create and manage all aspects warranty claims and entitlements for Microsoft manufactured hardware, like Surface and HoloLens.",
"IsEnabled": true,
"IsSystem": true,
"Name": "Microsoft Hardware Warranty Administrator",
"ObjectId": "1501b917-7653-4ff9-a4b5-203eaf33784f"
},
{
"ExtensionData": {},
"Description": "Create and read warranty claims for Microsoft manufactured hardware, like Surface and HoloLens.",
"IsEnabled": true,
"IsSystem": true,
"Name": "Microsoft Hardware Warranty Specialist",
"ObjectId": "281fe777-fb20-4fbb-b7a3-ccebce5b0d96"
},
{
"ExtensionData": {},
"Description": "Can manage network locations and review enterprise network design insights for Microsoft 365 Software as a Service applications.",
Expand All @@ -455,6 +511,14 @@
"Name": "Office Apps Administrator",
"ObjectId": "2b745bdf-0803-4d80-aa65-822c4493daac"
},
{
"ExtensionData": {},
"Description": "Write, publish, manage, and review the organizational messages for end-users through Microsoft product surfaces.",
"IsEnabled": true,
"IsSystem": true,
"Name": "Organizational Messages Writer",
"ObjectId": "507f53e4-4e52-4077-abd3-d2e1558b6ea2"
},
{
"ExtensionData": {},
"Description": "Can reset passwords for non-administrators and Password Administrators.",
Expand Down Expand Up @@ -583,6 +647,14 @@
"Name": "SharePoint Administrator",
"ObjectId": "f28a1f50-f6e7-4571-818b-6a12f2af6b6c"
},
{
"ExtensionData": {},
"Description": "Manage all aspects of SharePoint Embedded containers.",
"IsEnabled": true,
"IsSystem": true,
"Name": "SharePoint Embedded Administrator",
"ObjectId": "1a7d78b6-429f-476b-8eb-35fb715fffd4"
},
{
"ExtensionData": {},
"Description": "Can manage all aspects of the Skype for Business product.",
Expand Down Expand Up @@ -631,6 +703,22 @@
"Name": "Teams Devices Administrator",
"ObjectId": "3d762c5a-1b6c-493f-843e-55a3b42923d4"
},
{
"ExtensionData": {},
"Description": "Manage voice and telephony features and troubleshoot communication issues within the Microsoft Teams service.",
"IsEnabled": true,
"IsSystem": true,
"Name": "Teams Telephony Administrator",
"ObjectId": "aa38014f-0993-46e9-9b45-30501a20909d"
},
{
"ExtensionData": {},
"Description": "Create new Microsoft Entra or Azure AD B2C tenants.",
"IsEnabled": true,
"IsSystem": true,
"Name": "Tenant Creator",
"ObjectId": "112ca1a2-15ad-4102-995e-45b0bc479a6a"
},
{
"ExtensionData": {},
"Description": "Can see only tenant level aggregates in Microsoft 365 Usage Analytics and Productivity Score.",
Expand All @@ -647,6 +735,14 @@
"Name": "User Administrator",
"ObjectId": "fe930be7-5e62-47db-91af-98c3a49a38b1"
},
{
"ExtensionData": {},
"Description": "View product feedback, survey results, and reports to find training and communication opportunities.",
"IsEnabled": true,
"IsSystem": true,
"Name": "User Experience Success Manager",
"ObjectId": "27460883-1df1-4691-b032-3b79643e5e63"
},
{
"ExtensionData": {},
"Description": "Manage and share Virtual Visits information and metrics from admin centers or the Virtual Visits app.",
Expand Down
Loading