From 8c78bd092ec78e8ac468afb88c2ad47673171b7d Mon Sep 17 00:00:00 2001 From: John Duprey Date: Mon, 5 Feb 2024 17:40:25 -0500 Subject: [PATCH 01/30] Handle null values in flatten function --- src/components/tables/CippTable.jsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/components/tables/CippTable.jsx b/src/components/tables/CippTable.jsx index 81dcd5e92507..9a4493198592 100644 --- a/src/components/tables/CippTable.jsx +++ b/src/components/tables/CippTable.jsx @@ -556,6 +556,9 @@ export default function CippTable({ let output = {} for (let k in obj) { let val = obj[k] + if (val === null) { + val = '' + } const newKey = prefix ? prefix + '.' + k : k if (typeof val === 'object') { if (Array.isArray(val)) { From 744db5ac04090354d6c8d651c0f6f6053136db21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Tue, 6 Feb 2024 19:27:24 +0100 Subject: [PATCH 02/30] Add tags to all standards --- src/data/standards.json | 124 ++++++++++++++++++++++++++++++---------- 1 file changed, 95 insertions(+), 29 deletions(-) diff --git a/src/data/standards.json b/src/data/standards.json index 8c49f0deb337..762bdc713054 100644 --- a/src/data/standards.json +++ b/src/data/standards.json @@ -2,6 +2,7 @@ { "name": "standards.MailContacts", "cat": "Global Standards", + "tag": ["lowimpact"], "helpText": "Defines the email address to receive general updates and information related to M365 subscriptions. Leave a contact field blank if you do not want to update the contact information.", "disabledFeatures": { "report": false, @@ -37,6 +38,7 @@ { "name": "standards.AuditLog", "cat": "Global Standards", + "tag": ["lowimpact", "CIS"], "helpText": "Enables the Unified Audit Log for tracking and auditing activities. Also runs Enable-OrganizationCustomization if necessary.", "addedComponent": [], "label": "Enable the Unified Audit Log", @@ -46,6 +48,7 @@ { "name": "standards.PhishProtection", "cat": "Global Standards", + "tag": ["lowimpact"], "helpText": "Adds branding to the logon page that only appears if the url is not login.microsoftonline.com. This potentially prevents AITM attacks via EvilNginx. This will also automatically generate alerts if a clone of your login page has been found when set to Remediate.", "addedComponent": [], "label": "Enable Phishing Protection system via branding CSS", @@ -60,6 +63,7 @@ { "name": "standards.EnableCustomerLockbox", "cat": "Global Standards", + "tag": ["lowimpact", "CIS"], "helpText": "Enables Customer Lockbox that offers an approval process for Microsoft support to access organization data", "addedComponent": [], "label": "Enable Customer Lockbox", @@ -69,6 +73,7 @@ { "name": "standards.AnonReportDisable", "cat": "Global Standards", + "tag": ["lowimpact"], "helpText": "Shows usernames instead of pseudo anonymised names in reports. This standard is required for reporting to work correctly.", "addedComponent": [], "label": "Enable Usernames instead of pseudo anonymised names in reports", @@ -78,6 +83,7 @@ { "name": "standards.DisableGuestDirectory", "cat": "Global Standards", + "tag": ["lowimpact"], "helpText": "Disables Guest access to enumerate directory objects. This prevents guest users from seeing other users or guests in the directory.", "addedComponent": [], "label": "Restrict guest user access to directory objects", @@ -87,6 +93,7 @@ { "name": "standards.DisableBasicAuthSMTP", "cat": "Global Standards", + "tag": ["mediumimpact"], "helpText": "Disables SMTP AUTH for the organization and all users. This is the default for new tenants. ", "addedComponent": [], "label": "Disable SMTP Basic Authentication", @@ -96,6 +103,7 @@ { "name": "standards.ActivityBasedTimeout", "cat": "Global Standards", + "tag": ["mediumimpact", "CIS"], "helpText": "Enables and sets Idle session timeout for Microsoft 365 to 1 hour. This policy affects most M365 web apps", "addedComponent": [], "label": "Enable 1 hour Activity based Timeout", @@ -105,6 +113,7 @@ { "name": "standards.laps", "cat": "Entra (AAD) Standards", + "tag": ["lowimpact"], "helpText": "Enables the tenant to use LAPS. You must still create a policy for LAPS to be active on all devices. Use the template standards to deploy this by default.", "addedComponent": [], "label": "Enable LAPS on the tenant", @@ -112,8 +121,9 @@ "impactColour": "info" }, { - "cat": "Entra (AAD) Standards", "name": "standards.PWdisplayAppInformationRequiredState", + "cat": "Entra (AAD) Standards", + "tag": ["lowimpact", "CIS"], "helpText": "Enables the MS authenticator app to display information about the app that is requesting authentication. This displays the application name.", "addedComponent": [], "label": "Enable Passwordless with Location information and Number Matching", @@ -121,8 +131,9 @@ "impactColour": "info" }, { - "cat": "Entra (AAD) Standards", "name": "standards.allowOTPTokens", + "cat": "Entra (AAD) Standards", + "tag": ["lowimpact"], "helpText": "Allows you to use MS authenticator OTP token generator", "addedComponent": [], "label": "Enable OTP via Authenticator", @@ -130,8 +141,9 @@ "impactColour": "info" }, { - "cat": "Entra (AAD) Standards", "name": "standards.PWcompanionAppAllowedState", + "cat": "Entra (AAD) Standards", + "tag": ["lowimpact"], "helpText": "Sets the state of Authenticator Lite, Authenticator lite is a companion app for passwordless authentication.", "addedComponent": [ { @@ -155,8 +167,9 @@ "impactColour": "info" }, { - "cat": "Entra (AAD) Standards", "name": "standards.EnableFIDO2", + "cat": "Entra (AAD) Standards", + "tag": ["lowimpact"], "helpText": "Enables the FIDO2 authenticationMethod for the tenant", "addedComponent": [], "label": "Enable FIDO2 capabilities", @@ -164,8 +177,9 @@ "impactColour": "info" }, { - "cat": "Entra (AAD) Standards", "name": "standards.EnableHardwareOAuth", + "cat": "Entra (AAD) Standards", + "tag": ["lowimpact"], "helpText": "Enables the HardwareOath authenticationMethod for the tenant. This allows you to use hardware tokens for generating 6 digit MFA codes.", "addedComponent": [], "label": "Enable Hardware OAuth tokens", @@ -173,8 +187,9 @@ "impactColour": "info" }, { - "cat": "Entra (AAD) Standards", "name": "standards.allowOAuthTokens", + "cat": "Entra (AAD) Standards", + "tag": ["lowimpact"], "helpText": "Allows you to use any software OAuth token generator", "addedComponent": [], "label": "Enable OTP Software OAuth tokens", @@ -182,8 +197,9 @@ "impactColour": "info" }, { - "cat": "Entra (AAD) Standards", "name": "standards.TAP", + "cat": "Entra (AAD) Standards", + "tag": ["lowimpact"], "helpText": "Enables TAP and sets the default TAP lifetime to 1 hour. This configuration also allows you to select is a TAP is single use or multi-logon.", "addedComponent": [ { @@ -207,8 +223,9 @@ "impactColour": "info" }, { - "cat": "Entra (AAD) Standards", "name": "standards.PasswordExpireDisabled", + "cat": "Entra (AAD) Standards", + "tag": ["lowimpact", "CIS"], "helpText": "Disables the expiration of passwords for the tenant by setting the password expiration policy to never expire for any user.", "addedComponent": [], "label": "Do not expire passwords", @@ -216,8 +233,9 @@ "impactColour": "info" }, { - "cat": "Entra (AAD) Standards", "name": "standards.DisableTenantCreation", + "cat": "Entra (AAD) Standards", + "tag": ["lowimpact", "CIS"], "helpText": "Restricts creation of M365 tenants to the Global Administrator or Tenant Creator roles. ", "addedComponent": [], "label": "Disable M365 Tenant creation by users", @@ -225,8 +243,9 @@ "impactColour": "info" }, { - "cat": "Entra (AAD) Standards", "name": "standards.EnableAppConsentRequests", + "cat": "Entra (AAD) Standards", + "tag": ["lowimpact", "CIS"], "helpText": "Enables App consent admin requests for the tenant via the GA role. Does not overwrite existing reviewer settings", "addedComponent": [ { @@ -240,8 +259,9 @@ "impactColour": "info" }, { - "cat": "Entra (AAD) Standards", "name": "standards.NudgeMFA.enable", + "cat": "Entra (AAD) Standards", + "tag": ["lowimpact"], "helpText": "Enables registration campaign for the tenant", "addedComponent": [], "label": "Request to setup Authenticator if not setup yet", @@ -249,8 +269,9 @@ "impactColour": "info" }, { - "cat": "Entra (AAD) Standards", "name": "standards.NudgeMFA.disable", + "cat": "Entra (AAD) Standards", + "tag": ["lowimpact"], "helpText": "Disables registration campaign for the tenant", "addedComponent": [], "label": "Disables the request to setup Authenticator if setup", @@ -258,8 +279,9 @@ "impactColour": "info" }, { - "cat": "Entra (AAD) Standards", "name": "standards.DisableM365GroupUsers", + "cat": "Entra (AAD) Standards", + "tag": ["lowimpact"], "helpText": "Restricts M365 group creation to certain admin roles. This disables the ability to create Teams, Sharepoint sites, Planner, etc", "addedComponent": [], "label": "Disable M365 Group creation by users", @@ -267,8 +289,9 @@ "impactColour": "info" }, { - "cat": "Entra (AAD) Standards", "name": "standards.DisableSecurityGroupUsers", + "cat": "Entra (AAD) Standards", + "tag": ["mediumimpact"], "helpText": "Completely disables the creation of security groups by users. This also breaks the ability to manage groups themselves, or create Teams", "addedComponent": [], "label": "Disable Security Group creation by users", @@ -276,8 +299,9 @@ "impactColour": "warning" }, { - "cat": "Entra (AAD) Standards", "name": "standards.LegacyMFACleanup", + "cat": "Entra (AAD) Standards", + "tag": ["mediumimpact"], "helpText": "Removes legacy Per-User MFA if the tenant has Security Defaults or an All Users Conditional Access rule enabled.", "addedComponent": [], "label": "Remove Legacy MFA if SD or CA is active", @@ -285,8 +309,9 @@ "impactColour": "warning" }, { - "cat": "Entra (AAD) Standards", "name": "standards.DisableSelfServiceLicenses", + "cat": "Entra (AAD) Standards", + "tag": ["mediumimpact"], "helpText": "This standard currently does not function and can be safely disabled", "addedComponent": [], "label": "Disable Self Service Licensing", @@ -294,8 +319,9 @@ "impactColour": "warning" }, { - "cat": "Entra (AAD) Standards", "name": "standards.DisableGuests", + "cat": "Entra (AAD) Standards", + "tag": ["mediumimpact"], "helpText": "Blocks login for guest users that have not logged in for 90 days", "addedComponent": [], "label": "Disable Guest accounts that have not logged on for 90 days", @@ -303,8 +329,9 @@ "impactColour": "warning" }, { - "cat": "Entra (AAD) Standards", "name": "standards.OauthConsent", + "cat": "Entra (AAD) Standards", + "tag": ["mediumimpact", "CIS"], "helpText": "Disables users from being able to consent to applications, except for those specified in the field below", "addedComponent": [ { @@ -318,30 +345,33 @@ "impactColour": "warning" }, { - "cat": "Entra (AAD) Standards", "name": "standards.OauthConsentLowSec", + "cat": "Entra (AAD) Standards", + "tag": ["mediumimpact"], "helpText": "Sets the default oauth consent level so users can consent to applications that have low risks.", "label": "Allow users to consent to applications with low security risk (Prevent OAuth phishing. Lower impact, less secure)", "impact": "Medium Impact", "impactColour": "warning" }, { - "cat": "Entra (AAD) Standards", "name": "standards.UndoOauth", + "cat": "Entra (AAD) Standards", + "tag": ["highimpact"], + "helpText": "Disables App consent and set to Allow user consent for apps", + "addedComponent": [], "disabledFeatures": { "report": true, "warn": true, "remediate": false }, - "helpText": "Disables App consent and set to Allow user consent for apps", - "addedComponent": [], "label": "Undo App Consent Standard", "impact": "High Impact", "impactColour": "danger" }, { - "cat": "Entra (AAD) Standards", "name": "standards.SecurityDefaults", + "cat": "Entra (AAD) Standards", + "tag": ["highimpact"], "helpText": "Enables security defaults for the tenant, for newer tenants this is enabled by default. Do not enable this feature if you use Conditional Access.", "addedComponent": [], "label": "Enable Security Defaults", @@ -349,8 +379,9 @@ "impactColour": "danger" }, { - "cat": "Entra (AAD) Standards", "name": "standards.DisableSMS", + "cat": "Entra (AAD) Standards", + "tag": ["highimpact"], "helpText": "This blocks users from using SMS as an MFA method. If a user only has SMS as a MFA method, they will be unable to login.", "addedComponent": [], "label": "Disables SMS as an MFA method", @@ -358,8 +389,9 @@ "impactColour": "danger" }, { - "cat": "Entra (AAD) Standards", "name": "standards.DisableVoice", + "cat": "Entra (AAD) Standards", + "tag": ["highimpact"], "helpText": "This blocks users from using Voice call as an MFA method. If a user only has Voice as a MFA method, they will be unable to login.", "addedComponent": [], "label": "Disables Voice call as an MFA method", @@ -367,8 +399,9 @@ "impactColour": "danger" }, { - "cat": "Entra (AAD) Standards", "name": "standards.DisableEmail", + "cat": "Entra (AAD) Standards", + "tag": ["highimpact"], "helpText": "This blocks users from using email as an MFA method. This disables the email OTP option for guest users, and instead promts them to create a Microsoft account.", "addedComponent": [], "label": "Disables Email as an MFA method", @@ -376,8 +409,9 @@ "impactColour": "danger" }, { - "cat": "Entra (AAD) Standards", "name": "standards.Disablex509Certificate", + "cat": "Entra (AAD) Standards", + "tag": ["highimpact"], "helpText": "This blocks users from using Certificates as an MFA method.", "addedComponent": [], "label": "Disables Certificates as an MFA method", @@ -387,6 +421,7 @@ { "name": "standards.OutBoundSpamAlert", "cat": "Exchange Standards", + "tag": ["lowimpact", "CIS"], "helpText": "Set the Outbound Spam Alert e-mail address", "addedComponent": [ { @@ -402,6 +437,7 @@ { "name": "standards.AutoExpandArchive", "cat": "Exchange Standards", + "tag": ["lowimpact"], "helpText": "Enables auto-expanding archives for the tenant", "addedComponent": [], "label": "Enable Auto-expanding archives", @@ -411,6 +447,7 @@ { "name": "standards.EnableOnlineArchiving", "cat": "Exchange Standards", + "tag": ["lowimpact"], "helpText": "Enables the In-Place Online Archive for all UserMailboxes with a valid license.", "addedComponent": [], "label": "Enable Online Archive for all users", @@ -420,6 +457,7 @@ { "name": "standards.SpoofWarn", "cat": "Exchange Standards", + "tag": ["lowimpact", "CIS"], "helpText": "Adds or removes indicators to e-mail messages received from external senders in Outlook. Works on all Outlook clients/OWA", "addedComponent": [ { @@ -445,6 +483,7 @@ { "name": "standards.EnableMailTips", "cat": "Exchange Standards", + "tag": ["lowimpact", "CIS"], "helpText": "Enables all MailTips in Outlook. MailTips are the notifications Outlook and Outlook on the web shows when an email you create, meets some requirements", "addedComponent": [ { @@ -461,6 +500,7 @@ { "name": "standards.DisableViva", "cat": "Exchange Standards", + "tag": ["lowimpact"], "helpText": "Disables the daily viva reports for all users.", "addedComponent": [], "label": "Disable daily Insight/Viva reports", @@ -470,6 +510,7 @@ { "name": "standards.RotateDKIM", "cat": "Exchange Standards", + "tag": ["lowimpact", "CIS"], "helpText": "Rotate DKIM keys that are 1024 bit to 2048 bit", "addedComponent": [], "label": "Rotate DKIM keys that are 1024 bit to 2048 bit", @@ -479,6 +520,7 @@ { "name": "standards.AddDKIM", "cat": "Exchange Standards", + "tag": ["lowimpact", "CIS"], "helpText": "Enables DKIM for all domains that currently support it", "addedComponent": [], "label": "Enables DKIM for all domains that currently support it", @@ -488,6 +530,7 @@ { "name": "standards.EnableMailboxAuditing", "cat": "Exchange Standards", + "tag": ["lowimpact", "CIS"], "helpText": "Enables Mailbox auditing for all mailboxes and on tenant level. By default Microsoft does not enable mailbox auditing for Resource Mailboxes, Public Folder Mailboxes and DiscoverySearch Mailboxes. Unified Audit Log needs to be enabled for this standard to function.", "addedComponent": [], "label": "Enable Mailbox auditing", @@ -497,6 +540,7 @@ { "name": "standards.SendReceiveLimitTenant", "cat": "Exchange Standards", + "tag": ["lowimpact"], "helpText": "Sets the Send and Receive limits for new users. Valid values are 1MB to 150MB", "addedComponent": [ { @@ -517,6 +561,7 @@ { "name": "standards.calDefault", "cat": "Exchange Standards", + "tag": ["lowimpact"], "helpText": "Sets the default sharing level for the default calendar, for all users", "disabledFeatures": { "report": true, @@ -567,6 +612,7 @@ { "name": "standards.DisableExternalCalendarSharing", "cat": "Exchange Standards", + "tag": ["lowimpact", "CIS"], "helpText": "Disables the ability for users to share their calendar with external users. Only for the default policy, so exclusions can be made if needed.", "addedComponent": [], "label": "Disable external calendar sharing", @@ -576,6 +622,7 @@ { "name": "standards.DisableAdditionalStorageProviders", "cat": "Exchange Standards", + "tag": ["lowimpact", "CIS"], "helpText": "Disables the ability for users to open files in Outlook on the Web, from other providers such as Box, Dropbox, Facebook, Google Drive, OneDrive Personal, etc.", "addedComponent": [], "label": "Disable additional storage providers in OWA", @@ -585,6 +632,7 @@ { "name": "standards.DisableOutlookAddins", "cat": "Exchange Standards", + "tag": ["mediumimpact", "CIS"], "helpText": "Disables the ability for users to install add-ins in Outlook. This is to prevent users from installing malicious add-ins.", "addedComponent": [], "label": "Disable users from installing add-ins in Outlook", @@ -594,13 +642,14 @@ { "name": "standards.SafeSendersDisable", "cat": "Exchange Standards", + "tag": ["mediumimpact"], + "helpText": "Loops through all users and removes the Safe Senders list. This is to prevent SPF bypass attacks, as the Safe Senders list is not checked by SPF.", + "addedComponent": [], "disabledFeatures": { "report": true, "warn": true, "remediate": false }, - "helpText": "Loops through all users and removes the Safe Senders list. This is to prevent SPF bypass attacks, as the Safe Senders list is not checked by SPF.", - "addedComponent": [], "label": "Remove Safe Senders to prevent SPF bypass", "impact": "Medium Impact", "impactColour": "warning" @@ -608,6 +657,7 @@ { "name": "standards.DelegateSentItems", "cat": "Exchange Standards", + "tag": ["mediumimpact"], "helpText": "Sets emails sent as and on behalf of shared mailboxes to also be stored in the shared mailbox sent items folder", "addedComponent": [], "label": "Set mailbox Sent Items delegation (Sent items for shared mailboxes)", @@ -617,6 +667,7 @@ { "name": "standards.SendFromAlias", "cat": "Exchange Standards", + "tag": ["mediumimpact"], "helpText": "Enables the ability for users to send from their alias addresses.", "addedComponent": [], "label": "Allow users to send from their alias addresses", @@ -626,6 +677,7 @@ { "name": "standards.UserSubmissions.enable", "cat": "Exchange Standards", + "tag": ["mediumimpact"], "helpText": "Enables the spam submission button in Outlook", "addedComponent": [], "label": "Enable the built-in Report button in Outlook", @@ -635,6 +687,7 @@ { "name": "standards.UserSubmissions.disable", "cat": "Exchange Standards", + "tag": ["mediumimpact"], "helpText": "Disables the spam submission button in Outlook", "addedComponent": [], "label": "Disable the built-in Report button in Outlook", @@ -644,6 +697,7 @@ { "name": "standards.DisableSharedMailbox", "cat": "Exchange Standards", + "tag": ["mediumimpact", "CIS"], "helpText": "Blocks login for all accounts that are marked as a shared mailbox. This is Microsoft best practice to prevent direct logons to shared mailboxes.", "addedComponent": [], "label": "Disable Shared Mailbox AAD accounts", @@ -653,6 +707,7 @@ { "name": "standards.intuneDeviceRetirementDays", "cat": "Intune Standards", + "tag": ["lowimpact"], "helpText": "A value between 0 and 270 is supported. A value of 0 disables retirement, retired devices are removed from Intune after the specified number of days.", "addedComponent": [ { @@ -668,6 +723,7 @@ { "name": "standards.intuneDeviceReg", "cat": "Intune Standards", + "tag": ["mediumimpact"], "helpText": "sets the maximum number of devices that can be registered by a user. A value of 0 disables device registration by users", "addedComponent": [ { @@ -683,6 +739,7 @@ { "name": "standards.intuneRequireMFA", "cat": "Intune Standards", + "tag": ["mediumimpact"], "helpText": "Requires MFA for all users to register devices with Intune. This is useful when not using Conditional Access.", "label": "Require Multifactor Authentication to register or join devices with Microsoft Entra", "impact": "Medium Impact", @@ -691,6 +748,7 @@ { "name": "standards.DeletedUserRentention", "cat": "SharePoint Standards", + "tag": ["lowimpact"], "helpText": "Sets the retention period for deleted users OneDrive to 1 year/365 days", "addedComponent": [], "label": "Retain a deleted user OneDrive for 1 year", @@ -700,6 +758,7 @@ { "name": "standards.DisableAddShortcutsToOneDrive", "cat": "SharePoint Standards", + "tag": ["mediumimpact"], "helpText": "When the feature is disabled the option Add shortcut to OneDrive will be removed. Any folders that have already been added will remain on the user's computer.", "disabledFeatures": { "report": true, @@ -714,6 +773,7 @@ { "name": "standards.DisableSharePointLegacyAuth", "cat": "SharePoint Standards", + "tag": ["mediumimpact", "CIS"], "helpText": "Disables the ability to authenticate with SharePoint using legacy authentication methods. Any applications that use legacy authentication will need to be updated to use modern authentication.", "addedComponent": [], "label": "Disable legacy basic authentication for SharePoint", @@ -723,6 +783,7 @@ { "name": "standards.sharingCapability", "cat": "SharePoint Standards", + "tag": ["highimpact", "CIS"], "helpText": "Sets the default sharing level for OneDrive and Sharepoint. This is a tenant wide setting and overrules any settings set on the site level", "addedComponent": [ { @@ -756,6 +817,7 @@ { "name": "standards.DisableReshare", "cat": "SharePoint Standards", + "tag": ["highimpact", "CIS"], "helpText": "Disables the ability for external users to share files they don't own. Sharing links can only be made for People with existing access", "addedComponent": [], "label": "Disable Resharing by External Users", @@ -765,6 +827,7 @@ { "name": "standards.DisableUserSiteCreate", "cat": "SharePoint Standards", + "tag": ["highimpact"], "helpText": "Disables users from creating new SharePoint sites", "addedComponent": [], "label": "Disable site creation by standard users", @@ -774,6 +837,7 @@ { "name": "standards.ExcludedfileExt", "cat": "SharePoint Standards", + "tag": ["highimpact"], "helpText": "Sets the file extensions that are excluded from syncing with OneDrive. These files will be blocked from upload.", "addedComponent": [ { @@ -789,6 +853,7 @@ { "name": "standards.disableMacSync", "cat": "SharePoint Standards", + "tag": ["highimpact"], "helpText": "Disables the ability for Mac devices to sync with OneDrive.", "addedComponent": [], "label": "Do not allow Mac devices to sync using OneDrive", @@ -798,6 +863,7 @@ { "name": "standards.unmanagedSync", "cat": "SharePoint Standards", + "tag": ["highimpact"], "helpText": "This standard will only allow devices that are AD joined, or AAD joined to sync with OneDrive", "addedComponent": [], "label": "Only allow users to sync OneDrive from AAD joined devices", From 9a7809222cbc0dbcf6006b5c0b579d5fa7454fc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Tue, 6 Feb 2024 20:09:18 +0100 Subject: [PATCH 03/30] Helptext change to reflect change --- src/data/standards.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/data/standards.json b/src/data/standards.json index 762bdc713054..50286fe472d0 100644 --- a/src/data/standards.json +++ b/src/data/standards.json @@ -531,7 +531,7 @@ "name": "standards.EnableMailboxAuditing", "cat": "Exchange Standards", "tag": ["lowimpact", "CIS"], - "helpText": "Enables Mailbox auditing for all mailboxes and on tenant level. By default Microsoft does not enable mailbox auditing for Resource Mailboxes, Public Folder Mailboxes and DiscoverySearch Mailboxes. Unified Audit Log needs to be enabled for this standard to function.", + "helpText": "Enables Mailbox auditing for all mailboxes and on tenant level. Disables audit bypass on all mailboxes. Unified Audit Log needs to be enabled for this standard to function.", "addedComponent": [], "label": "Enable Mailbox auditing", "impact": "Low Impact", From 2c7e6085bdfa3e853cd0c7a2e1abcf7e310d8baf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Tue, 6 Feb 2024 21:42:38 +0100 Subject: [PATCH 04/30] Add sortable quota selectors for onedrive and email reports --- src/views/email-exchange/reports/MailboxStatisticsList.jsx | 6 ++++++ src/views/teams-share/onedrive/OneDriveList.jsx | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/src/views/email-exchange/reports/MailboxStatisticsList.jsx b/src/views/email-exchange/reports/MailboxStatisticsList.jsx index c362d618ba63..d2368dc69ccf 100644 --- a/src/views/email-exchange/reports/MailboxStatisticsList.jsx +++ b/src/views/email-exchange/reports/MailboxStatisticsList.jsx @@ -74,6 +74,12 @@ const MailboxStatsList = () => { sortable: true, exportSelector: 'QuotaGB', }, + { + selector: (row) => Math.round((row.UsedGB / row.QuotaGB) * 100 * 10) / 10, + name: 'Quota Used(%)', + sortable: true, + exportSelector: 'QuotaUsed', + }, { selector: (row) => row['ItemCount'], name: 'Item Count (Total)', diff --git a/src/views/teams-share/onedrive/OneDriveList.jsx b/src/views/teams-share/onedrive/OneDriveList.jsx index b4114ab96c06..4309c729bafb 100644 --- a/src/views/teams-share/onedrive/OneDriveList.jsx +++ b/src/views/teams-share/onedrive/OneDriveList.jsx @@ -112,6 +112,12 @@ const OneDriveList = () => { sortable: true, exportSelector: 'Allocated', }, + { + selector: (row) => Math.round((row.UsedGB / row.Allocated) * 100 * 10) / 10, + name: 'Quota Used(%)', + sortable: true, + exportSelector: 'QuotaUsed', + }, { name: 'URL', selector: (row) => row['url'], From 17cf0606940cd85bb7208fa488b0c2e973a12f0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Fri, 9 Feb 2024 12:36:33 +0100 Subject: [PATCH 05/30] Change nudgeMFA standard to be 1 entry --- src/data/standards.json | 39 +++++++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/src/data/standards.json b/src/data/standards.json index 50286fe472d0..d7a160f250dc 100644 --- a/src/data/standards.json +++ b/src/data/standards.json @@ -259,22 +259,33 @@ "impactColour": "info" }, { - "name": "standards.NudgeMFA.enable", + "name": "standards.NudgeMFA", "cat": "Entra (AAD) Standards", "tag": ["lowimpact"], - "helpText": "Enables registration campaign for the tenant", - "addedComponent": [], - "label": "Request to setup Authenticator if not setup yet", - "impact": "Low Impact", - "impactColour": "info" - }, - { - "name": "standards.NudgeMFA.disable", - "cat": "Entra (AAD) Standards", - "tag": ["lowimpact"], - "helpText": "Disables registration campaign for the tenant", - "addedComponent": [], - "label": "Disables the request to setup Authenticator if setup", + "helpText": "Sets the state of the registration campaign for the tenant", + "addedComponent": [ + { + "type": "Select", + "label": "Select value", + "name": "standards.NudgeMFA.state", + "values": [ + { + "label": "Enabled", + "value": "enabled" + }, + { + "label": "Disabled", + "value": "disabled" + } + ] + }, + { + "type": "number", + "name": "standards.NudgeMFA.snoozeDurationInDays", + "label": "Number of days to allow users to skip registering Authenticator (0-14, default is 1)" + } + ], + "label": "Sets the state for the request to setup Authenticator", "impact": "Low Impact", "impactColour": "info" }, From 22a84c8a60fb2df84cfdaf784e80bf721f8a4f82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Fri, 9 Feb 2024 12:59:16 +0100 Subject: [PATCH 06/30] Change to reflect backend --- src/data/standards.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/data/standards.json b/src/data/standards.json index d7a160f250dc..958d01e36346 100644 --- a/src/data/standards.json +++ b/src/data/standards.json @@ -313,7 +313,7 @@ "name": "standards.LegacyMFACleanup", "cat": "Entra (AAD) Standards", "tag": ["mediumimpact"], - "helpText": "Removes legacy Per-User MFA if the tenant has Security Defaults or an All Users Conditional Access rule enabled.", + "helpText": "This standard currently does not function and can be safely disabled", "addedComponent": [], "label": "Remove Legacy MFA if SD or CA is active", "impact": "Medium Impact", From c1b8f0e916c657185bfd671c4afbca329c0fbb8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Fri, 9 Feb 2024 14:38:05 +0100 Subject: [PATCH 07/30] Add reporting and alerts for undo oauth --- src/data/standards.json | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/data/standards.json b/src/data/standards.json index 958d01e36346..9da849695aa3 100644 --- a/src/data/standards.json +++ b/src/data/standards.json @@ -370,11 +370,6 @@ "tag": ["highimpact"], "helpText": "Disables App consent and set to Allow user consent for apps", "addedComponent": [], - "disabledFeatures": { - "report": true, - "warn": true, - "remediate": false - }, "label": "Undo App Consent Standard", "impact": "High Impact", "impactColour": "danger" From 58ea1f9826c44a2dba2681f0cb60e496c031ba1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Sun, 11 Feb 2024 01:21:57 +0100 Subject: [PATCH 08/30] Change UserSubmissions to be only 1 entry --- src/data/standards.json | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/src/data/standards.json b/src/data/standards.json index 9da849695aa3..c2a1f4534694 100644 --- a/src/data/standards.json +++ b/src/data/standards.json @@ -681,22 +681,28 @@ "impactColour": "warning" }, { - "name": "standards.UserSubmissions.enable", + "name": "standards.UserSubmissions", "cat": "Exchange Standards", "tag": ["mediumimpact"], - "helpText": "Enables the spam submission button in Outlook", - "addedComponent": [], - "label": "Enable the built-in Report button in Outlook", - "impact": "Medium Impact", - "impactColour": "warning" - }, - { - "name": "standards.UserSubmissions.disable", - "cat": "Exchange Standards", - "tag": ["mediumimpact"], - "helpText": "Disables the spam submission button in Outlook", - "addedComponent": [], - "label": "Disable the built-in Report button in Outlook", + "helpText": "Set the state of the spam submission button in Outlook", + "addedComponent": [ + { + "type": "Select", + "label": "Select value", + "name": "standards.UserSubmissions.state", + "values": [ + { + "label": "Enabled", + "value": "enable" + }, + { + "label": "Disabled", + "value": "disable" + } + ] + } + ], + "label": "Set the state of the built-in Report button in Outlook", "impact": "Medium Impact", "impactColour": "warning" }, From 968a7aa0a993bb79079c265e62fdcade554b70ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Sun, 11 Feb 2024 01:54:58 +0100 Subject: [PATCH 09/30] Change to number instead of string --- src/data/standards.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/data/standards.json b/src/data/standards.json index c2a1f4534694..99b730cd616d 100644 --- a/src/data/standards.json +++ b/src/data/standards.json @@ -723,7 +723,7 @@ "helpText": "A value between 0 and 270 is supported. A value of 0 disables retirement, retired devices are removed from Intune after the specified number of days.", "addedComponent": [ { - "type": "input", + "type": "number", "name": "standards.intuneDeviceRetirementDays.days", "label": "Maximum days (0 equals disabled)" } @@ -739,7 +739,7 @@ "helpText": "sets the maximum number of devices that can be registered by a user. A value of 0 disables device registration by users", "addedComponent": [ { - "type": "input", + "type": "number", "name": "standards.intuneDeviceReg.max", "label": "Maximum devices (Enter 2147483647 for unlimited.)" } From 9d28a5ed32de2f87bc70a31cd22927a569d8de46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Sun, 11 Feb 2024 18:00:43 +0100 Subject: [PATCH 10/30] helptext --- src/data/standards.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/data/standards.json b/src/data/standards.json index 99b730cd616d..5d8788197e96 100644 --- a/src/data/standards.json +++ b/src/data/standards.json @@ -850,7 +850,7 @@ "name": "standards.ExcludedfileExt", "cat": "SharePoint Standards", "tag": ["highimpact"], - "helpText": "Sets the file extensions that are excluded from syncing with OneDrive. These files will be blocked from upload.", + "helpText": "Sets the file extensions that are excluded from syncing with OneDrive. These files will be blocked from upload. '*.' is automatically added to the extension and can be omitted.", "addedComponent": [ { "type": "input", From 9b11d338a9d2e5acde8afe1f67aacd8c8c99cfa3 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Sat, 17 Feb 2024 19:17:11 +0100 Subject: [PATCH 11/30] improvements mailbox stats --- .../reports/MailboxStatisticsList.jsx | 42 +++++++++++-------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/src/views/email-exchange/reports/MailboxStatisticsList.jsx b/src/views/email-exchange/reports/MailboxStatisticsList.jsx index d2368dc69ccf..0a6a4c80e9c0 100644 --- a/src/views/email-exchange/reports/MailboxStatisticsList.jsx +++ b/src/views/email-exchange/reports/MailboxStatisticsList.jsx @@ -36,11 +36,11 @@ const MailboxStatsList = () => { omit: tenantColumnSet, }, { - selector: (row) => row['UPN'], + selector: (row) => row['userPrincipalName'], name: 'User Prinicipal Name', sortable: true, - cell: (row) => CellTip(row['UPN']), - exportSelector: 'UPN', + cell: (row) => CellTip(row['userPrincipalName']), + exportSelector: 'userPrincipalName', minWidth: '200px', }, { @@ -51,47 +51,49 @@ const MailboxStatsList = () => { exportSelector: 'displayName', }, { - selector: (row) => row['MailboxType'], + selector: (row) => row[' recipientType'], name: 'Mailbox Type', sortable: true, - exportSelector: 'MailboxType', + cell: (row) => CellTip(row['recipientType']), + exportSelector: 'recipientType', }, { - selector: (row) => row['LastActive'], + selector: (row) => row['lastActivityDate'], name: 'Last Active', sortable: true, - exportSelector: 'LastActive', + exportSelector: 'lastActivityDate', }, { - selector: (row) => row['UsedGB'], - name: 'Used Space(GB)', + selector: (row) => (row['storageUsedInBytes'] / 1024 ** 3).toFixed(2), + name: 'Used Space (GB)', sortable: true, - exportSelector: 'UsedGB', + exportSelector: 'storageUsedInBytes', }, { - selector: (row) => row['QuotaGB'], + selector: (row) => (row['prohibitSendReceiveQuotaInBytes'] / 1024 ** 3).toFixed(2), name: 'Quota (GB)', sortable: true, exportSelector: 'QuotaGB', }, { - selector: (row) => Math.round((row.UsedGB / row.QuotaGB) * 100 * 10) / 10, + selector: (row) => + Math.round((row.storageUsedInBytes / row.prohibitSendReceiveQuotaInBytes) * 100 * 10) / 10, name: 'Quota Used(%)', sortable: true, exportSelector: 'QuotaUsed', }, { - selector: (row) => row['ItemCount'], + selector: (row) => row['itemCount'], name: 'Item Count (Total)', sortable: true, - exportSelector: 'ItemCount', + exportSelector: 'itemCount', }, { - selector: (row) => row['HasArchive'], + selector: (row) => row['hasArchive'], name: 'Archiving Enabled', sortable: true, cell: cellBooleanFormatter({ colourless: true }), - exportSelector: 'HasArchive', + exportSelector: 'hasArchive', }, ] useEffect(() => { @@ -109,9 +111,13 @@ const MailboxStatsList = () => { datatable={{ keyField: 'id', reportName: `${tenant?.defaultDomainName}-MailboxStatistics-List`, - path: '/api/ListMailboxStatistics', + path: '/api/ListGraphRequest', + params: { + TenantFilter: tenant?.defaultDomainName, + Endpoint: "reports/getMailboxUsageDetail(period='D7')", + $format: 'application/json', + }, columns, - params: { TenantFilter: tenant?.defaultDomainName }, tableProps: { conditionalRowStyles: conditionalRowStyles, }, From 6f17b9428784239c5d03506b324c067fc1abf9f9 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Sun, 18 Feb 2024 23:13:59 +0100 Subject: [PATCH 12/30] added manager field --- src/views/identity/administration/AddUser.jsx | 13 +++++++++++++ src/views/identity/administration/EditUser.jsx | 14 ++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/src/views/identity/administration/AddUser.jsx b/src/views/identity/administration/AddUser.jsx index a915ec793bd0..8fe8b2969021 100644 --- a/src/views/identity/administration/AddUser.jsx +++ b/src/views/identity/administration/AddUser.jsx @@ -98,6 +98,7 @@ const AddUser = () => { MustChangePass: values.MustChangePass, tenantID: tenantDomain, addedAttributes: values.addedAttributes, + setManager: values.setManager, ...values.license, } //window.alert(JSON.stringify(shippedValues)) @@ -361,6 +362,18 @@ const AddUser = () => { + + ({ + value: user.id, + name: user.displayName, + }))} + placeholder={!usersIsFetching ? 'Select user' : 'Loading...'} + name="setManager" + /> + {usersError && Failed to load list of users} + { tenantID: tenantDomain, mustchangepass: values.RequirePasswordChange, addedAttributes: values.addedAttributes, + setManager: values.setManager, ...(values.licenses ? values.license : ''), } // window.alert(JSON.stringify(shippedValues)) @@ -425,6 +426,19 @@ const EditUser = () => { + + ({ + value: user.id, + name: user.displayName, + }))} + placeholder={!usersIsFetching ? 'Select user' : 'Loading...'} + name="setManager" + /> + {usersError && Failed to load list of users} + Date: Tue, 20 Feb 2024 20:39:40 -0500 Subject: [PATCH 13/30] Graph Explorer - Add import/export option - Add custom path to CippCodeOffcanvas --- .../utilities/CippCodeOffcanvas.jsx | 37 +++++++++++++------ src/components/utilities/SharedModal.jsx | 2 +- .../tenant/administration/GraphExplorer.jsx | 31 +++++++++++++++- 3 files changed, 55 insertions(+), 15 deletions(-) diff --git a/src/components/utilities/CippCodeOffcanvas.jsx b/src/components/utilities/CippCodeOffcanvas.jsx index 589c27ce3cb8..32572357e565 100644 --- a/src/components/utilities/CippCodeOffcanvas.jsx +++ b/src/components/utilities/CippCodeOffcanvas.jsx @@ -6,6 +6,8 @@ import { useLazyGenericGetRequestQuery, useLazyGenericPostRequestQuery } from 's import { Editor } from '@monaco-editor/react' import { useSelector } from 'react-redux' import PropTypes from 'prop-types' +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' +import CopyToClipboard from 'react-copy-to-clipboard' function CippCodeOffCanvas({ row, @@ -14,6 +16,7 @@ function CippCodeOffCanvas({ type, title = 'Template JSON', hideButton = false, + path = `/api/ExecEditTemplate?type=${type}`, }) { const [SaveTemplate, templateDetails] = useLazyGenericPostRequestQuery() const currentTheme = useSelector((state) => state.app.currentTheme) @@ -53,18 +56,27 @@ function CippCodeOffCanvas({ {!hideButton && ( - - SaveTemplate({ - path: `/api/ExecEditTemplate?type=${type}`, - method: 'POST', - values: templateData, - }) - } - > - Save changes {templateDetails.isFetching && } - + <> + + SaveTemplate({ + path: path, + method: 'POST', + values: templateData, + }) + } + className="me-2" + > + Save changes + {templateDetails.isFetching && } + + + + Copy to Clipboard + + + )} @@ -83,6 +95,7 @@ CippCodeOffCanvas.propTypes = { type: PropTypes.string, title: PropTypes.string, hideButton: PropTypes.bool, + path: PropTypes.string, } export default CippCodeOffCanvas diff --git a/src/components/utilities/SharedModal.jsx b/src/components/utilities/SharedModal.jsx index fb8501fc93ca..9167b7a2073b 100644 --- a/src/components/utilities/SharedModal.jsx +++ b/src/components/utilities/SharedModal.jsx @@ -29,7 +29,7 @@ function mapBodyComponent({ componentType, data, componentProps }) { } const sharedProps = { - componentType: PropTypes.oneOf(['table', 'list', 'text', 'confirm']), + componentType: PropTypes.oneOf(['table', 'list', 'text', 'confirm', 'codeblock']), componentProps: PropTypes.object, body: PropTypes.oneOfType([PropTypes.node, PropTypes.element]), data: PropTypes.any, diff --git a/src/views/tenant/administration/GraphExplorer.jsx b/src/views/tenant/administration/GraphExplorer.jsx index dea2ff3b06e1..1f77b38648ac 100644 --- a/src/views/tenant/administration/GraphExplorer.jsx +++ b/src/views/tenant/administration/GraphExplorer.jsx @@ -30,7 +30,7 @@ import { import { OnChange } from 'react-final-form-listeners' import { cellGenericFormatter } from 'src/components/tables/CellGenericFormat' import PropTypes from 'prop-types' -import { ModalService } from 'src/components/utilities' +import { CippCodeOffCanvas, ModalService } from 'src/components/utilities' const GraphExplorer = () => { const tenant = useSelector((state) => state.app.currentTenant) @@ -39,6 +39,7 @@ const GraphExplorer = () => { const [alertVisible, setAlertVisible] = useState() const [random, setRandom] = useState('') const [random2, setRandom2] = useState('') + const [ocVisible, setOCVisible] = useState(false) const [searchNow, setSearchNow] = useState(false) const [visibleA, setVisibleA] = useState(true) const handleSubmit = async (values) => { @@ -316,7 +317,11 @@ const GraphExplorer = () => { - + + + + + {(props) => { @@ -326,6 +331,14 @@ const GraphExplorer = () => { return ( <>
+ + setOCVisible(true)} + className="me-2" + > + + + {!preset[0]?.isBuiltin && preset[0]?.id && preset[0]?.IsMyPreset && ( @@ -373,6 +386,7 @@ const GraphExplorer = () => { values: props.values, }) } + className="me-2" > @@ -394,6 +408,19 @@ const GraphExplorer = () => { {postResults.data?.Results} )} + { + setOCVisible(false) + setRandom2((Math.random() + 1).toString(36).substring(7)) + }} + /> ) }} From 3722ee348361b891ab5940b902e8ec364604afdf Mon Sep 17 00:00:00 2001 From: John Duprey Date: Tue, 20 Feb 2024 21:35:23 -0500 Subject: [PATCH 14/30] Add copied state --- src/components/utilities/CippCodeOffcanvas.jsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/components/utilities/CippCodeOffcanvas.jsx b/src/components/utilities/CippCodeOffcanvas.jsx index 32572357e565..f17433ff2e4a 100644 --- a/src/components/utilities/CippCodeOffcanvas.jsx +++ b/src/components/utilities/CippCodeOffcanvas.jsx @@ -22,6 +22,7 @@ function CippCodeOffCanvas({ const currentTheme = useSelector((state) => state.app.currentTheme) const [templateData, setFormData] = useState(row) const [invalidJSON, setInvalid] = useState(false) + const [copied, setCopied] = useState(false) function handleEditorChange(value, event) { try { @@ -71,9 +72,10 @@ function CippCodeOffCanvas({ Save changes {templateDetails.isFetching && } - + setCopied(true)}> - Copy to Clipboard + Copy + to Clipboard From 03cb55e4f7335f412a07fd61c7ca66cd3f470b8a Mon Sep 17 00:00:00 2001 From: John Duprey Date: Tue, 20 Feb 2024 22:02:09 -0500 Subject: [PATCH 15/30] Update CippCodeOffcanvas.jsx --- src/components/utilities/CippCodeOffcanvas.jsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/components/utilities/CippCodeOffcanvas.jsx b/src/components/utilities/CippCodeOffcanvas.jsx index f17433ff2e4a..edd5abc34b74 100644 --- a/src/components/utilities/CippCodeOffcanvas.jsx +++ b/src/components/utilities/CippCodeOffcanvas.jsx @@ -1,4 +1,4 @@ -import React, { useState } from 'react' +import React, { useState, useEffect } from 'react' import { CButton, CCallout, CCol, CRow, CSpinner } from '@coreui/react' import { CippOffcanvas } from 'src/components/utilities' import { useLazyGenericGetRequestQuery, useLazyGenericPostRequestQuery } from 'src/store/api/app' @@ -33,6 +33,10 @@ function CippCodeOffCanvas({ } } + useEffect(() => { + setCopied(false) + }, [setCopied, templateData]) + return ( <> Date: Wed, 21 Feb 2024 11:14:55 +0100 Subject: [PATCH 16/30] add bulk remove and add of users --- src/components/tables/CippTable.jsx | 34 +++++++++++++- src/views/identity/administration/Users.jsx | 52 +++++++++++++++++++++ 2 files changed, 84 insertions(+), 2 deletions(-) diff --git a/src/components/tables/CippTable.jsx b/src/components/tables/CippTable.jsx index 99c36ae46708..74dbf52ecd53 100644 --- a/src/components/tables/CippTable.jsx +++ b/src/components/tables/CippTable.jsx @@ -389,14 +389,43 @@ export default function CippTable({ } const newModalBody = {} for (let [objName, objValue] of Object.entries(modalBody)) { - if (objValue.toString().startsWith('!')) { + if (typeof objValue === 'object' && objValue !== null) { + newModalBody[objName] = {} + for (let [nestedObjName, nestedObjValue] of Object.entries(objValue)) { + if (typeof nestedObjValue === 'string' && nestedObjValue.startsWith('!')) { + newModalBody[objName][nestedObjName] = row[nestedObjValue.replace('!', '')] + } else { + newModalBody[objName][nestedObjName] = nestedObjValue + } + } + } else if (typeof objValue === 'string' && objValue.startsWith('!')) { newModalBody[objName] = row[objValue.replace('!', '')] + } else { + newModalBody[objName] = objValue } } const NewModalUrl = `${modalUrl.split('?')[0]}?${urlParams.toString()}` + const selectedValue = inputRef.current.value + let additionalFields = {} + if (inputRef.current.nodeName === 'SELECT') { + const selectedItem = dropDownInfo.data.find( + (item) => item[modalDropdown.valueField] === selectedValue, + ) + if (selectedItem && modalDropdown.addedField) { + Object.keys(modalDropdown.addedField).forEach((key) => { + additionalFields[key] = selectedItem[modalDropdown.addedField[key]] + }) + } + } + const results = await genericPostRequest({ path: NewModalUrl, - values: { ...modalBody, ...newModalBody, ...{ input: inputRef.current.value } }, + values: { + ...modalBody, + ...newModalBody, + ...additionalFields, + ...{ input: inputRef.current.value }, + }, }) resultsarr.push(results) setMassResults(resultsarr) @@ -466,6 +495,7 @@ export default function CippTable({ } const executeselectedAction = (item) => { + console.log(item) setModalContent({ item, }) diff --git a/src/views/identity/administration/Users.jsx b/src/views/identity/administration/Users.jsx index e6e4cbc30539..1d060f02d59d 100644 --- a/src/views/identity/administration/Users.jsx +++ b/src/views/identity/administration/Users.jsx @@ -551,6 +551,58 @@ const Users = (row) => { valueField: 'URL', }, }, + { + label: 'Add to group', + color: 'info', + modal: true, + modalType: 'POST', + modalBody: { + username: '!userPrincipalName', + userid: '!id', + TenantId: tenant.defaultDomainName, + Addmember: { + value: '!userPrincipalName', + }, + }, + modalUrl: `/api/EditGroup`, + modalMessage: 'Select the group to add', + modalDropdown: { + url: `/api/listGroups?TenantFilter=${tenant.defaultDomainName}`, + labelField: 'displayName', + valueField: 'id', + addedField: { + groupId: 'id', + groupType: 'calculatedGroupType', + groupName: 'displayName', + }, + }, + }, + { + label: 'Remove from group', + color: 'info', + modal: true, + modalType: 'POST', + modalBody: { + username: '!userPrincipalName', + userid: '!id', + TenantId: tenant.defaultDomainName, + RemoveMember: { + value: '!userPrincipalName', + }, + }, + modalUrl: `/api/EditGroup`, + modalMessage: 'Select the group to remove', + modalDropdown: { + url: `/api/listGroups?TenantFilter=${tenant.defaultDomainName}`, + labelField: 'displayName', + valueField: 'id', + addedField: { + groupId: 'id', + groupType: 'calculatedGroupType', + groupName: 'displayName', + }, + }, + }, { label: 'Set Out of Office', color: 'info', From 3618f88c229b57bf484ed26eafbed5d1c7d197c6 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Wed, 21 Feb 2024 11:20:16 +0100 Subject: [PATCH 17/30] text changes --- src/views/email-exchange/connectors/ConnectorList.jsx | 2 +- src/views/email-exchange/spamfilter/Spamfilter.jsx | 2 +- src/views/email-exchange/transport/TransportRules.jsx | 2 +- src/views/endpoint/autopilot/AutopilotListDevices.jsx | 2 +- src/views/identity/administration/Deleted.jsx | 2 +- src/views/teams-share/onedrive/OneDriveList.jsx | 2 +- src/views/teams-share/sharepoint/SharepointList.jsx | 2 +- src/views/tenant/administration/ListAlertsQueue.jsx | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/views/email-exchange/connectors/ConnectorList.jsx b/src/views/email-exchange/connectors/ConnectorList.jsx index e4e887adbd71..990e1d555199 100644 --- a/src/views/email-exchange/connectors/ConnectorList.jsx +++ b/src/views/email-exchange/connectors/ConnectorList.jsx @@ -18,7 +18,7 @@ const Offcanvas = (row, rowIndex, formatExtraData) => { { { { { { { { ({ label: key, value: From faf371e514e99360e21941e85c2c408de48c19a5 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Wed, 21 Feb 2024 11:39:34 +0100 Subject: [PATCH 18/30] add urlonly --- src/views/identity/administration/Users.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/views/identity/administration/Users.jsx b/src/views/identity/administration/Users.jsx index 1d060f02d59d..f3a4644eb1ec 100644 --- a/src/views/identity/administration/Users.jsx +++ b/src/views/identity/administration/Users.jsx @@ -129,7 +129,7 @@ const Offcanvas = (row, rowIndex, formatExtraData) => { }, modalUrl: `/api/ExecOneDriveShortCut`, modalDropdown: { - url: `/api/listSites?TenantFilter=${tenant.defaultDomainName}&type=SharePointSiteUsage`, + url: `/api/listSites?TenantFilter=${tenant.defaultDomainName}&type=SharePointSiteUsage?URLOnly=true`, labelField: 'URL', valueField: 'URL', }, From be6fdbaa68b7911ca564529b8f061b49b6645dfe Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Wed, 21 Feb 2024 11:41:02 +0100 Subject: [PATCH 19/30] add urlonly --- src/views/identity/administration/Users.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/views/identity/administration/Users.jsx b/src/views/identity/administration/Users.jsx index f3a4644eb1ec..774f25a29c2d 100644 --- a/src/views/identity/administration/Users.jsx +++ b/src/views/identity/administration/Users.jsx @@ -129,7 +129,7 @@ const Offcanvas = (row, rowIndex, formatExtraData) => { }, modalUrl: `/api/ExecOneDriveShortCut`, modalDropdown: { - url: `/api/listSites?TenantFilter=${tenant.defaultDomainName}&type=SharePointSiteUsage?URLOnly=true`, + url: `/api/listSites?TenantFilter=${tenant.defaultDomainName}&type=SharePointSiteUsage&URLOnly=true`, labelField: 'URL', valueField: 'URL', }, From 35c31a5b141c544f22d01851b89fe27b0cade1da Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Wed, 21 Feb 2024 12:30:07 +0100 Subject: [PATCH 20/30] add device list --- src/_nav.jsx | 5 + src/routes.js | 4 + src/views/identity/administration/Devices.jsx | 105 ++++++++++++++++++ 3 files changed, 114 insertions(+) create mode 100644 src/views/identity/administration/Devices.jsx diff --git a/src/_nav.jsx b/src/_nav.jsx index a17d7e73a344..abbc9c2e9835 100644 --- a/src/_nav.jsx +++ b/src/_nav.jsx @@ -50,6 +50,11 @@ const _nav = [ name: 'Groups', to: '/identity/administration/groups', }, + { + component: CNavItem, + name: 'Devices', + to: '/identity/administration/devices', + }, { component: CNavItem, name: 'Deploy Group Template', diff --git a/src/routes.js b/src/routes.js index 2f41ef51dff5..e5d7082719fc 100644 --- a/src/routes.js +++ b/src/routes.js @@ -30,6 +30,8 @@ const EditGroup = React.lazy(() => import('src/views/identity/administration/Edi const ViewGroup = React.lazy(() => import('src/views/identity/administration/ViewGroup')) const Roles = React.lazy(() => import('src/views/identity/administration/Roles')) const Devices = React.lazy(() => import('src/views/endpoint/intune/Devices')) +const allDevices = React.lazy(() => import('src/views/identity/administration/Devices')) + const PageLogOut = React.lazy(() => import('src/views/pages/LogoutRedirect/PageLogOut')) const Page404 = React.lazy(() => import('src/views/pages/page404/Page404')) @@ -258,6 +260,8 @@ const routes = [ { path: '/identity/administration/ViewBec', name: 'View BEC', component: ViewBEC }, { path: '/identity/administration', name: 'Administration' }, { path: '/identity/administration/users', name: 'Users', component: Users }, + { path: '/identity/administration/devices', name: 'Devices', component: allDevices }, + { path: '/identity/administration/groups/add', name: 'Add Group', component: AddGroup }, { path: '/identity/administration/group-templates', diff --git a/src/views/identity/administration/Devices.jsx b/src/views/identity/administration/Devices.jsx new file mode 100644 index 000000000000..935f5af5dcc1 --- /dev/null +++ b/src/views/identity/administration/Devices.jsx @@ -0,0 +1,105 @@ +import React, { useEffect, useState } from 'react' +import { useSelector } from 'react-redux' +import { CellTip, cellBooleanFormatter } from 'src/components/tables' +import { CippPageList } from 'src/components/layout' + +const DevicesList = () => { + const [tenantColumnSet, setTenantColumn] = useState(true) + const tenant = useSelector((state) => state.app.currentTenant) + + const columns = [ + { + name: 'Tenant', + selector: (row) => row['Tenant'], + sortable: true, + cell: (row) => CellTip(row['Tenant']), + exportSelector: 'Tenant', + omit: tenantColumnSet, + }, + { + name: 'Retrieval Status', + selector: (row) => row['CippStatus'], + sortable: true, + cell: (row) => CellTip(row['CippStatus']), + exportSelector: 'CippStatus', + omit: tenantColumnSet, + }, + { + selector: (row) => row['displayName'], + name: 'Display Name', + sortable: true, + cell: (row) => CellTip(row['displayName']), + exportSelector: 'displayName', + }, + { + selector: (row) => row['deviceOwnership'], + name: 'Device Ownership', + sortable: true, + cell: (row) => CellTip(row['deviceOwnership']), + exportSelector: 'recipientType', + }, + { + selector: (row) => row['enrollmentType'], + name: 'Enrollment Type', + sortable: true, + exportSelector: 'enrollmentType', + }, + { + selector: (row) => row['manufacturer'], + name: 'Manufacturer', + sortable: true, + exportSelector: 'manufacturer', + }, + { + selector: (row) => row['model'], + name: 'Model', + sortable: true, + exportSelector: 'model', + }, + { + selector: (row) => row['operatingSystem'], + name: 'OS', + sortable: true, + exportSelector: 'operatingSystem', + }, + { + selector: (row) => row['operatingSystemVersion'], + name: 'Version', + sortable: true, + exportSelector: 'operatingSystemVersion', + }, + { + selector: (row) => row['profileType'], + name: 'Profile Type', + sortable: true, + exportSelector: 'profileType', + }, + ] + useEffect(() => { + if (tenant.defaultDomainName === 'AllTenants') { + setTenantColumn(false) + } + if (tenant.defaultDomainName !== 'AllTenants') { + setTenantColumn(true) + } + }, [tenant.defaultDomainName, tenantColumnSet]) + return ( + + ) +} + +export default DevicesList From 06b708f86c1574780c34a67133e0a3825010346e Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Wed, 21 Feb 2024 13:06:48 +0100 Subject: [PATCH 21/30] add device actions --- src/views/identity/administration/Devices.jsx | 51 ++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/src/views/identity/administration/Devices.jsx b/src/views/identity/administration/Devices.jsx index 935f5af5dcc1..aa608f343977 100644 --- a/src/views/identity/administration/Devices.jsx +++ b/src/views/identity/administration/Devices.jsx @@ -2,11 +2,55 @@ import React, { useEffect, useState } from 'react' import { useSelector } from 'react-redux' import { CellTip, cellBooleanFormatter } from 'src/components/tables' import { CippPageList } from 'src/components/layout' +import { Link } from 'react-router-dom' +import { CButton } from '@coreui/react' +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' +import { faEdit, faEllipsisV } from '@fortawesome/free-solid-svg-icons' +import { CippActionsOffcanvas } from 'src/components/utilities' const DevicesList = () => { const [tenantColumnSet, setTenantColumn] = useState(true) const tenant = useSelector((state) => state.app.currentTenant) - + const Offcanvas = (row, rowIndex, formatExtraData) => { + const tenant = useSelector((state) => state.app.currentTenant) + const [ocVisible, setOCVisible] = useState(false) + const editLink = `/identity/administration/groups/edit?groupId=${row.id}&tenantDomain=${tenant.defaultDomainName}` + return ( + <> + setOCVisible(true)}> + + + setOCVisible(false)} + /> + + ) + } const columns = [ { name: 'Tenant', @@ -74,6 +118,11 @@ const DevicesList = () => { sortable: true, exportSelector: 'profileType', }, + { + name: 'Actions', + cell: Offcanvas, + maxWidth: '20px', + }, ] useEffect(() => { if (tenant.defaultDomainName === 'AllTenants') { From 375459f3a19f66dc02afe95369cb7c3f19ee9d89 Mon Sep 17 00:00:00 2001 From: John Duprey Date: Wed, 21 Feb 2024 16:57:50 -0500 Subject: [PATCH 22/30] Cleanup graph explorer import/export --- src/components/utilities/CippCodeOffcanvas.jsx | 8 ++++++-- src/views/tenant/administration/GraphExplorer.jsx | 15 ++++++++++++--- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/components/utilities/CippCodeOffcanvas.jsx b/src/components/utilities/CippCodeOffcanvas.jsx index edd5abc34b74..a9b5cf41a055 100644 --- a/src/components/utilities/CippCodeOffcanvas.jsx +++ b/src/components/utilities/CippCodeOffcanvas.jsx @@ -73,8 +73,12 @@ function CippCodeOffCanvas({ } className="me-2" > - Save changes - {templateDetails.isFetching && } + {templateDetails.isFetching ? ( + + ) : ( + + )} + Save changes setCopied(true)}> diff --git a/src/views/tenant/administration/GraphExplorer.jsx b/src/views/tenant/administration/GraphExplorer.jsx index 1f77b38648ac..3664f42caed6 100644 --- a/src/views/tenant/administration/GraphExplorer.jsx +++ b/src/views/tenant/administration/GraphExplorer.jsx @@ -83,7 +83,7 @@ const GraphExplorer = () => { const handleManagePreset = ({ values, action, message }) => { var params = { action: action, - values: values, + preset: values, } ModalService.confirm({ title: 'Confirm', @@ -260,6 +260,15 @@ const GraphExplorer = () => { field: PropTypes.node, set: PropTypes.string, } + + function getPresetProps(values) { + var newvals = Object.assign({}, values) + delete newvals['reportTemplate'] + delete newvals['tenantFilter'] + delete newvals['IsShared'] + return newvals + } + console.log(graphrequest.data) return ( @@ -301,6 +310,7 @@ const GraphExplorer = () => { name="reportTemplate" label="Select a report preset" placeholder="Select a report" + retainInput={false} multi={false} values={presets.map((preset) => { return { @@ -411,8 +421,7 @@ const GraphExplorer = () => { Date: Fri, 23 Feb 2024 00:46:24 -0500 Subject: [PATCH 23/30] Function Statistics --- src/_nav.jsx | 5 ++ src/routes.js | 3 +- src/views/cipp/Statistics.jsx | 153 ++++++++++++++++++++++++++++++++++ 3 files changed, 160 insertions(+), 1 deletion(-) create mode 100644 src/views/cipp/Statistics.jsx diff --git a/src/_nav.jsx b/src/_nav.jsx index abbc9c2e9835..d701c055f36d 100644 --- a/src/_nav.jsx +++ b/src/_nav.jsx @@ -742,6 +742,11 @@ const _nav = [ name: 'Logbook', to: '/cipp/logs', }, + { + component: CNavItem, + name: 'Statistics', + to: '/cipp/statistics', + }, { component: CNavItem, name: 'SAM Setup Wizard', diff --git a/src/routes.js b/src/routes.js index e5d7082719fc..4f119b52d8c8 100644 --- a/src/routes.js +++ b/src/routes.js @@ -3,6 +3,7 @@ import React from 'react' const Home = React.lazy(() => import('src/views/home/Home')) const Logs = React.lazy(() => import('src/views/cipp/Logs')) const Scheduler = React.lazy(() => import('src/views/cipp/Scheduler')) +const Statistics = React.lazy(() => import('src/views/cipp/Statistics')) const Users = React.lazy(() => import('src/views/identity/administration/Users')) const DeletedItems = React.lazy(() => import('src/views/identity/administration/Deleted')) const ViewBEC = React.lazy(() => import('src/views/identity/administration/ViewBEC')) @@ -244,7 +245,7 @@ const routes = [ { path: '/home', name: 'Home', component: Home }, { path: '/cipp/logs', name: 'Logs', component: Logs }, { path: '/cipp/scheduler', name: 'Scheduler', component: Scheduler }, - + { path: '/cipp/statistics', name: 'Statistics', component: Statistics }, { path: '/cipp/404', name: 'Error', component: Page404 }, { path: '/cipp/403', name: 'Error', component: Page403 }, { path: '/cipp/500', name: 'Error', component: Page500 }, diff --git a/src/views/cipp/Statistics.jsx b/src/views/cipp/Statistics.jsx new file mode 100644 index 000000000000..6fba968ca726 --- /dev/null +++ b/src/views/cipp/Statistics.jsx @@ -0,0 +1,153 @@ +import React, { useState } from 'react' +import { CippPage } from 'src/components/layout' +import { + CButton, + CCard, + CCardBody, + CCardHeader, + CCardTitle, + CCol, + CCollapse, + CFormInput, + CFormLabel, + CFormSelect, + CRow, + CSpinner, +} from '@coreui/react' +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' +import { faChevronRight, faChevronDown } from '@fortawesome/free-solid-svg-icons' +import { CippTable } from 'src/components/tables' +import { cellGenericFormatter } from 'src/components/tables/CellGenericFormat' +import { useSelector } from 'react-redux' +import { useGenericGetRequestQuery } from 'src/store/api/app' +import { RFFCFormSelect } from 'src/components/forms' + +const columns = [ + { + name: 'Name', + selector: (row) => row['Name'], + sortable: true, + cell: cellGenericFormatter(), + exportSelector: 'Name', + minWidth: '145px', + maxWidth: '145px', + }, + { + name: 'Executions', + selector: (row) => row['ExecutionCount'], + sortable: true, + exportSelector: 'ExecutionCount', + }, + { + name: 'Total (seconds)', + selector: (row) => row['TotalSeconds'], + sortable: true, + exportSelector: 'TotalSeconds', + }, + { + name: 'Max (seconds)', + selector: (row) => row['MaxSeconds'], + sortable: true, + exportSelector: 'MaxSeconds', + }, + { + name: 'Avg (seconds)', + selector: (row) => row['AvgSeconds'], + sortable: true, + exportSelector: 'AvgSeconds', + cell: (row) => Math.round(row['AvgSeconds'] * 100) / 100, + }, +] + +const Statistics = () => { + const [visibleA, setVisibleA] = useState(false) + const [type, setType] = useState('Functions') + const [interval, setInterval] = useState('Days') + const [time, setTime] = useState(1) + const tenant = useSelector((state) => state.app.currentTenant) + const { data, isFetching, error, isSuccess } = useGenericGetRequestQuery({ + path: '/api/ListFunctionStats', + params: { + FunctionType: 'Queue', + Interval: interval, + Time: time, + TenantFilter: tenant?.defaultDomainName, + }, + }) + + return ( + <> + + + + + + Options + setVisibleA(!visibleA)} + > + + + + + + + + + + + + Report + setType(e.target.value)}> + + + + + +
+ Interval + setInterval(e.target.value)}> + + + + +
+
+ Time + setTime(e.target.value)} + defaultValue={1} + /> +
+
+
+
+
+
+
+
+
+ + + + Statistics + + + {isFetching && } + {isSuccess && ( + + )} + + + + + ) +} + +export default Statistics From b501b21fa5834df5adc883c67c7680dc70813c43 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Fri, 23 Feb 2024 12:21:31 +0100 Subject: [PATCH 24/30] fix interface bug for all tenants overview --- .../tenant/standards/ListAppliedStandards.jsx | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/views/tenant/standards/ListAppliedStandards.jsx b/src/views/tenant/standards/ListAppliedStandards.jsx index 1d0979924189..61c50f1a0d99 100644 --- a/src/views/tenant/standards/ListAppliedStandards.jsx +++ b/src/views/tenant/standards/ListAppliedStandards.jsx @@ -207,10 +207,16 @@ const ApplyNewStandard = () => { (tenant) => tenant.displayName === 'AllTenants', ) - function getLabel(item) { + function getLabel(item, type) { + if (!item || !item.name) { + return '' + } const keys = item.name.split('.') let value = keys.reduce((prev, curr) => prev && prev[curr], allTenantsStandard) - return value ? `* Enabled via All Tenants` : '' + if (!value || !value[type]) { + return '' + } + return `* Enabled via All Tenants` } const groupedStandards = allStandardsList.reduce((acc, obj) => { @@ -437,7 +443,7 @@ const ApplyNewStandard = () => { name={`${obj.name}.report`} disabled={obj.disabledFeatures?.report} helpText="Report stores the data in the database to use in custom BPA reports." - sublabel={getLabel(obj)} + sublabel={getLabel(obj, 'report')} /> @@ -446,7 +452,7 @@ const ApplyNewStandard = () => { name={`${obj.name}.alert`} disabled={obj.disabledFeatures?.warn} helpText="Alert Generates an alert in the log, if remediate is enabled the log entry will also say if the remediation was successful." - sublabel={getLabel(obj)} + sublabel={getLabel(obj, 'alert')} /> @@ -455,7 +461,7 @@ const ApplyNewStandard = () => { name={`${obj.name}.remediate`} disabled={obj.disabledFeatures?.remediate} helpText={'Remediate executes the fix for standard.'} - sublabel={getLabel(obj)} + sublabel={getLabel(obj, 'remediate')} /> From 3b64090129bff0d3f2a4e4dca637c670b23c960a Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Fri, 23 Feb 2024 14:40:35 +0100 Subject: [PATCH 25/30] add exchange standard --- src/data/standards.json | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/data/standards.json b/src/data/standards.json index 5d8788197e96..01394297cd34 100644 --- a/src/data/standards.json +++ b/src/data/standards.json @@ -440,6 +440,16 @@ "impact": "Low Impact", "impactColour": "info" }, + { + "name": "standards.MessageExpiration", + "cat": "Exchange Standards", + "tag": ["lowimpact"], + "helpText": "Sets the transport message configuration to timeout a message at 12 hours.", + "addedComponent": [], + "label": "Lower Transport Message Expiration to 12 hours", + "impact": "Low Impact", + "impactColour": "info" + }, { "name": "standards.AutoExpandArchive", "cat": "Exchange Standards", From 129d3a778234588cc2680bd1eaa83f7b22f0c835 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Fri, 23 Feb 2024 14:57:33 +0100 Subject: [PATCH 26/30] version up --- public/version_latest.txt | 2 +- version_latest.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/public/version_latest.txt b/public/version_latest.txt index 3bff059174b8..7cbea073bea1 100644 --- a/public/version_latest.txt +++ b/public/version_latest.txt @@ -1 +1 @@ -5.1.1 \ No newline at end of file +5.2.0 \ No newline at end of file diff --git a/version_latest.txt b/version_latest.txt index 3bff059174b8..7cbea073bea1 100644 --- a/version_latest.txt +++ b/version_latest.txt @@ -1 +1 @@ -5.1.1 \ No newline at end of file +5.2.0 \ No newline at end of file From 29f22a9599b8fa02c8b78ef61b475db61eb424d7 Mon Sep 17 00:00:00 2001 From: John Duprey Date: Sat, 24 Feb 2024 10:30:17 -0500 Subject: [PATCH 27/30] Graph Explorer - Add React Select search with Creatable component - Change $select form input to RFFCSelectSearch with preloading properties --- src/components/forms/RFFComponents.jsx | 43 ++++++++- .../tenant/administration/GraphExplorer.jsx | 93 +++++++++++++++++-- 2 files changed, 124 insertions(+), 12 deletions(-) diff --git a/src/components/forms/RFFComponents.jsx b/src/components/forms/RFFComponents.jsx index 2d315826b4f2..834c9688d2cc 100644 --- a/src/components/forms/RFFComponents.jsx +++ b/src/components/forms/RFFComponents.jsx @@ -11,6 +11,7 @@ import { CTooltip, } from '@coreui/react' import Select from 'react-select' +import Creatable, { useCreatable } from 'react-select/creatable' import { Field } from 'react-final-form' import { FieldArray } from 'react-final-form-arrays' import React, { useState, useMemo, useRef } from 'react' @@ -393,6 +394,7 @@ export const RFFSelectSearch = ({ disabled = false, retainInput = true, isLoading = false, + allowCreate = false, refreshFunction, props, }) => { @@ -433,7 +435,7 @@ export const RFFSelectSearch = ({ )} - {onChange && ( + {!allowCreate && onChange && ( )} + {allowCreate && onChange && ( + + )} + {allowCreate && !onChange && ( + + )} {meta.error && meta.touched && {meta.error}}
) diff --git a/src/views/tenant/administration/GraphExplorer.jsx b/src/views/tenant/administration/GraphExplorer.jsx index 3664f42caed6..8f38821ec387 100644 --- a/src/views/tenant/administration/GraphExplorer.jsx +++ b/src/views/tenant/administration/GraphExplorer.jsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState, useRef } from 'react' +import React, { useEffect, useState, useRef, useMemo } from 'react' import { CAlert, CButton, @@ -31,6 +31,7 @@ import { OnChange } from 'react-final-form-listeners' import { cellGenericFormatter } from 'src/components/tables/CellGenericFormat' import PropTypes from 'prop-types' import { CippCodeOffCanvas, ModalService } from 'src/components/utilities' +import { debounce } from 'lodash-es' const GraphExplorer = () => { const tenant = useSelector((state) => state.app.currentTenant) @@ -39,6 +40,7 @@ const GraphExplorer = () => { const [alertVisible, setAlertVisible] = useState() const [random, setRandom] = useState('') const [random2, setRandom2] = useState('') + const [random3, setRandom3] = useState('') const [ocVisible, setOCVisible] = useState(false) const [searchNow, setSearchNow] = useState(false) const [visibleA, setVisibleA] = useState(true) @@ -49,6 +51,7 @@ const GraphExplorer = () => { } const [execGraphRequest, graphrequest] = useLazyGenericGetRequestQuery() const [execPostRequest, postResults] = useLazyGenericPostRequestQuery() + const [execPropRequest, availableProperties] = useLazyGenericGetRequestQuery() const { data: customPresets = [], isFetching: presetsIsFetching, @@ -56,6 +59,22 @@ const GraphExplorer = () => { } = useGenericGetRequestQuery({ path: '/api/ListGraphExplorerPresets', params: { random2 } }) const QueryColumns = { set: false, data: [] } + function endpointChange(value) { + execPropRequest({ + path: '/api/ListGraphRequest', + params: { + Endpoint: value, + ListProperties: true, + TenantFilter: tenant.defaultDomainName, + IgnoreErrors: true, + random: (Math.random() + 1).toString(36).substring(7), + }, + }) + } + const debounceEndpointChange = useMemo(() => { + return debounce(endpointChange, 1000) + }, [endpointChange]) + if (graphrequest.isSuccess) { if (graphrequest.data?.Results?.length > 0) { //set columns @@ -217,10 +236,15 @@ const GraphExplorer = () => { useEffect(() => { if (params?.endpoint) { + var select = '' + if (params?.$select) { + select = params.$select.map((p) => p.value).join(',') + } execGraphRequest({ path: 'api/ListGraphRequest', params: { ...params, + $select: select, random: random, }, }) @@ -237,15 +261,36 @@ const GraphExplorer = () => { {({ form }) => ( {(value) => { + if (field == 'endpoint') { + debounceEndpointChange(value) + } if (value?.value) { let preset = presets.filter(function (obj) { return obj.id === value.value }) if (preset[0]?.id !== '') { - if (preset[0]?.params[set]) { - onChange(preset[0]?.params[set]) + if (set == 'endpoint') { + debounceEndpointChange(preset[0]?.params[set]) + } + if (set == '$select') { + if (preset[0]?.params[set]) { + var properties = preset[0].params[set].split(',') + var selectedProps = properties.map((prop) => { + return { + label: prop, + value: prop, + } + }) + onChange(selectedProps) + } else { + onChange('') + } } else { - onChange(preset[0][set]) + if (preset[0]?.params[set]) { + onChange(preset[0]?.params[set]) + } else { + onChange(preset[0][set]) + } } } } @@ -263,6 +308,10 @@ const GraphExplorer = () => { function getPresetProps(values) { var newvals = Object.assign({}, values) + console.log(newvals) + if (newvals?.$select !== undefined && Array.isArray(newvals?.$select)) { + newvals.$select = newvals?.$select.map((p) => p.value).join(',') + } delete newvals['reportTemplate'] delete newvals['tenantFilter'] delete newvals['IsShared'] @@ -454,6 +503,7 @@ const GraphExplorer = () => { placeholder="Enter the Graph Endpoint you'd like to run the custom report for." /> + { placeholder="Enter the filter string for the Graph query" /> - +
+ { + return { + name: prop, + value: prop, + } + }) + : [] + } + allowCreate={true} + refreshFunction={() => + setRandom3((Math.random() + 1).toString(36).substring(7)) + } + isLoading={availableProperties.isFetching} + /> +
{
{!searchNow && Execute a search to get started.} + {graphrequest.isFetching && ( +
+ Loading Data +
+ )} {graphrequest.isSuccess && QueryColumns.set && searchNow && ( From 32fb278b23e524b95419bd64cc8312e4454df541 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Sat, 24 Feb 2024 20:59:21 +0100 Subject: [PATCH 28/30] Add filters and reorder table --- src/views/identity/reports/MFAReport.jsx | 30 ++++++++++++++++-------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/src/views/identity/reports/MFAReport.jsx b/src/views/identity/reports/MFAReport.jsx index 5dbae89bb4ad..542bb0d63295 100644 --- a/src/views/identity/reports/MFAReport.jsx +++ b/src/views/identity/reports/MFAReport.jsx @@ -25,12 +25,6 @@ const columns = [ cell: cellBooleanFormatter({ colourless: true }), exportSelector: 'isLicensed', }, - { - selector: (row) => row['PerUser'], - name: 'Per user MFA Status', - sortable: true, - exportSelector: 'PerUser', - }, { selector: (row) => row['MFARegistration'], name: 'Registered for Conditional MFA', @@ -38,6 +32,13 @@ const columns = [ cell: cellBooleanFormatter(), exportSelector: 'MFARegistration', }, + { + selector: (row) => row['CoveredBySD'], + name: 'Enforced via Security Defaults', + sortable: true, + cell: cellBooleanFormatter({ colourless: true }), + exportSelector: 'CoveredBySD', + }, { selector: (row) => row['CoveredByCA'], name: 'Enforced via Conditional Access', @@ -46,11 +47,10 @@ const columns = [ exportSelector: 'CoveredByCA', }, { - selector: (row) => row['CoveredBySD'], - name: 'Enforced via Security Defaults', + selector: (row) => row['PerUser'], + name: 'Per user MFA Status', sortable: true, - cell: cellBooleanFormatter({ colourless: true }), - exportSelector: 'CoveredBySD', + exportSelector: 'PerUser', }, ] @@ -134,7 +134,17 @@ const MFAList = () => { datatable={{ filterlist: [ { filterName: 'Enabled users', filter: '"accountEnabled":true' }, + { filterName: 'No guest users', filter: 'Complex: UPN notlike #EXT#' }, { filterName: 'Licensed users', filter: 'Complex: IsLicensed eq true' }, + { + filterName: 'Enabled, licensed users missing MFA', + filter: + 'Complex: UPN notlike #EXT#; IsLicensed eq true; accountEnabled eq true; MFARegistration eq false', + }, + { + filterName: 'No MFA methods registered', + filter: 'Complex: MFARegistration eq false', + }, ], columns: tenant.defaultDomainName === 'AllTenants' ? Altcolumns : columns, path: '/api/ListMFAUsers', From dd548f5ce84cc898d37f19d4b3a21422778d034d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Sat, 24 Feb 2024 21:26:30 +0100 Subject: [PATCH 29/30] guest name change --- src/views/identity/reports/MFAReport.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/views/identity/reports/MFAReport.jsx b/src/views/identity/reports/MFAReport.jsx index 542bb0d63295..70ece62c2b4e 100644 --- a/src/views/identity/reports/MFAReport.jsx +++ b/src/views/identity/reports/MFAReport.jsx @@ -134,10 +134,10 @@ const MFAList = () => { datatable={{ filterlist: [ { filterName: 'Enabled users', filter: '"accountEnabled":true' }, - { filterName: 'No guest users', filter: 'Complex: UPN notlike #EXT#' }, + { filterName: 'Non-guest users', filter: 'Complex: UPN notlike #EXT#' }, { filterName: 'Licensed users', filter: 'Complex: IsLicensed eq true' }, { - filterName: 'Enabled, licensed users missing MFA', + filterName: 'Enabled, licensed non-guest users missing MFA', filter: 'Complex: UPN notlike #EXT#; IsLicensed eq true; accountEnabled eq true; MFARegistration eq false', }, From 992b5b52267075bb31819adabc6f0f97412a1054 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Mon, 26 Feb 2024 15:36:02 +0100 Subject: [PATCH 30/30] version up --- public/version_latest.txt | 2 +- version_latest.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/public/version_latest.txt b/public/version_latest.txt index 7cbea073bea1..804440660c71 100644 --- a/public/version_latest.txt +++ b/public/version_latest.txt @@ -1 +1 @@ -5.2.0 \ No newline at end of file +5.2.1 \ No newline at end of file diff --git a/version_latest.txt b/version_latest.txt index 7cbea073bea1..804440660c71 100644 --- a/version_latest.txt +++ b/version_latest.txt @@ -1 +1 @@ -5.2.0 \ No newline at end of file +5.2.1 \ No newline at end of file