From 0ef6c461aa128dbd3748b7277dc1e3d545e03d28 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Tue, 7 Mar 2023 17:05:30 +0100 Subject: [PATCH 001/124] fixed issue with spoofwarn --- 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 275483c45999..f60b586ccd78 100644 --- a/src/data/standards.json +++ b/src/data/standards.json @@ -230,14 +230,14 @@ "label": "Enable Auto-expanding archives" }, { - "name": "standards.SpoofWarn.Enable", + "name": "standards.SpoofWarn.enable", "cat": "Exchange", "helpText": "This is the default helptext", "addedComponent": null, "label": "Enable Spoofing warnings for Outlook (This e-mail is external identifiers)" }, { - "name": "standards.SpoofWarn.Disable", + "name": "standards.SpoofWarn.disable", "cat": "Exchange", "helpText": "This is the default helptext", "addedComponent": null, From c53446454c84edca9431252a0b4365f743577973 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Wed, 8 Mar 2023 12:41:57 +0100 Subject: [PATCH 002/124] added option to allow users to set tenantlist. --- src/components/utilities/CippProfile.js | 6 +++ .../utilities/TenantListSelector.js | 37 +++++++++++++++++++ src/store/features/app.js | 5 +++ src/views/tenant/administration/Tenants.js | 3 +- 4 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 src/components/utilities/TenantListSelector.js diff --git a/src/components/utilities/CippProfile.js b/src/components/utilities/CippProfile.js index 526855ab19e6..977370f3a2eb 100644 --- a/src/components/utilities/CippProfile.js +++ b/src/components/utilities/CippProfile.js @@ -12,6 +12,7 @@ import { import { useLoadClientPrincipalQuery } from 'src/store/api/auth' import { ThemeSwitcher, UsageLocation, PageSizeSwitcher } from 'src/components/utilities' import ReportImage from './ReportImage' +import TenantListSelector from './TenantListSelector' const CippProfile = () => { const { data: profile, isFetching, isLoading } = useLoadClientPrincipalQuery() @@ -52,6 +53,11 @@ const CippProfile = () => { + + + + +

diff --git a/src/components/utilities/TenantListSelector.js b/src/components/utilities/TenantListSelector.js new file mode 100644 index 000000000000..94eba4c0bfdc --- /dev/null +++ b/src/components/utilities/TenantListSelector.js @@ -0,0 +1,37 @@ +import React from 'react' +import { CButtonGroup, CButton, CCard, CCardHeader } from '@coreui/react' +import { useDispatch, useSelector } from 'react-redux' +import { setTenantList } from 'src/store/features/app' + +const TenantListSelector = () => { + const dispatch = useDispatch() + const TenantListSelector = useSelector((state) => state.app.TenantListSelector) + + const SwitchPageSize = (value) => { + dispatch(setTenantList({ TenantListSelector: value })) + } + + return ( + + Select default Tenant List + + SwitchPageSize(true)} + active={TenantListSelector ? true : false} + color="secondary" + > + Compressed + + SwitchPageSize(false)} + active={TenantListSelector ? false : true} + color="secondary" + > + Full list + + + + ) +} + +export default TenantListSelector diff --git a/src/store/features/app.js b/src/store/features/app.js index e4e1124d818d..8fcfea652c71 100644 --- a/src/store/features/app.js +++ b/src/store/features/app.js @@ -10,6 +10,7 @@ const initialState = { currentTheme: 'default', tablePageSize: 25, pageSizes: [25, 50, 100, 200, 500], + TenantListSelector: false, } export const appSlice = createSlice({ @@ -40,6 +41,9 @@ export const appSlice = createSlice({ setReportImage: (state, action) => { state.reportImage = action.payload?.reportImage }, + setTenantList: (state, action) => { + state.TenantListSelector = action.payload?.TenantListSelector + }, }, }) @@ -47,6 +51,7 @@ export const { toggleSidebarShow, toggleSidebarUnfoldable, setCurrentTenant, + setTenantList, setCurrentPageSize, setCurrentTheme, setSidebarVisible, diff --git a/src/views/tenant/administration/Tenants.js b/src/views/tenant/administration/Tenants.js index 98f74a9ba4f6..ef2ccef56a2d 100644 --- a/src/views/tenant/administration/Tenants.js +++ b/src/views/tenant/administration/Tenants.js @@ -167,8 +167,9 @@ function StatusText(graphErrorCount, lastGraphError) { } const TenantsList = () => { + const TenantListSelector = useSelector((state) => state.app.TenantListSelector) const tenant = useSelector((state) => state.app.currentTenant) - const [columnOmits, setOmitVisible] = useState(true) + const [columnOmits, setOmitVisible] = useState(TenantListSelector) const columns = [ { From f86fa07f9675e5ce1eef54450246cab2cae1dadf Mon Sep 17 00:00:00 2001 From: BNWEIN Date: Wed, 8 Mar 2023 14:43:50 +0000 Subject: [PATCH 003/124] Update Devices.js Added ability to rename an Intune device. --- src/views/endpoint/intune/Devices.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/views/endpoint/intune/Devices.js b/src/views/endpoint/intune/Devices.js index 00ef4cabdb4f..7d618378a044 100644 --- a/src/views/endpoint/intune/Devices.js +++ b/src/views/endpoint/intune/Devices.js @@ -84,6 +84,15 @@ const Offcanvas = (row, rowIndex, formatExtraData) => { modalUrl: `/api/ExecDeviceAction?TenantFilter=${tenant.defaultDomainName}&GUID=${row.id}&Action=CreateDeviceLogCollectionRequest`, modalMessage: 'Are you sure you want to generate logs and ship these to MEM?', }, + { + label: 'Rename device', + color: 'info', + modal: true, + modalType: 'POST', + modalInput: true, + modalUrl: `/api/ExecDeviceAction?TenantFilter=${tenant.defaultDomainName}&GUID=${row.id}&Action=setDeviceName`, + modalMessage: 'Enter the new name for the device', + }, { label: 'Fresh Start (Remove user data)', color: 'danger', From 3721371c5661d0855942ba14d42cd9e8bf2d964a Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Mon, 13 Mar 2023 15:34:46 +0100 Subject: [PATCH 004/124] added quota management --- .../administration/MailboxesList.js | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/src/views/email-exchange/administration/MailboxesList.js b/src/views/email-exchange/administration/MailboxesList.js index 92d3b7d82c91..3a25cf78eea2 100644 --- a/src/views/email-exchange/administration/MailboxesList.js +++ b/src/views/email-exchange/administration/MailboxesList.js @@ -111,6 +111,48 @@ const MailboxList = () => { modalMessage: 'Are you sure you want to unhide this mailbox from the global address list? Remember this will not work if the user is AD Synched.', }, + { + label: 'Set Send Quota', + color: 'info', + modal: true, + modalType: 'POST', + modalBody: { + user: row.UPN, + TenantFilter: tenant.defaultDomainName, + ProhibitSendQuota: true, + }, + modalUrl: `/api/ExecSetMailboxQuota`, + modalInput: true, + modalMessage: 'Enter a quota. e.g. 1000MB, 10GB,1TB', + }, + { + label: 'Set Send and Receive Quota', + color: 'info', + modal: true, + modalType: 'POST', + modalBody: { + user: row.UPN, + TenantFilter: tenant.defaultDomainName, + ProhibitSendReceiveQuota: true, + }, + modalUrl: `/api/ExecSetMailboxQuota`, + modalInput: true, + modalMessage: 'Enter a quota. e.g. 1000MB, 10GB,1TB', + }, + { + label: 'Set Quota Warning Level', + color: 'info', + modal: true, + modalType: 'POST', + modalBody: { + user: row.UPN, + TenantFilter: tenant.defaultDomainName, + IssueWarningQuota: true, + }, + modalUrl: `/api/ExecSetMailboxQuota`, + modalInput: true, + modalMessage: 'Enter a quota. e.g. 1000MB, 10GB,1TB', + }, ]} placement="end" visible={ocVisible} From 15afc7a4c66006b4369843993f81dc2d2db8af56 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Tue, 14 Mar 2023 00:05:54 +0100 Subject: [PATCH 005/124] added relationship type clarification --- src/views/cipp/CIPPSettings.js | 36 +++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/src/views/cipp/CIPPSettings.js b/src/views/cipp/CIPPSettings.js index dcef6907343f..85280ec9b86d 100644 --- a/src/views/cipp/CIPPSettings.js +++ b/src/views/cipp/CIPPSettings.js @@ -48,7 +48,13 @@ import { import { useListTenantsQuery } from 'src/store/api/tenants' import { useLazyEditDnsConfigQuery, useLazyGetDnsConfigQuery } from 'src/store/api/domains' import { useDispatch, useSelector } from 'react-redux' -import { cellBooleanFormatter, CellTip, CellTipIcon, CippTable } from 'src/components/tables' +import { + CellBadge, + cellBooleanFormatter, + CellTip, + CellTipIcon, + CippTable, +} from 'src/components/tables' import { CippPage, CippPageList } from 'src/components/layout' import { RFFCFormSwitch, @@ -641,6 +647,34 @@ const ExcludedTenantsSettings = () => { cell: (row) => CellTip(row['defaultDomainName']), exportSelector: 'defaultDomainName', }, + { + name: 'Relationship Type', + selector: (row) => row['delegatedPrivilegeStatus'], + sortable: true, + cell: (row, index, column) => { + const cell = column.selector(row) + console.log('here') + console.log(cell) + + if (!cell) { + return + } + if (cell.toLowerCase() == 'none') { + return + } + if (cell === 'delegatedAdminPrivileges') { + return + } + if (cell === 'delegatedAndGranularDelegetedAdminPrivileges') { + return + } + if (cell === 'GranularDelegetedAdminPrivileges') { + return + } + return + }, + exportSelector: 'delegatedPrivilegeStatus', + }, { name: 'Excluded', selector: (row) => row['Excluded'], From a21392dd7ab8ba93f8c6400e84977e37c4661edb Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Tue, 14 Mar 2023 00:08:28 +0100 Subject: [PATCH 006/124] removed console logging commands --- src/views/cipp/CIPPSettings.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/views/cipp/CIPPSettings.js b/src/views/cipp/CIPPSettings.js index 85280ec9b86d..d78797e6465c 100644 --- a/src/views/cipp/CIPPSettings.js +++ b/src/views/cipp/CIPPSettings.js @@ -653,9 +653,6 @@ const ExcludedTenantsSettings = () => { sortable: true, cell: (row, index, column) => { const cell = column.selector(row) - console.log('here') - console.log(cell) - if (!cell) { return } From f909dc865c337f0c7be1943c51581f6379594e19 Mon Sep 17 00:00:00 2001 From: BNWEIN Date: Tue, 14 Mar 2023 10:51:06 +0000 Subject: [PATCH 007/124] Added ability to delete a group Added ability to delete a group --- src/views/identity/administration/Groups.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/views/identity/administration/Groups.js b/src/views/identity/administration/Groups.js index de43dac23eec..5b5a7577a11d 100644 --- a/src/views/identity/administration/Groups.js +++ b/src/views/identity/administration/Groups.js @@ -70,6 +70,13 @@ const Offcanvas = (row, rowIndex, formatExtraData) => { modalMessage: 'Are you sure you want to allow messages from people inside and outside the organisation? Remember this will not work if the group is AD Synched.', }, + { + label: 'Delete Group', + color: 'warning', + modal: true, + modalUrl: `/api/ExecGroupsDelete?TenantFilter=${tenant.defaultDomainName}&ID=${row.id}&GroupType=${row.calculatedGroupType}&DisplayName=${row.displayName}`, + modalMessage: 'Are you sure you want to delete this group.', + }, ]} placement="end" visible={ocVisible} From 1fc741f83907ec94e5b6a9847066064fdd229d97 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Tue, 14 Mar 2023 21:24:45 +0100 Subject: [PATCH 008/124] add DKIM standards --- src/data/standards.json | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/data/standards.json b/src/data/standards.json index f60b586ccd78..999ffad10167 100644 --- a/src/data/standards.json +++ b/src/data/standards.json @@ -250,6 +250,20 @@ "addedComponent": null, "label": "Disable daily Insight/Viva reports" }, + { + "name": "standards.RotateDKIM", + "cat": "Exchange", + "helpText": "Rotate DKIM keys that are 1024 to 2048", + "addedComponent": null, + "label": "Rotate DKIM keys that are 1024 to 2048" + }, + { + "name": "standards.AddDKIM", + "cat": "Exchange", + "helpText": "Enables DKIM for all domains that currently support it", + "addedComponent": null, + "label": "Enables DKIM for all domains that currently support it" + }, { "name": "standards.ActivityBasedTimeout", "cat": "SharePoint", From 10b1efadbdfd82164aa0d2e64a9ad50ffd8ddfc4 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Tue, 14 Mar 2023 21:50:03 +0100 Subject: [PATCH 009/124] updated standards --- 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 999ffad10167..72b083fb4aaa 100644 --- a/src/data/standards.json +++ b/src/data/standards.json @@ -253,9 +253,9 @@ { "name": "standards.RotateDKIM", "cat": "Exchange", - "helpText": "Rotate DKIM keys that are 1024 to 2048", + "helpText": "Rotate DKIM keys that are 1024 bit to 2048 bit", "addedComponent": null, - "label": "Rotate DKIM keys that are 1024 to 2048" + "label": "Rotate DKIM keys that are 1024 bit to 2048 bit" }, { "name": "standards.AddDKIM", From b1207c0959bed8ff216afacd285f23f40dcc0446 Mon Sep 17 00:00:00 2001 From: BNWEIN Date: Wed, 15 Mar 2023 09:13:44 +0000 Subject: [PATCH 010/124] Update ServiceHealth.js Added Celltip to description as you could not read it all --- src/views/tenant/administration/ServiceHealth.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/views/tenant/administration/ServiceHealth.js b/src/views/tenant/administration/ServiceHealth.js index 492bbf7ebbdb..30d3a5e0199c 100644 --- a/src/views/tenant/administration/ServiceHealth.js +++ b/src/views/tenant/administration/ServiceHealth.js @@ -1,5 +1,6 @@ import React from 'react' import { CippPageList } from 'src/components/layout' +import { CellTip } from 'src/components/tables' const columns = [ { @@ -30,6 +31,7 @@ const columns = [ name: 'Description', selector: (row) => row['desc'], sortable: true, + cell: (row) => CellTip(row['desc']), exportSelector: 'desc', }, ] From 89188aeaae1ec928131e7c404b138c9d9bf59079 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Wed, 15 Mar 2023 19:17:38 +0100 Subject: [PATCH 011/124] enabled sending of body content --- src/components/tables/CippTable.js | 73 +++++++++++++++++----- src/views/identity/administration/Users.js | 63 +++++++++++++------ 2 files changed, 102 insertions(+), 34 deletions(-) diff --git a/src/components/tables/CippTable.js b/src/components/tables/CippTable.js index 67f025369f71..099165542d9a 100644 --- a/src/components/tables/CippTable.js +++ b/src/components/tables/CippTable.js @@ -1,4 +1,4 @@ -import React from 'react' +import React, { useRef } from 'react' import { useSelector } from 'react-redux' import { ExportCsvButton, ExportPDFButton } from 'src/components/buttons' import { @@ -124,6 +124,9 @@ export default function CippTable({ ...rest } = {}, }) { + const inputRef = useRef('') + const [loopRunning, setLoopRunning] = React.useState(false) + const [massResults, setMassResults] = React.useState([]) const [filterText, setFilterText] = React.useState('') const [updatedColumns, setUpdatedColumns] = React.useState(columns) const [selectedRows, setSelectedRows] = React.useState(false) @@ -205,11 +208,23 @@ export default function CippTable({ ), title: 'Confirm', - onConfirm: () => - selectedRows.forEach(function (number) { - console.log(number) - genericGetRequest({ path: modalUrl, refreshParam: number }) - }), + onConfirm: async () => { + const resultsarr = [] + for (const row of selectedRows) { + setLoopRunning(true) + const urlParams = new URLSearchParams(modalUrl.split('?')[1]) + for (let [paramName, paramValue] of urlParams.entries()) { + if (paramValue.includes('!')) { + urlParams.set(paramName, row[paramValue.replace('!', '')]) + } + } + const NewModalUrl = `${modalUrl.split('?')[0]}?${urlParams.toString()}` + const results = await genericGetRequest({ path: NewModalUrl, refreshParam: row.id }) + resultsarr.push(results) + setMassResults(resultsarr) + } + setLoopRunning(false) + }, }) } else { ModalService.confirm({ @@ -224,17 +239,35 @@ export default function CippTable({ ), title: 'Confirm', - onConfirm: () => [ - genericPostRequest({ - path: modalUrl, - values: { ...modalBody, ...{ input: inputRef.current.value } }, - }), - ], + onConfirm: async () => { + const resultsarr = [] + for (const row of selectedRows) { + setLoopRunning(true) + const urlParams = new URLSearchParams(modalUrl.split('?')[1]) + for (let [paramName, paramValue] of urlParams.entries()) { + if (paramValue.includes('!')) { + urlParams.set(paramName, row[paramValue.replace('!', '')]) + } + } + for (let [objName, objValue] of Object.entries(modalBody)) { + if (objValue.includes('!')) { + modalBody[objName] = row[objValue.replace('!', '')] + } + } + const NewModalUrl = `${modalUrl.split('?')[0]}?${urlParams.toString()}` + const results = await genericPostRequest({ + path: NewModalUrl, + values: { ...modalBody, ...{ input: inputRef.current.value } }, + }) + resultsarr.push(results) + setMassResults(resultsarr) + } + setLoopRunning(false) + }, }) } } const executeselectedAction = (item) => { - console.log(item) handleModal(item.modalMessage, item.modalUrl, item.modalType, item.modalBody, item.modalInput) } const defaultActions = [] @@ -393,6 +426,18 @@ export default function CippTable({
{(columns.length === updatedColumns.length || !dynamicColumns) && ( <> + {(massResults.length >= 1 || loopRunning) && ( + + {massResults.map((message, idx) => { + return
  • {message.data.Results}
  • + })} + {loopRunning && ( +
  • + +
  • + )} +
    + )} {selectedRows.length >= 1 && ( - Selected {selectedRows.length} items + Selected {selectedRows.length} items )} )} diff --git a/src/views/identity/administration/Users.js b/src/views/identity/administration/Users.js index 87d745a824d4..79096a1550e5 100644 --- a/src/views/identity/administration/Users.js +++ b/src/views/identity/administration/Users.js @@ -260,7 +260,7 @@ const columns = [ }, ] -const Users = () => { +const Users = (row) => { const tenant = useSelector((state) => state.app.currentTenant) const titleButton = return ( @@ -282,54 +282,77 @@ const Users = () => { reportName: `${tenant?.defaultDomainName}-Users`, params: { TenantFilter: tenant?.defaultDomainName }, tableProps: { - selectableRows: false, + selectableRows: true, actionsList: [ { label: 'Convert to Shared Mailbox', modal: true, - modalUrl: `/api/ExecConvertToSharedMailbox?TenantFilter=${tenant.defaultDomainName}&ID=`, - modalMessage: 'Are you sure you want to convert this user to a shared mailbox?', + modalUrl: `/api/ExecConvertToSharedMailbox?TenantFilter=${tenant.defaultDomainName}&ID=!userPrincipalName`, + modalMessage: 'Are you sure you want to convert these users to a shared mailbox?', }, { label: 'Rerequire MFA registration', modal: true, - modalUrl: `/api/ExecResetMFA?TenantFilter=${tenant.defaultDomainName}&ID=`, - modalMessage: 'Are you sure you want to enable MFA for this user?', + modalUrl: `/api/ExecResetMFA?TenantFilter=${tenant.defaultDomainName}&ID=!id`, + modalMessage: 'Are you sure you want to enable MFA for these users?', }, { label: 'Enable Online Archive', color: 'info', modal: true, - modalUrl: `/api/ExecEnableArchive?TenantFilter=${tenant.defaultDomainName}&ID=`, - modalMessage: 'Are you sure you want to enable the online archive for this user?', + modalUrl: `/api/ExecEnableArchive?TenantFilter=${tenant.defaultDomainName}&ID=!id`, + modalMessage: 'Are you sure you want to enable the online archive for these users?', }, { - label: 'Add to group', + label: 'Reset Password (Must Change)', color: 'info', modal: true, - modalUrl: `/api/ExecEnableArchive?TenantFilter=${tenant.defaultDomainName}&ID=`, - modalMessage: 'Are you sure you want to enable the online archive for this user?', + modalUrl: `/api/ExecResetPass?MustChange=true&TenantFilter=${tenant.defaultDomainName}&ID=!userPrincipalName`, + modalMessage: + 'Are you sure you want to reset the password for these users? The users must change their password at next logon.', }, { - label: 'Remove from group', + label: 'Reset Password', color: 'info', modal: true, - modalUrl: `/api/ExecEnableArchive?TenantFilter=${tenant.defaultDomainName}&ID=`, - modalMessage: 'Are you sure you want to enable the online archive for this user?', + modalUrl: `/api/ExecResetPass?MustChange=false&TenantFilter=${tenant.defaultDomainName}&ID=!userPrincipalName`, + modalMessage: + 'Are you sure you want to reset the password for these users? The users must change their password at next logon.', }, { - label: 'Add to Shared Mailbox', + label: 'Block signin', color: 'info', modal: true, - modalUrl: `/api/ExecEnableArchive?TenantFilter=${tenant.defaultDomainName}&ID=`, - modalMessage: 'Are you sure you want to enable the online archive for this user?', + modalUrl: `/api/ExecDisableUser?TenantFilter=${tenant.defaultDomainName}&ID=!userPrincipalName`, + modalMessage: 'Are you sure you want to disable these users?', }, { - label: 'Remove from shared mailbox', + label: 'Unblock signin', color: 'info', modal: true, - modalUrl: `/api/ExecEnableArchive?TenantFilter=${tenant.defaultDomainName}&ID=`, - modalMessage: 'Are you sure you want to enable the online archive for this user?', + modalUrl: `/api/ExecDisableUser?Enable=true&TenantFilter=${tenant.defaultDomainName}&ID=!userPrincipalName`, + modalMessage: 'Are you sure you want to enable these users?', + }, + { + label: 'Revoke sessions', + color: 'info', + modal: true, + modalUrl: `/api/ExecRevokeSessions?Enable=true&TenantFilter=${tenant.defaultDomainName}&ID=!userPrincipalName`, + modalMessage: 'Are you sure you want to revoke all sessions for these users?', + }, + { + label: 'Set Out of Office', + color: 'info', + modal: true, + modalType: 'POST', + modalBody: { + user: '!userPrincipalName', + TenantFilter: tenant.defaultDomainName, + }, + modalUrl: `/api/ExecSetOoO`, + modalInput: true, + modalMessage: + 'Enter a out of office message and press continue to set the out of office.', }, ], }, From 32e7863a5df452541f82b860c52e0583f58d4bfb Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Wed, 15 Mar 2023 19:50:47 +0100 Subject: [PATCH 012/124] added actions to users --- src/components/tables/CippTable.js | 7 +++-- src/views/identity/administration/Users.js | 32 ++++++++++++++++++++++ 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/src/components/tables/CippTable.js b/src/components/tables/CippTable.js index 099165542d9a..c8a9ee543fdd 100644 --- a/src/components/tables/CippTable.js +++ b/src/components/tables/CippTable.js @@ -214,7 +214,7 @@ export default function CippTable({ setLoopRunning(true) const urlParams = new URLSearchParams(modalUrl.split('?')[1]) for (let [paramName, paramValue] of urlParams.entries()) { - if (paramValue.includes('!')) { + if (paramValue.startsWith('!')) { urlParams.set(paramName, row[paramValue.replace('!', '')]) } } @@ -245,12 +245,13 @@ export default function CippTable({ setLoopRunning(true) const urlParams = new URLSearchParams(modalUrl.split('?')[1]) for (let [paramName, paramValue] of urlParams.entries()) { - if (paramValue.includes('!')) { + if (paramValue.toString().startsWith('!')) { urlParams.set(paramName, row[paramValue.replace('!', '')]) } } for (let [objName, objValue] of Object.entries(modalBody)) { - if (objValue.includes('!')) { + console.log(objValue) + if (objValue.toString().startsWith('!')) { modalBody[objName] = row[objValue.replace('!', '')] } } diff --git a/src/views/identity/administration/Users.js b/src/views/identity/administration/Users.js index 79096a1550e5..7df07ee6de0f 100644 --- a/src/views/identity/administration/Users.js +++ b/src/views/identity/administration/Users.js @@ -354,6 +354,38 @@ const Users = (row) => { modalMessage: 'Enter a out of office message and press continue to set the out of office.', }, + { + label: 'Disable Out of Office', + color: 'info', + modal: true, + modalType: 'POST', + modalBody: { + user: '!userPrincipalName', + TenantFilter: tenant.defaultDomainName, + Disable: true, + }, + modalUrl: `/api/ExecSetOoO`, + modalMessage: 'Are you sure you want to disable the out of office?', + }, + { + label: 'Disable Email Forwarding', + color: 'info', + modal: true, + modalType: 'POST', + modalBody: { + user: '!userPrincipalName', + TenantFilter: tenant.defaultDomainName, + }, + modalUrl: `/api/ExecDisableEmailForward`, + modalMessage: 'Are you sure you want to disable forwarding of these users emails?', + }, + { + label: 'Delete User', + color: 'danger', + modal: true, + modalUrl: `/api/RemoveUser?TenantFilter=${tenant.defaultDomainName}&ID=!id`, + modalMessage: 'Are you sure you want to delete these users?', + }, ], }, }} From 87833b819ef89d6bb0e5f56d853e3192f99474e4 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Wed, 15 Mar 2023 20:06:16 +0100 Subject: [PATCH 013/124] groups mass actions --- src/views/identity/administration/Groups.js | 44 +++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/src/views/identity/administration/Groups.js b/src/views/identity/administration/Groups.js index 5b5a7577a11d..49400c7206d9 100644 --- a/src/views/identity/administration/Groups.js +++ b/src/views/identity/administration/Groups.js @@ -154,6 +154,50 @@ const Groups = () => { reportName: `${tenant?.defaultDomainName}-Groups`, path: '/api/ListGroups', params: { TenantFilter: tenant?.defaultDomainName }, + tableProps: { + selectableRows: true, + actionsList: [ + { + label: 'Hide from Global Address List', + color: 'info', + modal: true, + modalUrl: `/api/ExecGroupsHideFromGAL?TenantFilter=${tenant.defaultDomainName}&ID=!mail&GroupType=!calculatedGroupType&HidefromGAL=true`, + modalMessage: + 'Are you sure you want to hide this mailbox from the global address list? Remember this will not work if the group is AD Synched.', + }, + { + label: 'Unhide from Global Address List', + color: 'info', + modal: true, + modalUrl: `/api/ExecGroupsHideFromGAL?TenantFilter=${tenant.defaultDomainName}&ID=!mail&GroupType=!calculatedGroupType`, + modalMessage: + 'Are you sure you want to unhide this mailbox from the global address list? Remember this will not work if the group is AD Synched.', + }, + { + label: 'Only allow messages from people inside the organisation', + color: 'info', + modal: true, + modalUrl: `/api/ExecGroupsDeliveryManagement?TenantFilter=${tenant.defaultDomainName}&ID=!mail&GroupType=!calculatedGroupType&OnlyAllowInternal=true`, + modalMessage: + 'Are you sure you want to only allow messages from people inside the organisation? Remember this will not work if the group is AD Synched.', + }, + { + label: 'Allow messages from people inside and outside the organisation', + color: 'info', + modal: true, + modalUrl: `/api/ExecGroupsDeliveryManagement?TenantFilter=${tenant.defaultDomainName}&ID=!mail&GroupType=!calculatedGroupType`, + modalMessage: + 'Are you sure you want to allow messages from people inside and outside the organisation? Remember this will not work if the group is AD Synched.', + }, + { + label: 'Delete Group', + color: 'warning', + modal: true, + modalUrl: `/api/ExecGroupsDelete?TenantFilter=${tenant.defaultDomainName}&ID=!mail&GroupType=!calculatedGroupType&DisplayName=!displayName`, + modalMessage: 'Are you sure you want to delete this group.', + }, + ], + }, columns, filterlist: [ { From e4e7c472f3164d764c82e2975fee45156bedd321 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Wed, 15 Mar 2023 22:04:34 +0100 Subject: [PATCH 014/124] added password generator options --- src/views/cipp/CIPPSettings.js | 59 ++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/src/views/cipp/CIPPSettings.js b/src/views/cipp/CIPPSettings.js index d78797e6465c..ffa5f765e85e 100644 --- a/src/views/cipp/CIPPSettings.js +++ b/src/views/cipp/CIPPSettings.js @@ -21,6 +21,7 @@ import { CSpinner, } from '@coreui/react' import { + useGenericGetRequestQuery, useLazyExecClearCacheQuery, useLazyExecNotificationConfigQuery, useLazyExecPermissionsAccessCheckQuery, @@ -503,6 +504,9 @@ const GeneralSettings = () => { + + +
    ) @@ -1098,6 +1102,61 @@ const LicenseSettings = () => { ) } +const PasswordSettings = () => { + const [getPasswordConfig, getPasswordConfigResult] = useLazyGenericGetRequestQuery() + const [editPasswordConfig, editPasswordConfigResult] = useLazyGenericPostRequestQuery() + + const [passAlertVisible, setPassAlertVisible] = useState(false) + + const switchResolver = (resolver) => { + editPasswordConfig({ path: '/api/ExecPasswordconfig', values: { passwordType: resolver } }) + getPasswordConfig() + setPassAlertVisible(true) + } + + const resolvers = ['Classic', 'Correct-Battery-Horse'] + + return ( + <> + {getPasswordConfigResult.isUninitialized && + getPasswordConfig({ path: '/api/ExecPasswordConfig?list=true' })} + + + Password Generation + + + Select a password style for generated passwords. + + {resolvers.map((r, index) => ( + switchResolver(r)} + color={ + r === getPasswordConfigResult.data?.Results?.passwordType + ? 'primary' + : 'secondary' + } + key={index} + > + {r} + + ))} + + {(editPasswordConfigResult.isSuccess || editPasswordConfigResult.isError) && ( + + {editPasswordConfigResult.isSuccess + ? editPasswordConfigResult.data.Results + : 'Error setting password style'} + + )} + + + + ) +} + const DNSSettings = () => { const [getDnsConfig, getDnsConfigResult] = useLazyGetDnsConfigQuery() const [editDnsConfig, editDnsConfigResult] = useLazyEditDnsConfigQuery() From bdaa90808409b73ed324b3c0007545a394af3789 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Wed, 15 Mar 2023 22:53:10 +0100 Subject: [PATCH 015/124] Add mass actions tenant exclusions --- src/views/cipp/CIPPSettings.js | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/views/cipp/CIPPSettings.js b/src/views/cipp/CIPPSettings.js index ffa5f765e85e..197bc742140c 100644 --- a/src/views/cipp/CIPPSettings.js +++ b/src/views/cipp/CIPPSettings.js @@ -737,6 +737,34 @@ const ExcludedTenantsSettings = () => { tenantSelector={false} titleButton={titleButton} datatable={{ + tableProps: { + selectableRows: true, + actionsList: [ + { + label: 'Exclude Tenants', + modal: true, + modalType: 'POST', + modalBody: { + value: '!customerId', + }, + modalUrl: `/api/ExecExcludeTenant?AddExclusion=true`, + modalMessage: 'Are you sure you want to exclude these tenants?', + }, + { + label: 'Include Tenants', + modal: true, + modalUrl: `/api/ExecExcludeTenant?RemoveExclusion=true&TenantFilter=!defaultDomainName`, + modalMessage: 'Are you sure you want to include these tenants?', + }, + { + label: 'Refresh CPV Permissions', + modal: true, + modalUrl: `/api/ExecCPVPermissions?TenantFilter=!customerId`, + modalMessage: + 'Are you sure you want to refresh the CPV permissions for these tenants?', + }, + ], + }, filterlist: [ { filterName: 'Excluded Tenants', filter: '"Excluded":true' }, { filterName: 'Included Tenants', filter: '"Excluded":false' }, From b6de8cbc74593b6b96bd936631d7915b4aeb9a72 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Wed, 15 Mar 2023 23:33:52 +0100 Subject: [PATCH 016/124] added universal search --- src/components/utilities/UniversalSearch.js | 11 ++++++----- src/views/home/Home.js | 5 +++-- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/components/utilities/UniversalSearch.js b/src/components/utilities/UniversalSearch.js index a99bc5a91830..edc6900e181f 100644 --- a/src/components/utilities/UniversalSearch.js +++ b/src/components/utilities/UniversalSearch.js @@ -18,7 +18,7 @@ export const UniversalSearch = React.forwardRef( const handleKeyDown = (event) => { if (event.key === 'Enter') { // on enter key, start the search - getSearchItems({ path: `/api/ExecUniversalSearch?SearchObj=${searchValue}` }) + getSearchItems({ path: `/api/ExecUniversalSearch?name=${searchValue}` }) } } @@ -28,13 +28,13 @@ export const UniversalSearch = React.forwardRef( - {searchItems.isSuccess && } + {searchItems.isFetching && ( <>
    @@ -48,6 +48,7 @@ export const UniversalSearch = React.forwardRef(
    )} + {searchItems.isSuccess && } ) }, @@ -78,7 +79,7 @@ const ResultsRow = ({ match }) => { const handleClick = () => { dispatch(hideSwitcher()) - navigate(`/identity/administration/users?customerId=${match.customerId}`) + navigate(`/identity/administration/users?customerId=${match._tenantId}`) } return ( @@ -88,7 +89,7 @@ const ResultsRow = ({ match }) => {
    {match.displayName}
    {match.userPrincipalName}
    - Found in tenant {match.defaultDomainName} + Found in tenant {match._tenantId}
    diff --git a/src/views/home/Home.js b/src/views/home/Home.js index 78fb59f988f4..7336e5e5ebfd 100644 --- a/src/views/home/Home.js +++ b/src/views/home/Home.js @@ -8,6 +8,7 @@ import { CippTable } from 'src/components/tables' import { Link } from 'react-router-dom' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import Skeleton from 'react-loading-skeleton' +import { UniversalSearch } from 'src/components/utilities/UniversalSearch' const Home = () => { const { data: versions, isSuccess: isSuccessVersion } = useLoadVersionsQuery() @@ -28,11 +29,11 @@ const Home = () => { <> - + - + From 6f6cb844bff2d8aaea8d03544a368fd2ffc8b929 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Wed, 15 Mar 2023 23:40:56 +0100 Subject: [PATCH 017/124] removed latest status --- src/components/utilities/UniversalSearch.js | 1 + src/views/cipp/CIPPSettings.js | 13 ------------- 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/src/components/utilities/UniversalSearch.js b/src/components/utilities/UniversalSearch.js index edc6900e181f..34733c4e69df 100644 --- a/src/components/utilities/UniversalSearch.js +++ b/src/components/utilities/UniversalSearch.js @@ -49,6 +49,7 @@ export const UniversalSearch = React.forwardRef( )} {searchItems.isSuccess && } + {searchItems.data <= 1 && 'No results found.'} ) }, diff --git a/src/views/cipp/CIPPSettings.js b/src/views/cipp/CIPPSettings.js index 197bc742140c..94e2e17f3897 100644 --- a/src/views/cipp/CIPPSettings.js +++ b/src/views/cipp/CIPPSettings.js @@ -624,19 +624,6 @@ const ExcludedTenantsSettings = () => { ) } const columns = [ - { - name: 'Latest Status', - selector: (row) => row['GraphErrorCount'], - sortable: true, - cell: (row) => - CellTipIcon( - StatusText(row['GraphErrorCount'], row['LastGraphError']), - StatusIcon(row['GraphErrorCount']), - ), - exportSelector: 'GraphErrorCount', - maxWidth: '130px', - minWidth: '130px', - }, { name: 'Name', selector: (row) => row['displayName'], From 05c2e99bf1cfda4083cfa32552539508f692bdf9 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Thu, 16 Mar 2023 00:59:00 +0100 Subject: [PATCH 018/124] changed basic auth to inactive users reports --- src/_nav.js | 4 +- src/routes.js | 4 +- src/views/identity/reports/BasicAuthReport.js | 73 ------------------- src/views/identity/reports/InactiveUsers.js | 61 ++++++++++++++++ 4 files changed, 65 insertions(+), 77 deletions(-) delete mode 100644 src/views/identity/reports/BasicAuthReport.js create mode 100644 src/views/identity/reports/InactiveUsers.js diff --git a/src/_nav.js b/src/_nav.js index 6a8db77a4ceb..3177cc44935d 100644 --- a/src/_nav.js +++ b/src/_nav.js @@ -90,8 +90,8 @@ const _nav = [ }, { component: CNavItem, - name: 'Basic Auth Report', - to: '/identity/reports/basic-auth-report', + name: 'Inactive Users', + to: '/identity/reports/inactive-users-report', }, { component: CNavItem, diff --git a/src/routes.js b/src/routes.js index 6ee996343ab4..61176edabc93 100644 --- a/src/routes.js +++ b/src/routes.js @@ -55,7 +55,7 @@ const DeployConditional = React.lazy(() => import('src/views/tenant/conditional/ const ListLicences = React.lazy(() => import('src/views/tenant/administration/ListLicences')) const ListAppConsent = React.lazy(() => import('src/views/tenant/administration/ListOauthApps')) -const BasicAuthReport = React.lazy(() => import('src/views/identity/reports/BasicAuthReport')) +const BasicAuthReport = React.lazy(() => import('src/views/identity/reports/InactiveUsers')) const SignInReport = React.lazy(() => import('src/views/identity/reports/SignIns')) const AzureADConnectReport = React.lazy(() => @@ -267,7 +267,7 @@ const routes = [ { path: '/endpoint/reports/devices', name: 'Devices', component: Devices }, { path: '/identity/reports/mfa-report', name: 'MFA Report', component: MFAReport }, { - path: '/identity/reports/basic-auth-report', + path: '/identity/reports/inactive-users-report', name: 'Basic Auth Report', component: BasicAuthReport, }, diff --git a/src/views/identity/reports/BasicAuthReport.js b/src/views/identity/reports/BasicAuthReport.js deleted file mode 100644 index d5c56bba3668..000000000000 --- a/src/views/identity/reports/BasicAuthReport.js +++ /dev/null @@ -1,73 +0,0 @@ -import { CLink } from '@coreui/react' -import React from 'react' -import { useSelector } from 'react-redux' -import { CippPageList } from 'src/components/layout' -const columns = [ - { - name: 'User Principal Name', - selector: (row) => row['userPrincipalName'], - sortable: true, - exportSelector: 'userPrincipalName', - }, - { - name: 'Basic Auth', - selector: (row) => row['clientAppUsed'], - sortable: true, - exportSelector: 'clientAppUsed', - }, - { - name: 'Failure Reason', - selector: (row) => row.status?.errorCode, - sortable: true, - exportSelector: 'status', - cell: (row) => { - return ( - - {row.status?.errorCode} - - ) - }, - }, -] - -const Altcolumns = [ - { - name: 'Tenant', - selector: (row) => row['Tenant'], - sortable: true, - exportSelector: 'Tenant', - }, - { - name: 'User Principal Name', - selector: (row) => row['userPrincipalName'], - sortable: true, - exportSelector: 'userPrincipalName', - }, - { - name: 'Basic Auth', - selector: (row) => row['clientAppUsed'], - sortable: true, - exportSelector: 'clientAppUsed', - }, -] -const BasicAuthReport = () => { - const tenant = useSelector((state) => state.app.currentTenant) - - return ( - - ) -} - -export default BasicAuthReport diff --git a/src/views/identity/reports/InactiveUsers.js b/src/views/identity/reports/InactiveUsers.js new file mode 100644 index 000000000000..d9d933c5d35c --- /dev/null +++ b/src/views/identity/reports/InactiveUsers.js @@ -0,0 +1,61 @@ +import { CLink } from '@coreui/react' +import React from 'react' +import { useSelector } from 'react-redux' +import { CippPageList } from 'src/components/layout' + +const Altcolumns = [ + { + name: 'Tenant', + selector: (row) => row['tenantDisplayName'], + sortable: true, + exportSelector: 'tenantDisplayName', + }, + { + name: 'User Principal Name', + selector: (row) => row['userPrincipalName'], + sortable: true, + exportSelector: 'userPrincipalName', + }, + { + name: 'Display Name', + selector: (row) => row['displayName'], + sortable: true, + exportSelector: 'displayName', + }, + { + name: 'Last sign in time', + selector: (row) => row['lastNonInteractiveSignInDateTime'], + sortable: true, + exportSelector: 'lastNonInteractiveSignInDateTime', + }, + { + name: 'Assigned Licenses Count', + selector: (row) => row['numberOfAssignedLicenses'], + sortable: true, + exportSelector: 'numberOfAssignedLicenses', + }, + { + name: 'Last updated at', + selector: (row) => row['lastRefreshedDateTime'], + sortable: true, + exportSelector: 'lastRefreshedDateTime', + }, +] +const BasicAuthReport = () => { + const tenant = useSelector((state) => state.app.currentTenant) + + return ( + + ) +} + +export default BasicAuthReport From 0e1ee07f04445d2f967a4facfdd0a042aa84b491 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Thu, 16 Mar 2023 01:44:30 +0100 Subject: [PATCH 019/124] fix for issues with sending body --- src/components/tables/CippTable.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/components/tables/CippTable.js b/src/components/tables/CippTable.js index c8a9ee543fdd..f941927a01fa 100644 --- a/src/components/tables/CippTable.js +++ b/src/components/tables/CippTable.js @@ -249,16 +249,17 @@ export default function CippTable({ urlParams.set(paramName, row[paramValue.replace('!', '')]) } } + const newModalBody = {} for (let [objName, objValue] of Object.entries(modalBody)) { console.log(objValue) if (objValue.toString().startsWith('!')) { - modalBody[objName] = row[objValue.replace('!', '')] + newModalBody[objName] = row[objValue.replace('!', '')] } } const NewModalUrl = `${modalUrl.split('?')[0]}?${urlParams.toString()}` const results = await genericPostRequest({ path: NewModalUrl, - values: { ...modalBody, ...{ input: inputRef.current.value } }, + values: { ...modalBody, ...newModalBody, ...{ input: inputRef.current.value } }, }) resultsarr.push(results) setMassResults(resultsarr) From e57653f7cacda6f0f714764126aa373f891817ef Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Thu, 16 Mar 2023 22:16:09 +0100 Subject: [PATCH 020/124] Lighthouse name changes --- src/components/utilities/UniversalSearch.js | 2 +- src/views/home/Home.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/utilities/UniversalSearch.js b/src/components/utilities/UniversalSearch.js index 34733c4e69df..0dadbe464659 100644 --- a/src/components/utilities/UniversalSearch.js +++ b/src/components/utilities/UniversalSearch.js @@ -28,7 +28,7 @@ export const UniversalSearch = React.forwardRef( { <> - + From d9c14fd508bb9677143aa108ba7a49f983d83c88 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Thu, 16 Mar 2023 23:12:10 +0100 Subject: [PATCH 021/124] added mass actions --- .../identity/administration/GroupTemplates.js | 12 ++++++ .../tenant/administration/ListAlertsQueue.js | 12 ++++++ .../tenant/conditional/ConditionalAccess.js | 39 ++++++++++++++++++- 3 files changed, 62 insertions(+), 1 deletion(-) diff --git a/src/views/identity/administration/GroupTemplates.js b/src/views/identity/administration/GroupTemplates.js index 2b64aaee906a..67ce049e327c 100644 --- a/src/views/identity/administration/GroupTemplates.js +++ b/src/views/identity/administration/GroupTemplates.js @@ -119,6 +119,18 @@ const GroupTemplates = () => { path: '/api/ListGroupTemplates', params: { TenantFilter: tenant?.defaultDomainName }, columns, + tableProps: { + selectableRows: true, + actionsList: [ + { + label: 'Delete Template', + color: 'info', + modal: true, + modalUrl: `/api/RemoveGroupTemplate?ID=!GUID`, + modalMessage: 'Are you sure you want to delete these templates?', + }, + ], + }, }} /> diff --git a/src/views/tenant/administration/ListAlertsQueue.js b/src/views/tenant/administration/ListAlertsQueue.js index c963d2ffd149..4d6bf2e72e8f 100644 --- a/src/views/tenant/administration/ListAlertsQueue.js +++ b/src/views/tenant/administration/ListAlertsQueue.js @@ -163,6 +163,18 @@ const ListAlertsQueue = () => { reportName: `AlertsQueue-List`, path: '/api/ListAlertsQueue', params: { TenantFilter: tenant?.defaultDomainName }, + tableProps: { + selectableRows: true, + actionsList: [ + { + label: 'Delete Template', + color: 'info', + modal: true, + modalUrl: `/api/RemoveQueuedAlert?ID=!tenantId`, + modalMessage: 'Are you sure you want to delete these templates?', + }, + ], + }, }} /> diff --git a/src/views/tenant/conditional/ConditionalAccess.js b/src/views/tenant/conditional/ConditionalAccess.js index ce4b49a60989..205816829601 100644 --- a/src/views/tenant/conditional/ConditionalAccess.js +++ b/src/views/tenant/conditional/ConditionalAccess.js @@ -75,7 +75,7 @@ const Offcanvas = (row, rowIndex, formatExtraData) => { modal: true, icon: , modalUrl: `/api/RemoveCAPolicy?TenantFilter=${tenant.defaultDomainName}&GUID=${row.id}`, - modalMessage: 'Are you sure you want to disable this rule?', + modalMessage: 'Are you sure you want to delete this rule?', }, ]} placement="end" @@ -223,6 +223,43 @@ const ConditionalAccessList = () => { path: '/api/ListConditionalAccessPolicies', params: { TenantFilter: tenant?.defaultDomainName }, columns, + tableProps: { + selectableRows: true, + actionsList: [ + { + label: 'Enable Rule', + color: 'info', + icon: , + modal: true, + modalUrl: `/api/EditCAPolicy?State=Enabled&TenantFilter=${tenant.defaultDomainName}&GUID=!id`, + modalMessage: 'Are you sure you want to enable this rule?', + }, + { + label: 'Disable Rule', + color: 'info', + icon: , + modal: true, + modalUrl: `/api/EditCAPolicy?State=Disabled&TenantFilter=${tenant.defaultDomainName}&GUID=!id`, + modalMessage: 'Are you sure you want to disable this rule?', + }, + { + label: 'Set rule to report only', + color: 'info', + icon: , + modal: true, + modalUrl: `/api/EditCAPolicy?State=enabledForReportingButNotEnforced&TenantFilter=${tenant.defaultDomainName}&GUID=!id`, + modalMessage: 'Are you sure you want to disable this rule?', + }, + { + label: 'Delete Rule', + color: 'danger', + modal: true, + icon: , + modalUrl: `/api/RemoveCAPolicy?TenantFilter=${tenant.defaultDomainName}&GUID=!id`, + modalMessage: 'Are you sure you want to delete this rule?', + }, + ], + }, }} /> ) From 54461cf477259041a376662f26a569403bec2bbd Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Thu, 16 Mar 2023 23:25:48 +0100 Subject: [PATCH 022/124] added mass actions --- .../administration/MailboxesList.js | 78 +++++++++++++++++++ .../endpoint/applications/ApplicationsList.js | 36 +++++++++ 2 files changed, 114 insertions(+) diff --git a/src/views/email-exchange/administration/MailboxesList.js b/src/views/email-exchange/administration/MailboxesList.js index 3a25cf78eea2..3ccf0b7da802 100644 --- a/src/views/email-exchange/administration/MailboxesList.js +++ b/src/views/email-exchange/administration/MailboxesList.js @@ -230,6 +230,84 @@ const MailboxList = () => { reportName: `${tenant?.defaultDomainName}-Mailbox-List`, path: '/api/ListMailboxes', columns, + tableProps: { + selectableRows: true, + actionsList: [ + { + label: 'Convert to Shared Mailbox', + color: 'info', + modal: true, + modalUrl: `/api/ExecConvertToSharedMailbox?TenantFilter=${tenant.defaultDomainName}&ID=!UPN`, + modalMessage: 'Are you sure you want to convert this user to a shared mailbox?', + }, + { + label: 'Convert to User Mailbox', + color: 'info', + modal: true, + modalUrl: `/api/ExecConvertToSharedMailbox?TenantFilter=${tenant.defaultDomainName}&ID=!UPN&ConvertToUser=true`, + modalMessage: + 'Are you sure you want to convert this shared mailbox to a user mailbox?', + }, + { + label: 'Hide from Global Address List', + color: 'info', + modal: true, + modalUrl: `/api/ExecHideFromGAL?TenantFilter=${tenant.defaultDomainName}&ID=!UPN&HidefromGAL=true`, + modalMessage: + 'Are you sure you want to hide this mailbox from the global address list? Remember this will not work if the user is AD Synched.', + }, + { + label: 'Unhide from Global Address List', + color: 'info', + modal: true, + modalUrl: `/api/ExecHideFromGAL?TenantFilter=${tenant.defaultDomainName}&ID=!UPN`, + modalMessage: + 'Are you sure you want to unhide this mailbox from the global address list? Remember this will not work if the user is AD Synched.', + }, + { + label: 'Set Send Quota', + color: 'info', + modal: true, + modalType: 'POST', + modalBody: { + user: '!UPN', + TenantFilter: tenant.defaultDomainName, + ProhibitSendQuota: true, + }, + modalUrl: `/api/ExecSetMailboxQuota`, + modalInput: true, + modalMessage: 'Enter a quota. e.g. 1000MB, 10GB,1TB', + }, + { + label: 'Set Send and Receive Quota', + color: 'info', + modal: true, + modalType: 'POST', + modalBody: { + user: '!UPN', + TenantFilter: tenant.defaultDomainName, + ProhibitSendReceiveQuota: true, + }, + modalUrl: `/api/ExecSetMailboxQuota`, + modalInput: true, + modalMessage: 'Enter a quota. e.g. 1000MB, 10GB,1TB', + }, + { + label: 'Set Quota Warning Level', + color: 'info', + modal: true, + modalType: 'POST', + modalBody: { + user: '!UPN', + TenantFilter: tenant.defaultDomainName, + IssueWarningQuota: true, + }, + modalUrl: `/api/ExecSetMailboxQuota`, + modalInput: true, + modalMessage: 'Enter a quota. e.g. 1000MB, 10GB,1TB', + }, + ], + }, params: { TenantFilter: tenant?.defaultDomainName }, filterlist: [ { diff --git a/src/views/endpoint/applications/ApplicationsList.js b/src/views/endpoint/applications/ApplicationsList.js index 5d4b1238429f..547f036da607 100644 --- a/src/views/endpoint/applications/ApplicationsList.js +++ b/src/views/endpoint/applications/ApplicationsList.js @@ -134,6 +134,42 @@ const ApplicationsList = () => { reportName: `${tenant?.defaultDomainName}-Applications-List`, path: '/api/ListApps', params: { TenantFilter: tenant?.defaultDomainName }, + tableProps: { + selectableRows: true, + actionsList: [ + { + icon: , + label: ' Assign to All Users', + color: 'info', + modal: true, + modalUrl: `/api/ExecAssignApp?AssignTo=AllUsers&TenantFilter=${tenant.defaultDomainName}&ID=!id`, + modalMessage: `Are you sure you want to assign these apps to all users?`, + }, + { + icon: , + label: ' Assign to All Devices', + color: 'info', + modal: true, + modalUrl: `/api/ExecAssignApp?AssignTo=AllDevices&TenantFilter=${tenant.defaultDomainName}&ID=!id`, + modalMessage: `Are you sure you want to assign these apps to all devices?`, + }, + { + icon: , + label: ' Assign Globally (All Users / All Devices)', + color: 'info', + modal: true, + modalUrl: `/api/ExecAssignApp?AssignTo=Both&TenantFilter=${tenant.defaultDomainName}&ID=!id`, + modalMessage: `Are you sure you want to assign these apps to all users and devices?`, + }, + { + label: 'Delete Application', + color: 'danger', + modal: true, + modalUrl: `/api/RemoveApp?TenantFilter=${tenant.defaultDomainName}&ID=!id`, + modalMessage: 'Are you sure you want to delete this policy?', + }, + ], + }, }} /> ) From 983f5a215599272725ae744b560829fca7e96738 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Fri, 17 Mar 2023 00:13:14 +0100 Subject: [PATCH 023/124] fixes for weird issue with input field --- src/components/utilities/CippProfile.js | 8 ++------ src/components/utilities/UsageLocation.js | 1 - 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/components/utilities/CippProfile.js b/src/components/utilities/CippProfile.js index 977370f3a2eb..e033bc568df9 100644 --- a/src/components/utilities/CippProfile.js +++ b/src/components/utilities/CippProfile.js @@ -60,15 +60,11 @@ const CippProfile = () => {

    - - - + {!isLoading && }

    - - - + {!isLoading && } ) diff --git a/src/components/utilities/UsageLocation.js b/src/components/utilities/UsageLocation.js index 4dd0d4dddcd3..10ac692681ec 100644 --- a/src/components/utilities/UsageLocation.js +++ b/src/components/utilities/UsageLocation.js @@ -9,7 +9,6 @@ const UsageLocation = () => { const dispatch = useDispatch() const usagelocation = useSelector((state) => state.app.usageLocation) const Switchusage = (t, n) => { - // console.log(t) dispatch(setDefaultusageLocation({ usageLocation: t })) } From eecfe9e9135c475c75c23b6c7c64cc2e920180bd Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Fri, 17 Mar 2023 19:24:57 +0100 Subject: [PATCH 024/124] upped version for release. --- 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 a0cd9f0ccb01..a4f52a5dbb5a 100644 --- a/public/version_latest.txt +++ b/public/version_latest.txt @@ -1 +1 @@ -3.1.0 \ No newline at end of file +3.2.0 \ No newline at end of file diff --git a/version_latest.txt b/version_latest.txt index a0cd9f0ccb01..a4f52a5dbb5a 100644 --- a/version_latest.txt +++ b/version_latest.txt @@ -1 +1 @@ -3.1.0 \ No newline at end of file +3.2.0 \ No newline at end of file From e71197f8004c79d2cee2722f42448ba906684e80 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Tue, 21 Mar 2023 13:43:07 +0100 Subject: [PATCH 025/124] Update bug.yml --- .github/ISSUE_TEMPLATE/bug.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml index 0c6b95cbf595..1e0e6afd8faa 100644 --- a/.github/ISSUE_TEMPLATE/bug.yml +++ b/.github/ISSUE_TEMPLATE/bug.yml @@ -31,7 +31,12 @@ body: attributes: label: Environment data description: > - Please let us know your environment information - e.g. hosted version, Azure, local Dev version. + Please let us know your environment information. This must follow this format or the ticket will be closed: + Sponsored / Non-sponsored instance + Front end version number: + Back end version number: + Tried Tenant Cache Clear: true/false + Tried Token Cache Clear: true/false render: PowerShell validations: required: true From 9f9f2b44b932954c924f3fb0385aeb9cabf964eb Mon Sep 17 00:00:00 2001 From: BNWEIN Date: Tue, 21 Mar 2023 15:56:16 +0000 Subject: [PATCH 026/124] Fixed Mailbox List View Fixed Mailbox List View --- src/views/email-exchange/administration/MailboxesList.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/views/email-exchange/administration/MailboxesList.js b/src/views/email-exchange/administration/MailboxesList.js index 3ccf0b7da802..0fc1535160d6 100644 --- a/src/views/email-exchange/administration/MailboxesList.js +++ b/src/views/email-exchange/administration/MailboxesList.js @@ -17,7 +17,7 @@ const MailboxList = () => { return ( <> From 2b9090ccd572cab5dd1ba12d4f8e61f10c66a6b2 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Tue, 21 Mar 2023 19:11:11 +0100 Subject: [PATCH 027/124] version up for hotfix --- version_latest.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version_latest.txt b/version_latest.txt index a4f52a5dbb5a..0444f3207675 100644 --- a/version_latest.txt +++ b/version_latest.txt @@ -1 +1 @@ -3.2.0 \ No newline at end of file +3.2.1 \ No newline at end of file From ee3890695427093f0e9a09d2c138b8f122fe43ff Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Tue, 21 Mar 2023 20:00:34 +0100 Subject: [PATCH 028/124] added filter --- src/views/identity/administration/Users.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/views/identity/administration/Users.js b/src/views/identity/administration/Users.js index 7df07ee6de0f..b086ddee69d4 100644 --- a/src/views/identity/administration/Users.js +++ b/src/views/identity/administration/Users.js @@ -271,6 +271,7 @@ const Users = (row) => { datatable={{ filterlist: [ { filterName: 'Enabled users', filter: '"accountEnabled":true' }, + { filterName: 'Disabled users', filter: '"accountEnabled":false' }, { filterName: 'AAD users', filter: '"onPremisesSyncEnabled":false' }, { filterName: 'Synced users', filter: '"onPremisesSyncEnabled":true' }, { filterName: 'Guest users', filter: '"usertype":"guest"' }, From a3e411e884f7c6bd07fe3a71640ee11f60b5c0de Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Tue, 21 Mar 2023 23:15:42 +0100 Subject: [PATCH 029/124] Update version_latest.txt --- public/version_latest.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/version_latest.txt b/public/version_latest.txt index a4f52a5dbb5a..e4604e3afd0d 100644 --- a/public/version_latest.txt +++ b/public/version_latest.txt @@ -1 +1 @@ -3.2.0 \ No newline at end of file +3.2.1 From 7693782fa71085e8cdb63fc62665efbbac829fcb Mon Sep 17 00:00:00 2001 From: BNWEIN Date: Wed, 22 Mar 2023 12:17:48 +0000 Subject: [PATCH 030/124] Update routes.js Changed Title of page from "Basic Auth Report" to "Inactive User Report" --- src/routes.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes.js b/src/routes.js index 61176edabc93..34165aabe388 100644 --- a/src/routes.js +++ b/src/routes.js @@ -268,7 +268,7 @@ const routes = [ { path: '/identity/reports/mfa-report', name: 'MFA Report', component: MFAReport }, { path: '/identity/reports/inactive-users-report', - name: 'Basic Auth Report', + name: 'Inactive Users Report', component: BasicAuthReport, }, { From b8a08b82b10724f305a16190cd7a491f88a8b982 Mon Sep 17 00:00:00 2001 From: BNWEIN Date: Wed, 22 Mar 2023 12:30:33 +0000 Subject: [PATCH 031/124] Updated "BasicAuthReport" to "InActiveUserReport" Updated "BasicAuthReport" to "InActiveUserReport" --- src/routes.js | 4 ++-- src/views/identity/reports/InactiveUsers.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/routes.js b/src/routes.js index 34165aabe388..a71896e965cf 100644 --- a/src/routes.js +++ b/src/routes.js @@ -55,7 +55,7 @@ const DeployConditional = React.lazy(() => import('src/views/tenant/conditional/ const ListLicences = React.lazy(() => import('src/views/tenant/administration/ListLicences')) const ListAppConsent = React.lazy(() => import('src/views/tenant/administration/ListOauthApps')) -const BasicAuthReport = React.lazy(() => import('src/views/identity/reports/InactiveUsers')) +const InActiveUserReport = React.lazy(() => import('src/views/identity/reports/InactiveUsers')) const SignInReport = React.lazy(() => import('src/views/identity/reports/SignIns')) const AzureADConnectReport = React.lazy(() => @@ -269,7 +269,7 @@ const routes = [ { path: '/identity/reports/inactive-users-report', name: 'Inactive Users Report', - component: BasicAuthReport, + component: InActiveUserReport, }, { path: '/identity/reports/Signin-report', diff --git a/src/views/identity/reports/InactiveUsers.js b/src/views/identity/reports/InactiveUsers.js index d9d933c5d35c..4c64fc18386e 100644 --- a/src/views/identity/reports/InactiveUsers.js +++ b/src/views/identity/reports/InactiveUsers.js @@ -41,7 +41,7 @@ const Altcolumns = [ exportSelector: 'lastRefreshedDateTime', }, ] -const BasicAuthReport = () => { +const InActiveUserReport = () => { const tenant = useSelector((state) => state.app.currentTenant) return ( @@ -58,4 +58,4 @@ const BasicAuthReport = () => { ) } -export default BasicAuthReport +export default InActiveUserReport From 98a80d735203e020f7fd35de493896f92f63cada Mon Sep 17 00:00:00 2001 From: BNWEIN Date: Fri, 24 Mar 2023 11:15:50 +0000 Subject: [PATCH 032/124] Added CopyForSentItems Function Added CopyForSentItems Function and added displayName to output when resetting password --- .../email-exchange/administration/MailboxesList.js | 14 ++++++++++++++ src/views/identity/administration/Users.js | 4 ++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/views/email-exchange/administration/MailboxesList.js b/src/views/email-exchange/administration/MailboxesList.js index 0fc1535160d6..9126ba955d04 100644 --- a/src/views/email-exchange/administration/MailboxesList.js +++ b/src/views/email-exchange/administration/MailboxesList.js @@ -95,6 +95,20 @@ const MailboxList = () => { modalMessage: 'Are you sure you want to convert this shared mailbox to a user mailbox?', }, + { + label: 'Copy Sent Items to Shared Mailbox', + color: 'info', + modal: true, + modalUrl: `/api/ExecCopyForSent?TenantFilter=${tenant.defaultDomainName}&ID=${row.UPN}`, + modalMessage: 'Are you sure you want to enable Copy Sent Items to Shared Mailbox?', + }, + { + label: 'Disable Copy Sent Items to Shared Mailbox', + color: 'info', + modal: true, + modalUrl: `/api/ExecCopyForSent?TenantFilter=${tenant.defaultDomainName}&ID=${row.UPN}&MessageCopyForSentAsEnabled=false`, + modalMessage: 'Are you sure you want to disable Copy Sent Items to Shared Mailbox?', + }, { label: 'Hide from Global Address List', color: 'info', diff --git a/src/views/identity/administration/Users.js b/src/views/identity/administration/Users.js index b086ddee69d4..92f4ef1f6bd0 100644 --- a/src/views/identity/administration/Users.js +++ b/src/views/identity/administration/Users.js @@ -159,14 +159,14 @@ const Offcanvas = (row, rowIndex, formatExtraData) => { label: 'Reset Password (Must Change)', color: 'info', modal: true, - modalUrl: `/api/ExecResetPass?MustChange=true&TenantFilter=${tenant.defaultDomainName}&ID=${row.id}`, + modalUrl: `/api/ExecResetPass?MustChange=true&TenantFilter=${tenant.defaultDomainName}&ID=${row.id}&displayName=${row.displayName}`, modalMessage: 'Are you sure you want to reset the password for this user?', }, { label: 'Reset Password', color: 'info', modal: true, - modalUrl: `/api/ExecResetPass?MustChange=false&TenantFilter=${tenant.defaultDomainName}&ID=${row.id}`, + modalUrl: `/api/ExecResetPass?MustChange=false&TenantFilter=${tenant.defaultDomainName}&ID=${row.id}&displayName=${row.displayName}`, modalMessage: 'Are you sure you want to reset the password for this user?', }, { From b9ae134f89841a687f18f1746c9c9d6e95830965 Mon Sep 17 00:00:00 2001 From: BNWEIN Date: Fri, 24 Mar 2023 14:42:56 +0000 Subject: [PATCH 033/124] Added User Mailbox Rules to the Users Page Added User Mailbox Rules to the Users Page --- .../administration/UserMailboxRuleList.js | 65 +++++++++++++++++++ src/views/identity/administration/ViewUser.js | 4 ++ 2 files changed, 69 insertions(+) create mode 100644 src/views/identity/administration/UserMailboxRuleList.js diff --git a/src/views/identity/administration/UserMailboxRuleList.js b/src/views/identity/administration/UserMailboxRuleList.js new file mode 100644 index 000000000000..8d15e48d2960 --- /dev/null +++ b/src/views/identity/administration/UserMailboxRuleList.js @@ -0,0 +1,65 @@ +import React from 'react' +import PropTypes from 'prop-types' +import { CellTip } from 'src/components/tables' +import { DatatableContentCard } from 'src/components/contentcards' +import { faEnvelope } from '@fortawesome/free-solid-svg-icons' + +const rowStyle = (row, rowIndex) => { + const style = {} + + return style +} + +export default function UserMailboxRuleList({ userId, tenantDomain, className = null }) { + const columns = [ + { + selector: (row) => row['Name'], + name: 'Display Name', + sortable: true, + cell: (row) => CellTip(row['Name']), + exportSelector: 'Name', + maxwidth: '350px', + }, + { + selector: (row) => row['Description'], + name: 'Description', + sortable: true, + cell: (row) => CellTip(row['Description']), + exportSelector: 'Description', + width: '600px', + }, + { + selector: (row) => row['ForwardTo'], + name: 'Forwards To', + sortable: true, + cell: (row) => CellTip(row['ForwardTo']), + exportSelector: 'ForwardTo', + width: '600px', + }, + ] + + return ( + + ) +} + +UserMailboxRuleList.propTypes = { + userId: PropTypes.string.isRequired, + tenantDomain: PropTypes.string.isRequired, + className: PropTypes.string, +} diff --git a/src/views/identity/administration/ViewUser.js b/src/views/identity/administration/ViewUser.js index 1f9363eb06b2..9e7f39feb4c8 100644 --- a/src/views/identity/administration/ViewUser.js +++ b/src/views/identity/administration/ViewUser.js @@ -19,6 +19,7 @@ import UserEmailSettings from 'src/views/identity/administration/UserEmailSettin import UserEmailPermissions from 'src/views/identity/administration/UserEmailPermissions' import UserGroups from 'src/views/identity/administration/UserGroups' import UserSigninLogs from 'src/views/identity/administration/UserSigninLogs' +import UserMailboxRuleList from 'src/views/identity/administration/UserMailboxRuleList' import { useListUserQuery } from 'src/store/api/users' const ViewUser = (props) => { @@ -90,6 +91,9 @@ const ViewUser = (props) => { + + + )} From cc5db48f7a6daa0a122ec60d3f8de6eb13c76210 Mon Sep 17 00:00:00 2001 From: BNWEIN Date: Fri, 24 Mar 2023 15:33:20 +0000 Subject: [PATCH 034/124] Update UserMailboxRuleList.js --- .../administration/UserMailboxRuleList.js | 43 ++++++++++++++++--- 1 file changed, 38 insertions(+), 5 deletions(-) diff --git a/src/views/identity/administration/UserMailboxRuleList.js b/src/views/identity/administration/UserMailboxRuleList.js index 8d15e48d2960..acb19e3e44e1 100644 --- a/src/views/identity/administration/UserMailboxRuleList.js +++ b/src/views/identity/administration/UserMailboxRuleList.js @@ -1,6 +1,6 @@ import React from 'react' import PropTypes from 'prop-types' -import { CellTip } from 'src/components/tables' +import { cellBooleanFormatter, CellTip } from 'src/components/tables' import { DatatableContentCard } from 'src/components/contentcards' import { faEnvelope } from '@fortawesome/free-solid-svg-icons' @@ -11,6 +11,7 @@ const rowStyle = (row, rowIndex) => { } export default function UserMailboxRuleList({ userId, tenantDomain, className = null }) { + const formatter = (cell) => CellBoolean({ cell }) const columns = [ { selector: (row) => row['Name'], @@ -18,7 +19,7 @@ export default function UserMailboxRuleList({ userId, tenantDomain, className = sortable: true, cell: (row) => CellTip(row['Name']), exportSelector: 'Name', - maxwidth: '350px', + width: '200px', }, { selector: (row) => row['Description'], @@ -26,7 +27,7 @@ export default function UserMailboxRuleList({ userId, tenantDomain, className = sortable: true, cell: (row) => CellTip(row['Description']), exportSelector: 'Description', - width: '600px', + width: '350px', }, { selector: (row) => row['ForwardTo'], @@ -34,10 +35,42 @@ export default function UserMailboxRuleList({ userId, tenantDomain, className = sortable: true, cell: (row) => CellTip(row['ForwardTo']), exportSelector: 'ForwardTo', - width: '600px', + width: '250px', + }, + { + selector: (row) => row['RedirectTo'], + name: 'Redirect To', + sortable: true, + cell: (row) => CellTip(row['RedirectTo']), + exportSelector: 'RedirectTo', + maxwidth: '250px', + }, + { + selector: (row) => row['CopyToFolder'], + name: 'Copy To Folder', + sortable: true, + cell: (row) => CellTip(row['CopyToFolder']), + exportSelector: 'CopyToFolder', + maxwidth: '200px', + }, + { + selector: (row) => row['MoveToFolder'], + name: 'Move To Folder', + sortable: true, + cell: (row) => CellTip(row['MoveToFolder']), + exportSelector: 'MoveToFolder', + maxwidth: '200px', + }, + { + selector: (row) => row['DeleteMessage'], + name: 'Delete Message', + sortable: true, + cell: cellBooleanFormatter({ colourless: true }), + formatter, + exportSelector: 'DeleteMessage', + width: '200px', }, ] - return ( Date: Sat, 25 Mar 2023 06:08:00 +0100 Subject: [PATCH 035/124] Fixed GranularDelegetedAdminPrivileges spelling mistake Fixed spelling mistake as mentioned in https://github.com/KelvinTegelaar/CIPP/issues/1443 Left the spelling mistake in delegatedAndGranularDelegetedAdminPrivileges because Microsoft misspelled it in Graph itself. --- src/views/cipp/CIPPSettings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/views/cipp/CIPPSettings.js b/src/views/cipp/CIPPSettings.js index 94e2e17f3897..55de4cd0580d 100644 --- a/src/views/cipp/CIPPSettings.js +++ b/src/views/cipp/CIPPSettings.js @@ -656,7 +656,7 @@ const ExcludedTenantsSettings = () => { if (cell === 'delegatedAndGranularDelegetedAdminPrivileges') { return } - if (cell === 'GranularDelegetedAdminPrivileges') { + if (cell === 'granularDelegatedAdminPrivileges') { return } return From 22506385b92788d72f7adf410e13b3e56bea29d2 Mon Sep 17 00:00:00 2001 From: BNWEIN Date: Tue, 28 Mar 2023 21:20:02 +0100 Subject: [PATCH 036/124] Added "Guests" functionality @KelvinTegelaar This is slightly broken "View" guest does not work "Edit" guest does not work I had to add the additional "GuestDetails" and "GuestLastLoginDetails" because the "Userdetails" and "UserLastLoginDetails" both refer back to the "ListUsers" function which no longer contains "Guests" If we wanted to keep "Guests" showing in the main "User" list, then a lot of what i have done can be undone, and the "View" and "Edit" button are likely to then work, but i dont think we should keep the guests in the "User" list now that we have a separate place for them Once the "View" and "Edit" pages are working there may well be some clean up required on them which i am happy to do. But its hard to do that whilst its not working. Sorry, i hope this isnt too much of a mess! --- src/_nav.js | 5 + src/routes.js | 8 + src/store/api/users.js | 22 + src/views/identity/administration/AddGuest.js | 148 ++++++ .../identity/administration/EditGuest.js | 432 ++++++++++++++++++ .../identity/administration/GuestDetails.js | 54 +++ .../administration/GuestLastLoginDetails.js | 54 +++ src/views/identity/administration/Guests.js | 290 ++++++++++++ .../identity/administration/ViewGuest.js | 84 ++++ 9 files changed, 1097 insertions(+) create mode 100644 src/views/identity/administration/AddGuest.js create mode 100644 src/views/identity/administration/EditGuest.js create mode 100644 src/views/identity/administration/GuestDetails.js create mode 100644 src/views/identity/administration/GuestLastLoginDetails.js create mode 100644 src/views/identity/administration/Guests.js create mode 100644 src/views/identity/administration/ViewGuest.js diff --git a/src/_nav.js b/src/_nav.js index 3177cc44935d..c5f872216928 100644 --- a/src/_nav.js +++ b/src/_nav.js @@ -44,6 +44,11 @@ const _nav = [ name: 'Users', to: '/identity/administration/users', }, + { + component: CNavItem, + name: 'Guests', + to: '/identity/administration/guests', + }, { component: CNavItem, name: 'Groups', diff --git a/src/routes.js b/src/routes.js index a71896e965cf..167bf6d71cb2 100644 --- a/src/routes.js +++ b/src/routes.js @@ -3,11 +3,15 @@ import React from 'react' const Home = React.lazy(() => import('src/views/home/Home')) const Logs = React.lazy(() => import('src/views/cipp/Logs')) const Users = React.lazy(() => import('src/views/identity/administration/Users')) +const Guests = React.lazy(() => import('src/views/identity/administration/Guests')) const DeletedItems = React.lazy(() => import('src/views/identity/administration/Deleted')) const ViewBEC = React.lazy(() => import('src/views/identity/administration/ViewBEC')) const AddUser = React.lazy(() => import('src/views/identity/administration/AddUser')) +const AddGuest = React.lazy(() => import('src/views/identity/administration/AddGuest')) const EditUser = React.lazy(() => import('src/views/identity/administration/EditUser')) +const EditGuest = React.lazy(() => import('src/views/identity/administration/EditGuest')) const ViewUser = React.lazy(() => import('src/views/identity/administration/ViewUser')) +const ViewGuest = React.lazy(() => import('src/views/identity/administration/ViewGuest')) const Groups = React.lazy(() => import('src/views/identity/administration/Groups')) const AddGroup = React.lazy(() => import('src/views/identity/administration/AddGroup')) const AddGroupTemplates = React.lazy(() => @@ -232,6 +236,10 @@ const routes = [ { path: '/identity/administration', name: 'Administration' }, { path: '/identity/administration/users', name: 'Users', component: Users }, { path: '/identity/administration/groups/add', name: 'Add Group', component: AddGroup }, + { path: '/identity/administration/guests', name: 'Guests', component: Guests }, + { path: '/identity/administration/guests/view', name: 'View Guest', component: ViewGuest }, + { path: '/identity/administration/guests/edit', name: 'Edit Guest', component: EditGuest }, + { path: '/identity/administration/guests/add', name: 'Add Guest', component: AddGuest }, { path: '/identity/administration/group-templates', name: 'Group Templates', diff --git a/src/store/api/users.js b/src/store/api/users.js index 66cfd9bd48c6..8f6aa1eb93e6 100644 --- a/src/store/api/users.js +++ b/src/store/api/users.js @@ -17,6 +17,14 @@ export const usersApi = baseApi.injectEndpoints({ }, }), }), + listGuests: builder.query({ + query: ({ tenantDomain }) => ({ + path: '/api/ListGuests', + params: { + TenantFilter: tenantDomain, + }, + }), + }), listContacts: builder.query({ query: ({ tenantDomain }) => ({ path: '/api/ListContacts', @@ -37,6 +45,18 @@ export const usersApi = baseApi.injectEndpoints({ return {} }, }), + listGuest: builder.query({ + query: ({ tenantDomain, userId, IncludeLogonDetails }) => ({ + path: '/api/ListGuests', + params: { userId, TenantFilter: tenantDomain, IncludeLogonDetails }, + }), + transformResponse: (response) => { + if (response?.length > 0) { + return response[0] + } + return {} + }, + }), listUserConditionalAccessPolicies: builder.query({ query: ({ tenantDomain, userId }) => ({ path: '/api/ListUserConditionalAccessPolicies', @@ -117,6 +137,8 @@ export const { useEditUserMutation, useListUsersQuery, useListUserQuery, + useListGuestsQuery, + useListGuestQuery, useListContactsQuery, useListUserConditionalAccessPoliciesQuery, useListUserSigninLogsQuery, diff --git a/src/views/identity/administration/AddGuest.js b/src/views/identity/administration/AddGuest.js new file mode 100644 index 000000000000..b8c117ea7f2d --- /dev/null +++ b/src/views/identity/administration/AddGuest.js @@ -0,0 +1,148 @@ +import React from 'react' +import { + CButton, + CCard, + CCardBody, + CCardHeader, + CCardTitle, + CCol, + CForm, + CRow, + CCallout, +} from '@coreui/react' +import { Form } from 'react-final-form' +import { RFFCFormCheck, RFFCFormInput } from 'src/components/forms' +import { CippPage } from 'src/components/layout' +import { useListAdConnectSettingsQuery } from 'src/store/api/adconnect' +import { useLazyGenericPostRequestQuery } from 'src/store/api/app' +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' +import { faCircleNotch } from '@fortawesome/free-solid-svg-icons' +import { useSelector } from 'react-redux' +import { required } from 'src/validators' +import useQuery from 'src/hooks/useQuery' +import { useNavigate } from 'react-router-dom' + +const AddGuest = () => { + let navigate = useNavigate() + + const tenant = useSelector((state) => state.app.currentTenant) + const { defaultDomainName: tenantDomain } = tenant + let query = useQuery() + const allQueryObj = {} + for (const [key, value] of query.entries()) { + allQueryObj[key] = value + } + const { + data: adconnectsettings = [], + isFetching: adcIsFetching, + error: adcError, + } = useListAdConnectSettingsQuery({ tenantDomain }) + + const [genericPostRequest, postResults] = useLazyGenericPostRequestQuery() + const onSubmit = (values) => { + const shippedValues = { + DisplayName: values.displayName, + Domain: values.primDomain, + Mail: values.mail, + PostalCode: values.postalCode, + RedirectURL: values.RedirectURL, + SendInvite: values.SendInvite, + tenantID: tenantDomain, + } + //window.alert(JSON.stringify(shippedValues)) + genericPostRequest({ path: '/api/AddGuest', values: shippedValues }) + } + + return ( + + {postResults.isSuccess && ( + + {postResults.data?.Results.map((result, index) => ( +
  • {result}
  • + ))} +
    + )} + + + + + Account Details + + + {adcError && Unable to determine Azure AD Connect Settings} + {!adcIsFetching && adconnectsettings.dirSyncEnabled && ( + + Warning! {adconnectsettings.dirSyncEnabled} This tenant currently has Active + Directory Sync Enabled. This usually means users should be created in Active + Directory + + )} +
    { + return ( + + + + + + + + + + + + + + + + + + + + + Add User + {postResults.isFetching && ( + + )} + + + + {postResults.isSuccess && ( + + {postResults.data.Results.map((message, idx) => { + return
  • {message}
  • + })} +
    + )} +
    + ) + }} + /> + + + + + + ) +} + +export default AddGuest diff --git a/src/views/identity/administration/EditGuest.js b/src/views/identity/administration/EditGuest.js new file mode 100644 index 000000000000..6759d0018386 --- /dev/null +++ b/src/views/identity/administration/EditGuest.js @@ -0,0 +1,432 @@ +import React, { useEffect, useState } from 'react' +import { CButton, CCallout, CCol, CForm, CFormLabel, CRow, CSpinner } from '@coreui/react' +import useQuery from 'src/hooks/useQuery' +import { useDispatch, useSelector } from 'react-redux' +import { Form } from 'react-final-form' +import { + Condition, + RFFCFormCheck, + RFFCFormInput, + RFFCFormSelect, + RFFCFormSwitch, + RFFCFormTextarea, + RFFSelectSearch, +} from 'src/components/forms' +import countryList from 'src/data/countryList' +import { useListGuestQuery, useListGuestsQuery } from 'src/store/api/users' +import { useListDomainsQuery } from 'src/store/api/domains' +import { useListLicensesQuery } from 'src/store/api/licenses' +import { CippCodeBlock, ModalService } from 'src/components/utilities' +import { useLazyGenericPostRequestQuery } from 'src/store/api/app' +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' +import { faCircleNotch, faEdit, faEye } from '@fortawesome/free-solid-svg-icons' +import { CippContentCard, CippPage } from 'src/components/layout' +import { password } from 'src/validators' + +const EditGuest = () => { + const dispatch = useDispatch() + let query = useQuery() + const userId = query.get('userId') + const tenantDomain = query.get('tenantDomain') + + const [queryError, setQueryError] = useState(false) + + //const [editUser, { error: editUserError, isFetching: editUserIsFetching }] = useEditUserMutation() + + const { + data: user = {}, + isFetching: userIsFetching, + error: userError, + } = useListGuestQuery({ tenantDomain, userId }) + + const { + data: users = [], + isFetching: usersIsFetching, + error: usersError, + } = useListGuestsQuery({ tenantDomain }) + + const { + data: domains = [], + isFetching: domainsIsFetching, + error: domainsError, + } = useListDomainsQuery({ tenantDomain, userId }) + + const { + data: licenses = [], + isFetching: licensesIsFetching, + error: licensesError, + } = useListLicensesQuery({ tenantDomain }) + + useEffect(() => { + if (!userId || !tenantDomain) { + ModalService.open({ + body: 'Error invalid request, could not load requested user.', + title: 'Invalid Request', + }) + setQueryError(true) + } else { + setQueryError(false) + } + }, [userId, tenantDomain, dispatch]) + const [genericPostRequest, postResults] = useLazyGenericPostRequestQuery() + const onSubmit = (values) => { + const shippedValues = { + BusinessPhone: values.businessPhones, + City: values.city, + CompanyName: values.companyName, + CopyFrom: values.CopyFrom ? values.CopyFrom.value : '', + Country: values.country, + Department: values.department, + DisplayName: values.displayName, + Domain: values.primDomain, + firstName: values.givenName, + Jobtitle: values.jobTitle, + LastName: values.surname, + License: values.licenses, + MobilePhone: values.mobilePhone, + Password: values.password, + PostalCode: values.postalCode, + usageLocation: values.usageLocation ? values.usageLocation.value : '', + UserID: userId, + Username: values.mailNickname, + streetAddress: values.streetAddress, + tenantID: tenantDomain, + mustchangepass: values.RequirePasswordChange, + } + //window.alert(JSON.stringify(shippedValues)) + genericPostRequest({ path: '/api/EditUser', values: shippedValues }) + } + const usageLocation = useSelector((state) => state.app.usageLocation) + const precheckedLicenses = user.assignedLicenses + ? user.assignedLicenses.reduce( + (o, key) => Object.assign(o, { [`License_${key.skuId}`]: true }), + {}, + ) + : '' + const initialState = { + keepLicenses: true, + ...user, + usageLocation: { + value: user.usageLocation ? user.usageLocation : usageLocation?.value, + label: user.usageLocation ? user.usageLocation : usageLocation?.label, + }, + license: precheckedLicenses, + } + + const formDisabled = queryError === true || !!userError || !user || Object.keys(user).length === 0 + const RawUser = JSON.stringify(user, null, 2) + return ( + + {!queryError && ( + <> + {postResults.isSuccess && ( + {postResults.data?.Results} + )} + {queryError && ( + + + + {/* @todo add more descriptive help message here */} + Failed to load user + + + + )} + + + + {userIsFetching && } + {userError && Error loading user} + {!userIsFetching && ( + { + return ( + + + + + + + + + + + + + + + + + + + + {domainsIsFetching && } + {!domainsIsFetching && ( + ({ + value: domain.id, + label: domain.id, + }))} + /> + )} + {domainsError && Failed to load list of domains} + + + + + + + + + + Settings + + + + + + + + + + + + ({ + value: Code, + name: Name, + }))} + disabled={formDisabled} + name="usageLocation" + placeholder="Type to search..." + label="Usage Location" + /> + + + + + + + Licenses +
    + {licensesIsFetching && } + {licensesError && Error loading licenses} + + {licensesIsFetching && } + {licensesError && Error loading licenses} + {!licensesIsFetching && + licenses?.map((license) => ( + + ))} +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ({ + value: user.mail, + name: user.displayName, + }))} + placeholder={!usersIsFetching ? 'Select user' : 'Loading...'} + name="CopyFrom" + /> + {usersError && Failed to load list of users} + + + + + + Edit User + {postResults.isFetching && ( + + )} + + + + {postResults.isSuccess && ( + + {postResults.data.Results.map((message, idx) => { + return
  • {message}
  • + })} +
    + )} +
    + ) + }} + /> + )} +
    +
    + + + {userIsFetching && } + {userError && Error loading user} + {!userIsFetching && ( + <> + This is the (raw) information for this account. + + + )} + + +
    + + )} +
    + ) +} + +export default EditGuest diff --git a/src/views/identity/administration/GuestDetails.js b/src/views/identity/administration/GuestDetails.js new file mode 100644 index 000000000000..9f36fc0d250d --- /dev/null +++ b/src/views/identity/administration/GuestDetails.js @@ -0,0 +1,54 @@ +import React from 'react' +import PropTypes from 'prop-types' +import { faPortrait } from '@fortawesome/free-solid-svg-icons' +import { useListGuestQuery } from 'src/store/api/users' +import { ListGroupContentCard } from 'src/components/contentcards' + +export default function GuestDetails({ tenantDomain, userId, className = null }) { + const { data: user = {}, isFetching, error } = useListGuestQuery({ tenantDomain, userId }) + + const content = [ + { + heading: 'First Name', + body: user.givenName, + }, + { + heading: 'Last Name', + body: user.surname, + }, + { + heading: 'User Principal Name', + body: user.userPrincipalName, + }, + { + heading: 'Job Title', + body: user.jobTitle, + }, + { + heading: 'Mobile Phone', + body: user.mobilePhone, + }, + { + heading: 'Business Phone', + body: user.businessPhones, + }, + ] + + return ( + + ) +} + +GuestDetails.propTypes = { + tenantDomain: PropTypes.string.isRequired, + userId: PropTypes.string.isRequired, + className: PropTypes.string, +} diff --git a/src/views/identity/administration/GuestLastLoginDetails.js b/src/views/identity/administration/GuestLastLoginDetails.js new file mode 100644 index 000000000000..bb439c9e96aa --- /dev/null +++ b/src/views/identity/administration/GuestLastLoginDetails.js @@ -0,0 +1,54 @@ +import React from 'react' +import PropTypes from 'prop-types' +import { faClock } from '@fortawesome/free-solid-svg-icons' +import { ListGroupContentCard } from 'src/components/contentcards' +import { useListGuestQuery } from 'src/store/api/users' + +export default function GuestLastLoginDetails({ tenantDomain, userId, className = null }) { + const { + data: user = {}, + isFetching, + error, + } = useListGuestQuery({ tenantDomain, userId, IncludeLogonDetails: true }) + + const content = [ + { + heading: 'Last Sign in Date (UTC)', + body: user.LastSigninDate, + }, + { + heading: 'Last Sign in Application', + body: user.LastSigninApplication, + }, + { + heading: 'Last Sign in Status', + body: user.LastSigninStatus, + }, + { + heading: 'Last Sign in Result', + body: user.LastSigninResult, + }, + { + heading: 'Last Sign in Failure Reason', + body: user.LastSigninFailureReason, + }, + ] + + return ( + + ) +} + +GuestLastLoginDetails.propTypes = { + tenantDomain: PropTypes.string.isRequired, + userId: PropTypes.string.isRequired, + className: PropTypes.string, +} diff --git a/src/views/identity/administration/Guests.js b/src/views/identity/administration/Guests.js new file mode 100644 index 000000000000..603463eedcc6 --- /dev/null +++ b/src/views/identity/administration/Guests.js @@ -0,0 +1,290 @@ +import React, { useState } from 'react' +import { CButton } from '@coreui/react' +import { Link } from 'react-router-dom' +import { useSelector } from 'react-redux' +import { faEdit, faEllipsisV, faEye } from '@fortawesome/free-solid-svg-icons' +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' +import { cellBooleanFormatter, CellTip } from 'src/components/tables' +import { CippPageList } from 'src/components/layout' +import { TitleButton } from 'src/components/buttons' +import { CippActionsOffcanvas } from 'src/components/utilities' + +const Offcanvas = (row, rowIndex, formatExtraData) => { + const tenant = useSelector((state) => state.app.currentTenant) + const [ocVisible, setOCVisible] = useState(false) + const viewLink = `/identity/administration/Guests/view?userId=${row.id}&tenantDomain=${tenant.defaultDomainName}&userEmail=${row.userPrincipalName}` + const editLink = `/identity/administration/Guests/edit?userId=${row.id}&tenantDomain=${tenant.defaultDomainName}` + //console.log(row) + return ( + <> + + + + + + + + + + + setOCVisible(true)}> + + + , + label: 'View User', + link: viewLink, + color: 'success', + }, + { + icon: , + label: 'Edit User', + link: editLink, + color: 'info', + }, + { + label: 'Research Compromised Account', + link: `/identity/administration/ViewBec?userId=${row.id}&tenantDomain=${tenant.defaultDomainName}`, + color: 'info', + }, + { + label: 'Create Temporary Access Password', + color: 'info', + modal: true, + modalUrl: `/api/ExecCreateTAP?TenantFilter=${tenant.defaultDomainName}&ID=${row.userPrincipalName}`, + modalMessage: 'Are you sure you want to create a Temporary Access Pass?', + }, + { + label: 'Rerequire MFA registration', + color: 'info', + modal: true, + modalUrl: `/api/ExecResetMFA?TenantFilter=${tenant.defaultDomainName}&ID=${row.id}`, + modalMessage: 'Are you sure you want to enable MFA for this user?', + }, + { + label: 'Send MFA Push', + color: 'info', + modal: true, + modalUrl: `/api/ExecSendPush?TenantFilter=${tenant.defaultDomainName}&UserEmail=${row.userPrincipalName}`, + modalMessage: 'Are you sure you want to send a MFA request?', + }, + { + label: 'Block Sign In', + color: 'info', + modal: true, + modalUrl: `/api/ExecDisableUser?TenantFilter=${tenant.defaultDomainName}&ID=${row.id}`, + modalMessage: 'Are you sure you want to block the sign in for this user?', + }, + { + label: 'Unblock Sign In', + color: 'info', + modal: true, + modalUrl: `/api/ExecDisableUser?Enable=true&TenantFilter=${tenant.defaultDomainName}&ID=${row.id}`, + modalMessage: 'Are you sure you want to enable this user?', + }, + { + label: 'Reset Password (Must Change)', + color: 'info', + modal: true, + modalUrl: `/api/ExecResetPass?MustChange=true&TenantFilter=${tenant.defaultDomainName}&ID=${row.id}&displayName=${row.displayName}`, + modalMessage: 'Are you sure you want to reset the password for this user?', + }, + { + label: 'Reset Password', + color: 'info', + modal: true, + modalUrl: `/api/ExecResetPass?MustChange=false&TenantFilter=${tenant.defaultDomainName}&ID=${row.id}&displayName=${row.displayName}`, + modalMessage: 'Are you sure you want to reset the password for this user?', + }, + { + label: 'Clear ImmutableId', + color: 'warning', + modal: true, + modalUrl: `/api/ExecClrImmId?TenantFilter=${tenant.defaultDomainName}&ID=${row.id}`, + modalMessage: 'Are you sure you want to clear the ImmutableId for this user?', + }, + { + label: 'Revoke all user sessions', + color: 'danger', + modal: true, + modalUrl: `/api/ExecRevokeSessions?TenantFilter=${tenant.defaultDomainName}&ID=${row.id}`, + modalMessage: 'Are you sure you want to revoke this users sessions?', + }, + { + label: 'Delete User', + color: 'danger', + modal: true, + modalUrl: `/api/RemoveUser?TenantFilter=${tenant.defaultDomainName}&ID=${row.id}`, + modalMessage: 'Are you sure you want to delete this user?', + }, + ]} + placement="end" + visible={ocVisible} + id={row.id} + hideFunction={() => setOCVisible(false)} + /> + + ) +} + +const columns = [ + { + name: 'Display Name', + selector: (row) => row['displayName'], + sortable: true, + cell: (row) => CellTip(row['displayName']), + exportSelector: 'displayName', + minWidth: '300px', + }, + { + name: 'Email', + selector: (row) => row['mail'], + sortable: true, + cell: (row) => CellTip(row['mail']), + exportSelector: 'mail', + minWidth: '250px', + }, + { + name: 'User Type', + selector: (row) => row['userType'], + sortable: true, + exportSelector: 'userType', + minWidth: '140px', + }, + { + name: 'Enabled', + selector: (row) => row['accountEnabled'], + cell: cellBooleanFormatter({ colourless: true }), + sortable: true, + exportSelector: 'accountEnabled', + minWidth: '100px', + }, + { + name: 'AD Synced', + selector: (row) => row['onPremisesSyncEnabled'], + cell: cellBooleanFormatter({ colourless: true }), + sortable: true, + exportSelector: 'onPremisesSyncEnabled', + minWidth: '120px', + }, + { + name: 'Licenses', + selector: (row) => row['LicJoined'], + exportSelector: 'LicJoined', + sortable: true, + grow: 5, + wrap: true, + minWidth: '200px', + }, + { + name: 'id', + selector: (row) => row['id'], + omit: true, + }, + { + name: 'Actions', + cell: Offcanvas, + }, +] + +const Guests = (row) => { + const tenant = useSelector((state) => state.app.currentTenant) + const titleButton = + return ( + + ) +} + +export default Guests diff --git a/src/views/identity/administration/ViewGuest.js b/src/views/identity/administration/ViewGuest.js new file mode 100644 index 000000000000..7388d890b459 --- /dev/null +++ b/src/views/identity/administration/ViewGuest.js @@ -0,0 +1,84 @@ +import React, { useEffect, useState } from 'react' +import { CSpinner } from '@coreui/react' +import PropTypes from 'prop-types' +import useQuery from 'src/hooks/useQuery' +import { useDispatch } from 'react-redux' +import { CippPage } from 'src/components/layout' +import { CippMasonry, CippMasonryItem } from 'src/components/layout' +import { ModalService } from 'src/components/utilities' +import UserDevices from 'src/views/identity/administration/UserDevices' +import GuestDetails from 'src/views/identity/administration/GuestDetails' +import GuestLastLoginDetails from 'src/views/identity/administration/GuestLastLoginDetails' +import UserCAPs from 'src/views/identity/administration/UserCAPs' +import UserActions from 'src/views/identity/administration/UserActions' +import User365Management from 'src/views/identity/administration/User365Management' +import UserGroups from 'src/views/identity/administration/UserGroups' +import UserSigninLogs from 'src/views/identity/administration/UserSigninLogs' +import { useListGuestQuery } from 'src/store/api/users' + +const ViewGuest = (props) => { + const dispatch = useDispatch() + let query = useQuery() + const userId = query.get('userId') + const tenantDomain = query.get('tenantDomain') + const userEmail = query.get('userEmail') + const [queryError, setQueryError] = useState(false) + + const { + data: user = {}, + isFetching: userFetching, + error: userError, + } = useListGuestQuery({ tenantDomain, userId }) + + useEffect(() => { + if (!userId || !tenantDomain) { + ModalService.open({ + body: 'Error invalid request, could not load requested user.', + title: 'Invalid Request', + }) + setQueryError(true) + } + }, [tenantDomain, userId, dispatch]) + + return ( + + {userFetching && } + {!userFetching && userError && Error loading user} + {!queryError && !userFetching && ( + + + + + + + + + + + + + + + + + + + + + + + + + + + )} + + ) +} + +ViewGuest.propTypes = { + params: PropTypes.object, + location: PropTypes.object, +} + +export default ViewGuest From 2cf767ed0a9164b17010881884aadbdc8e0a56e8 Mon Sep 17 00:00:00 2001 From: BNWEIN Date: Tue, 28 Mar 2023 21:40:05 +0100 Subject: [PATCH 037/124] Revert "Added "Guests" functionality" This reverts commit 22506385b92788d72f7adf410e13b3e56bea29d2. --- src/_nav.js | 5 - src/routes.js | 8 - src/store/api/users.js | 22 - src/views/identity/administration/AddGuest.js | 148 ------ .../identity/administration/EditGuest.js | 432 ------------------ .../identity/administration/GuestDetails.js | 54 --- .../administration/GuestLastLoginDetails.js | 54 --- src/views/identity/administration/Guests.js | 290 ------------ .../identity/administration/ViewGuest.js | 84 ---- 9 files changed, 1097 deletions(-) delete mode 100644 src/views/identity/administration/AddGuest.js delete mode 100644 src/views/identity/administration/EditGuest.js delete mode 100644 src/views/identity/administration/GuestDetails.js delete mode 100644 src/views/identity/administration/GuestLastLoginDetails.js delete mode 100644 src/views/identity/administration/Guests.js delete mode 100644 src/views/identity/administration/ViewGuest.js diff --git a/src/_nav.js b/src/_nav.js index c5f872216928..3177cc44935d 100644 --- a/src/_nav.js +++ b/src/_nav.js @@ -44,11 +44,6 @@ const _nav = [ name: 'Users', to: '/identity/administration/users', }, - { - component: CNavItem, - name: 'Guests', - to: '/identity/administration/guests', - }, { component: CNavItem, name: 'Groups', diff --git a/src/routes.js b/src/routes.js index 167bf6d71cb2..a71896e965cf 100644 --- a/src/routes.js +++ b/src/routes.js @@ -3,15 +3,11 @@ import React from 'react' const Home = React.lazy(() => import('src/views/home/Home')) const Logs = React.lazy(() => import('src/views/cipp/Logs')) const Users = React.lazy(() => import('src/views/identity/administration/Users')) -const Guests = React.lazy(() => import('src/views/identity/administration/Guests')) const DeletedItems = React.lazy(() => import('src/views/identity/administration/Deleted')) const ViewBEC = React.lazy(() => import('src/views/identity/administration/ViewBEC')) const AddUser = React.lazy(() => import('src/views/identity/administration/AddUser')) -const AddGuest = React.lazy(() => import('src/views/identity/administration/AddGuest')) const EditUser = React.lazy(() => import('src/views/identity/administration/EditUser')) -const EditGuest = React.lazy(() => import('src/views/identity/administration/EditGuest')) const ViewUser = React.lazy(() => import('src/views/identity/administration/ViewUser')) -const ViewGuest = React.lazy(() => import('src/views/identity/administration/ViewGuest')) const Groups = React.lazy(() => import('src/views/identity/administration/Groups')) const AddGroup = React.lazy(() => import('src/views/identity/administration/AddGroup')) const AddGroupTemplates = React.lazy(() => @@ -236,10 +232,6 @@ const routes = [ { path: '/identity/administration', name: 'Administration' }, { path: '/identity/administration/users', name: 'Users', component: Users }, { path: '/identity/administration/groups/add', name: 'Add Group', component: AddGroup }, - { path: '/identity/administration/guests', name: 'Guests', component: Guests }, - { path: '/identity/administration/guests/view', name: 'View Guest', component: ViewGuest }, - { path: '/identity/administration/guests/edit', name: 'Edit Guest', component: EditGuest }, - { path: '/identity/administration/guests/add', name: 'Add Guest', component: AddGuest }, { path: '/identity/administration/group-templates', name: 'Group Templates', diff --git a/src/store/api/users.js b/src/store/api/users.js index 8f6aa1eb93e6..66cfd9bd48c6 100644 --- a/src/store/api/users.js +++ b/src/store/api/users.js @@ -17,14 +17,6 @@ export const usersApi = baseApi.injectEndpoints({ }, }), }), - listGuests: builder.query({ - query: ({ tenantDomain }) => ({ - path: '/api/ListGuests', - params: { - TenantFilter: tenantDomain, - }, - }), - }), listContacts: builder.query({ query: ({ tenantDomain }) => ({ path: '/api/ListContacts', @@ -45,18 +37,6 @@ export const usersApi = baseApi.injectEndpoints({ return {} }, }), - listGuest: builder.query({ - query: ({ tenantDomain, userId, IncludeLogonDetails }) => ({ - path: '/api/ListGuests', - params: { userId, TenantFilter: tenantDomain, IncludeLogonDetails }, - }), - transformResponse: (response) => { - if (response?.length > 0) { - return response[0] - } - return {} - }, - }), listUserConditionalAccessPolicies: builder.query({ query: ({ tenantDomain, userId }) => ({ path: '/api/ListUserConditionalAccessPolicies', @@ -137,8 +117,6 @@ export const { useEditUserMutation, useListUsersQuery, useListUserQuery, - useListGuestsQuery, - useListGuestQuery, useListContactsQuery, useListUserConditionalAccessPoliciesQuery, useListUserSigninLogsQuery, diff --git a/src/views/identity/administration/AddGuest.js b/src/views/identity/administration/AddGuest.js deleted file mode 100644 index b8c117ea7f2d..000000000000 --- a/src/views/identity/administration/AddGuest.js +++ /dev/null @@ -1,148 +0,0 @@ -import React from 'react' -import { - CButton, - CCard, - CCardBody, - CCardHeader, - CCardTitle, - CCol, - CForm, - CRow, - CCallout, -} from '@coreui/react' -import { Form } from 'react-final-form' -import { RFFCFormCheck, RFFCFormInput } from 'src/components/forms' -import { CippPage } from 'src/components/layout' -import { useListAdConnectSettingsQuery } from 'src/store/api/adconnect' -import { useLazyGenericPostRequestQuery } from 'src/store/api/app' -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' -import { faCircleNotch } from '@fortawesome/free-solid-svg-icons' -import { useSelector } from 'react-redux' -import { required } from 'src/validators' -import useQuery from 'src/hooks/useQuery' -import { useNavigate } from 'react-router-dom' - -const AddGuest = () => { - let navigate = useNavigate() - - const tenant = useSelector((state) => state.app.currentTenant) - const { defaultDomainName: tenantDomain } = tenant - let query = useQuery() - const allQueryObj = {} - for (const [key, value] of query.entries()) { - allQueryObj[key] = value - } - const { - data: adconnectsettings = [], - isFetching: adcIsFetching, - error: adcError, - } = useListAdConnectSettingsQuery({ tenantDomain }) - - const [genericPostRequest, postResults] = useLazyGenericPostRequestQuery() - const onSubmit = (values) => { - const shippedValues = { - DisplayName: values.displayName, - Domain: values.primDomain, - Mail: values.mail, - PostalCode: values.postalCode, - RedirectURL: values.RedirectURL, - SendInvite: values.SendInvite, - tenantID: tenantDomain, - } - //window.alert(JSON.stringify(shippedValues)) - genericPostRequest({ path: '/api/AddGuest', values: shippedValues }) - } - - return ( - - {postResults.isSuccess && ( - - {postResults.data?.Results.map((result, index) => ( -
  • {result}
  • - ))} -
    - )} - - - - - Account Details - - - {adcError && Unable to determine Azure AD Connect Settings} - {!adcIsFetching && adconnectsettings.dirSyncEnabled && ( - - Warning! {adconnectsettings.dirSyncEnabled} This tenant currently has Active - Directory Sync Enabled. This usually means users should be created in Active - Directory - - )} - { - return ( - - - - - - - - - - - - - - - - - - - - - Add User - {postResults.isFetching && ( - - )} - - - - {postResults.isSuccess && ( - - {postResults.data.Results.map((message, idx) => { - return
  • {message}
  • - })} -
    - )} -
    - ) - }} - /> -
    -
    -
    -
    -
    - ) -} - -export default AddGuest diff --git a/src/views/identity/administration/EditGuest.js b/src/views/identity/administration/EditGuest.js deleted file mode 100644 index 6759d0018386..000000000000 --- a/src/views/identity/administration/EditGuest.js +++ /dev/null @@ -1,432 +0,0 @@ -import React, { useEffect, useState } from 'react' -import { CButton, CCallout, CCol, CForm, CFormLabel, CRow, CSpinner } from '@coreui/react' -import useQuery from 'src/hooks/useQuery' -import { useDispatch, useSelector } from 'react-redux' -import { Form } from 'react-final-form' -import { - Condition, - RFFCFormCheck, - RFFCFormInput, - RFFCFormSelect, - RFFCFormSwitch, - RFFCFormTextarea, - RFFSelectSearch, -} from 'src/components/forms' -import countryList from 'src/data/countryList' -import { useListGuestQuery, useListGuestsQuery } from 'src/store/api/users' -import { useListDomainsQuery } from 'src/store/api/domains' -import { useListLicensesQuery } from 'src/store/api/licenses' -import { CippCodeBlock, ModalService } from 'src/components/utilities' -import { useLazyGenericPostRequestQuery } from 'src/store/api/app' -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' -import { faCircleNotch, faEdit, faEye } from '@fortawesome/free-solid-svg-icons' -import { CippContentCard, CippPage } from 'src/components/layout' -import { password } from 'src/validators' - -const EditGuest = () => { - const dispatch = useDispatch() - let query = useQuery() - const userId = query.get('userId') - const tenantDomain = query.get('tenantDomain') - - const [queryError, setQueryError] = useState(false) - - //const [editUser, { error: editUserError, isFetching: editUserIsFetching }] = useEditUserMutation() - - const { - data: user = {}, - isFetching: userIsFetching, - error: userError, - } = useListGuestQuery({ tenantDomain, userId }) - - const { - data: users = [], - isFetching: usersIsFetching, - error: usersError, - } = useListGuestsQuery({ tenantDomain }) - - const { - data: domains = [], - isFetching: domainsIsFetching, - error: domainsError, - } = useListDomainsQuery({ tenantDomain, userId }) - - const { - data: licenses = [], - isFetching: licensesIsFetching, - error: licensesError, - } = useListLicensesQuery({ tenantDomain }) - - useEffect(() => { - if (!userId || !tenantDomain) { - ModalService.open({ - body: 'Error invalid request, could not load requested user.', - title: 'Invalid Request', - }) - setQueryError(true) - } else { - setQueryError(false) - } - }, [userId, tenantDomain, dispatch]) - const [genericPostRequest, postResults] = useLazyGenericPostRequestQuery() - const onSubmit = (values) => { - const shippedValues = { - BusinessPhone: values.businessPhones, - City: values.city, - CompanyName: values.companyName, - CopyFrom: values.CopyFrom ? values.CopyFrom.value : '', - Country: values.country, - Department: values.department, - DisplayName: values.displayName, - Domain: values.primDomain, - firstName: values.givenName, - Jobtitle: values.jobTitle, - LastName: values.surname, - License: values.licenses, - MobilePhone: values.mobilePhone, - Password: values.password, - PostalCode: values.postalCode, - usageLocation: values.usageLocation ? values.usageLocation.value : '', - UserID: userId, - Username: values.mailNickname, - streetAddress: values.streetAddress, - tenantID: tenantDomain, - mustchangepass: values.RequirePasswordChange, - } - //window.alert(JSON.stringify(shippedValues)) - genericPostRequest({ path: '/api/EditUser', values: shippedValues }) - } - const usageLocation = useSelector((state) => state.app.usageLocation) - const precheckedLicenses = user.assignedLicenses - ? user.assignedLicenses.reduce( - (o, key) => Object.assign(o, { [`License_${key.skuId}`]: true }), - {}, - ) - : '' - const initialState = { - keepLicenses: true, - ...user, - usageLocation: { - value: user.usageLocation ? user.usageLocation : usageLocation?.value, - label: user.usageLocation ? user.usageLocation : usageLocation?.label, - }, - license: precheckedLicenses, - } - - const formDisabled = queryError === true || !!userError || !user || Object.keys(user).length === 0 - const RawUser = JSON.stringify(user, null, 2) - return ( - - {!queryError && ( - <> - {postResults.isSuccess && ( - {postResults.data?.Results} - )} - {queryError && ( - - - - {/* @todo add more descriptive help message here */} - Failed to load user - - - - )} - - - - {userIsFetching && } - {userError && Error loading user} - {!userIsFetching && ( - { - return ( - - - - - - - - - - - - - - - - - - - - {domainsIsFetching && } - {!domainsIsFetching && ( - ({ - value: domain.id, - label: domain.id, - }))} - /> - )} - {domainsError && Failed to load list of domains} - - - - - - - - - - Settings - - - - - - - - - - - - ({ - value: Code, - name: Name, - }))} - disabled={formDisabled} - name="usageLocation" - placeholder="Type to search..." - label="Usage Location" - /> - - - - - - - Licenses -
    - {licensesIsFetching && } - {licensesError && Error loading licenses} - - {licensesIsFetching && } - {licensesError && Error loading licenses} - {!licensesIsFetching && - licenses?.map((license) => ( - - ))} -
    -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ({ - value: user.mail, - name: user.displayName, - }))} - placeholder={!usersIsFetching ? 'Select user' : 'Loading...'} - name="CopyFrom" - /> - {usersError && Failed to load list of users} - - - - - - Edit User - {postResults.isFetching && ( - - )} - - - - {postResults.isSuccess && ( - - {postResults.data.Results.map((message, idx) => { - return
  • {message}
  • - })} -
    - )} -
    - ) - }} - /> - )} -
    -
    - - - {userIsFetching && } - {userError && Error loading user} - {!userIsFetching && ( - <> - This is the (raw) information for this account. - - - )} - - -
    - - )} -
    - ) -} - -export default EditGuest diff --git a/src/views/identity/administration/GuestDetails.js b/src/views/identity/administration/GuestDetails.js deleted file mode 100644 index 9f36fc0d250d..000000000000 --- a/src/views/identity/administration/GuestDetails.js +++ /dev/null @@ -1,54 +0,0 @@ -import React from 'react' -import PropTypes from 'prop-types' -import { faPortrait } from '@fortawesome/free-solid-svg-icons' -import { useListGuestQuery } from 'src/store/api/users' -import { ListGroupContentCard } from 'src/components/contentcards' - -export default function GuestDetails({ tenantDomain, userId, className = null }) { - const { data: user = {}, isFetching, error } = useListGuestQuery({ tenantDomain, userId }) - - const content = [ - { - heading: 'First Name', - body: user.givenName, - }, - { - heading: 'Last Name', - body: user.surname, - }, - { - heading: 'User Principal Name', - body: user.userPrincipalName, - }, - { - heading: 'Job Title', - body: user.jobTitle, - }, - { - heading: 'Mobile Phone', - body: user.mobilePhone, - }, - { - heading: 'Business Phone', - body: user.businessPhones, - }, - ] - - return ( - - ) -} - -GuestDetails.propTypes = { - tenantDomain: PropTypes.string.isRequired, - userId: PropTypes.string.isRequired, - className: PropTypes.string, -} diff --git a/src/views/identity/administration/GuestLastLoginDetails.js b/src/views/identity/administration/GuestLastLoginDetails.js deleted file mode 100644 index bb439c9e96aa..000000000000 --- a/src/views/identity/administration/GuestLastLoginDetails.js +++ /dev/null @@ -1,54 +0,0 @@ -import React from 'react' -import PropTypes from 'prop-types' -import { faClock } from '@fortawesome/free-solid-svg-icons' -import { ListGroupContentCard } from 'src/components/contentcards' -import { useListGuestQuery } from 'src/store/api/users' - -export default function GuestLastLoginDetails({ tenantDomain, userId, className = null }) { - const { - data: user = {}, - isFetching, - error, - } = useListGuestQuery({ tenantDomain, userId, IncludeLogonDetails: true }) - - const content = [ - { - heading: 'Last Sign in Date (UTC)', - body: user.LastSigninDate, - }, - { - heading: 'Last Sign in Application', - body: user.LastSigninApplication, - }, - { - heading: 'Last Sign in Status', - body: user.LastSigninStatus, - }, - { - heading: 'Last Sign in Result', - body: user.LastSigninResult, - }, - { - heading: 'Last Sign in Failure Reason', - body: user.LastSigninFailureReason, - }, - ] - - return ( - - ) -} - -GuestLastLoginDetails.propTypes = { - tenantDomain: PropTypes.string.isRequired, - userId: PropTypes.string.isRequired, - className: PropTypes.string, -} diff --git a/src/views/identity/administration/Guests.js b/src/views/identity/administration/Guests.js deleted file mode 100644 index 603463eedcc6..000000000000 --- a/src/views/identity/administration/Guests.js +++ /dev/null @@ -1,290 +0,0 @@ -import React, { useState } from 'react' -import { CButton } from '@coreui/react' -import { Link } from 'react-router-dom' -import { useSelector } from 'react-redux' -import { faEdit, faEllipsisV, faEye } from '@fortawesome/free-solid-svg-icons' -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' -import { cellBooleanFormatter, CellTip } from 'src/components/tables' -import { CippPageList } from 'src/components/layout' -import { TitleButton } from 'src/components/buttons' -import { CippActionsOffcanvas } from 'src/components/utilities' - -const Offcanvas = (row, rowIndex, formatExtraData) => { - const tenant = useSelector((state) => state.app.currentTenant) - const [ocVisible, setOCVisible] = useState(false) - const viewLink = `/identity/administration/Guests/view?userId=${row.id}&tenantDomain=${tenant.defaultDomainName}&userEmail=${row.userPrincipalName}` - const editLink = `/identity/administration/Guests/edit?userId=${row.id}&tenantDomain=${tenant.defaultDomainName}` - //console.log(row) - return ( - <> - - - - - - - - - - - setOCVisible(true)}> - - - , - label: 'View User', - link: viewLink, - color: 'success', - }, - { - icon: , - label: 'Edit User', - link: editLink, - color: 'info', - }, - { - label: 'Research Compromised Account', - link: `/identity/administration/ViewBec?userId=${row.id}&tenantDomain=${tenant.defaultDomainName}`, - color: 'info', - }, - { - label: 'Create Temporary Access Password', - color: 'info', - modal: true, - modalUrl: `/api/ExecCreateTAP?TenantFilter=${tenant.defaultDomainName}&ID=${row.userPrincipalName}`, - modalMessage: 'Are you sure you want to create a Temporary Access Pass?', - }, - { - label: 'Rerequire MFA registration', - color: 'info', - modal: true, - modalUrl: `/api/ExecResetMFA?TenantFilter=${tenant.defaultDomainName}&ID=${row.id}`, - modalMessage: 'Are you sure you want to enable MFA for this user?', - }, - { - label: 'Send MFA Push', - color: 'info', - modal: true, - modalUrl: `/api/ExecSendPush?TenantFilter=${tenant.defaultDomainName}&UserEmail=${row.userPrincipalName}`, - modalMessage: 'Are you sure you want to send a MFA request?', - }, - { - label: 'Block Sign In', - color: 'info', - modal: true, - modalUrl: `/api/ExecDisableUser?TenantFilter=${tenant.defaultDomainName}&ID=${row.id}`, - modalMessage: 'Are you sure you want to block the sign in for this user?', - }, - { - label: 'Unblock Sign In', - color: 'info', - modal: true, - modalUrl: `/api/ExecDisableUser?Enable=true&TenantFilter=${tenant.defaultDomainName}&ID=${row.id}`, - modalMessage: 'Are you sure you want to enable this user?', - }, - { - label: 'Reset Password (Must Change)', - color: 'info', - modal: true, - modalUrl: `/api/ExecResetPass?MustChange=true&TenantFilter=${tenant.defaultDomainName}&ID=${row.id}&displayName=${row.displayName}`, - modalMessage: 'Are you sure you want to reset the password for this user?', - }, - { - label: 'Reset Password', - color: 'info', - modal: true, - modalUrl: `/api/ExecResetPass?MustChange=false&TenantFilter=${tenant.defaultDomainName}&ID=${row.id}&displayName=${row.displayName}`, - modalMessage: 'Are you sure you want to reset the password for this user?', - }, - { - label: 'Clear ImmutableId', - color: 'warning', - modal: true, - modalUrl: `/api/ExecClrImmId?TenantFilter=${tenant.defaultDomainName}&ID=${row.id}`, - modalMessage: 'Are you sure you want to clear the ImmutableId for this user?', - }, - { - label: 'Revoke all user sessions', - color: 'danger', - modal: true, - modalUrl: `/api/ExecRevokeSessions?TenantFilter=${tenant.defaultDomainName}&ID=${row.id}`, - modalMessage: 'Are you sure you want to revoke this users sessions?', - }, - { - label: 'Delete User', - color: 'danger', - modal: true, - modalUrl: `/api/RemoveUser?TenantFilter=${tenant.defaultDomainName}&ID=${row.id}`, - modalMessage: 'Are you sure you want to delete this user?', - }, - ]} - placement="end" - visible={ocVisible} - id={row.id} - hideFunction={() => setOCVisible(false)} - /> - - ) -} - -const columns = [ - { - name: 'Display Name', - selector: (row) => row['displayName'], - sortable: true, - cell: (row) => CellTip(row['displayName']), - exportSelector: 'displayName', - minWidth: '300px', - }, - { - name: 'Email', - selector: (row) => row['mail'], - sortable: true, - cell: (row) => CellTip(row['mail']), - exportSelector: 'mail', - minWidth: '250px', - }, - { - name: 'User Type', - selector: (row) => row['userType'], - sortable: true, - exportSelector: 'userType', - minWidth: '140px', - }, - { - name: 'Enabled', - selector: (row) => row['accountEnabled'], - cell: cellBooleanFormatter({ colourless: true }), - sortable: true, - exportSelector: 'accountEnabled', - minWidth: '100px', - }, - { - name: 'AD Synced', - selector: (row) => row['onPremisesSyncEnabled'], - cell: cellBooleanFormatter({ colourless: true }), - sortable: true, - exportSelector: 'onPremisesSyncEnabled', - minWidth: '120px', - }, - { - name: 'Licenses', - selector: (row) => row['LicJoined'], - exportSelector: 'LicJoined', - sortable: true, - grow: 5, - wrap: true, - minWidth: '200px', - }, - { - name: 'id', - selector: (row) => row['id'], - omit: true, - }, - { - name: 'Actions', - cell: Offcanvas, - }, -] - -const Guests = (row) => { - const tenant = useSelector((state) => state.app.currentTenant) - const titleButton = - return ( - - ) -} - -export default Guests diff --git a/src/views/identity/administration/ViewGuest.js b/src/views/identity/administration/ViewGuest.js deleted file mode 100644 index 7388d890b459..000000000000 --- a/src/views/identity/administration/ViewGuest.js +++ /dev/null @@ -1,84 +0,0 @@ -import React, { useEffect, useState } from 'react' -import { CSpinner } from '@coreui/react' -import PropTypes from 'prop-types' -import useQuery from 'src/hooks/useQuery' -import { useDispatch } from 'react-redux' -import { CippPage } from 'src/components/layout' -import { CippMasonry, CippMasonryItem } from 'src/components/layout' -import { ModalService } from 'src/components/utilities' -import UserDevices from 'src/views/identity/administration/UserDevices' -import GuestDetails from 'src/views/identity/administration/GuestDetails' -import GuestLastLoginDetails from 'src/views/identity/administration/GuestLastLoginDetails' -import UserCAPs from 'src/views/identity/administration/UserCAPs' -import UserActions from 'src/views/identity/administration/UserActions' -import User365Management from 'src/views/identity/administration/User365Management' -import UserGroups from 'src/views/identity/administration/UserGroups' -import UserSigninLogs from 'src/views/identity/administration/UserSigninLogs' -import { useListGuestQuery } from 'src/store/api/users' - -const ViewGuest = (props) => { - const dispatch = useDispatch() - let query = useQuery() - const userId = query.get('userId') - const tenantDomain = query.get('tenantDomain') - const userEmail = query.get('userEmail') - const [queryError, setQueryError] = useState(false) - - const { - data: user = {}, - isFetching: userFetching, - error: userError, - } = useListGuestQuery({ tenantDomain, userId }) - - useEffect(() => { - if (!userId || !tenantDomain) { - ModalService.open({ - body: 'Error invalid request, could not load requested user.', - title: 'Invalid Request', - }) - setQueryError(true) - } - }, [tenantDomain, userId, dispatch]) - - return ( - - {userFetching && } - {!userFetching && userError && Error loading user} - {!queryError && !userFetching && ( - - - - - - - - - - - - - - - - - - - - - - - - - - - )} - - ) -} - -ViewGuest.propTypes = { - params: PropTypes.object, - location: PropTypes.object, -} - -export default ViewGuest From 0fcc0ea2ed3c8554bf9e82df94fce3c94540b79d Mon Sep 17 00:00:00 2001 From: Roel van der Wegen Date: Tue, 28 Mar 2023 23:16:35 +0200 Subject: [PATCH 038/124] Removed ExchangeRefreshToken --- deployment/AzureDeploymentTemplate.json | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/deployment/AzureDeploymentTemplate.json b/deployment/AzureDeploymentTemplate.json index 620700934567..bc7eb0ba9efe 100644 --- a/deployment/AzureDeploymentTemplate.json +++ b/deployment/AzureDeploymentTemplate.json @@ -115,18 +115,6 @@ "dependsOn": [ "[resourceId('Microsoft.KeyVault/vaults', variables('uniqueResourceNameBase'))]" ] - }, - { - "type": "secrets", - "name": "exchangerefreshtoken", - "apiVersion": "2015-06-01", - "properties": { - "contentType": "text/plain", - "value": "ExchangeRefreshToken" - }, - "dependsOn": [ - "[resourceId('Microsoft.KeyVault/vaults', variables('uniqueResourceNameBase'))]" - ] } ], "dependsOn": ["[resourceId('Microsoft.Web/sites', variables('funcAppName'))]"] @@ -178,10 +166,6 @@ "name": "RefreshToken", "value": "[concat('@Microsoft.KeyVault(SecretUri=https://',variables('uniqueResourceNameBase'), '.vault.azure.net/secrets/RefreshToken)')]" }, - { - "name": "ExchangeRefreshtoken", - "value": "[concat('@Microsoft.KeyVault(SecretUri=https://',variables('uniqueResourceNameBase'), '.vault.azure.net/secrets/ExchangeRefreshToken)')]" - }, { "name": "TenantID", "value": "[concat('@Microsoft.KeyVault(SecretUri=https://',variables('uniqueResourceNameBase'), '.vault.azure.net/secrets/tenantid)')]" From f9feeb461c6ccd124b75a6f1fddff9d8cd4e6fc1 Mon Sep 17 00:00:00 2001 From: Roel van der Wegen Date: Tue, 28 Mar 2023 23:17:15 +0200 Subject: [PATCH 039/124] Removed ExchangeRefreshToken --- .../AzureDeploymentTemplate_regionoptions.json | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/deployment/AzureDeploymentTemplate_regionoptions.json b/deployment/AzureDeploymentTemplate_regionoptions.json index c187bb7dc914..11fccba7350c 100644 --- a/deployment/AzureDeploymentTemplate_regionoptions.json +++ b/deployment/AzureDeploymentTemplate_regionoptions.json @@ -115,18 +115,6 @@ "dependsOn": [ "[resourceId('Microsoft.KeyVault/vaults', variables('uniqueResourceNameBase'))]" ] - }, - { - "type": "secrets", - "name": "exchangerefreshtoken", - "apiVersion": "2015-06-01", - "properties": { - "contentType": "text/plain", - "value": "ExchangeRefreshToken" - }, - "dependsOn": [ - "[resourceId('Microsoft.KeyVault/vaults', variables('uniqueResourceNameBase'))]" - ] } ], "dependsOn": ["[resourceId('Microsoft.Web/sites', variables('funcAppName'))]"] @@ -178,10 +166,6 @@ "name": "RefreshToken", "value": "[concat('@Microsoft.KeyVault(SecretUri=https://',variables('uniqueResourceNameBase'), '.vault.azure.net/secrets/RefreshToken)')]" }, - { - "name": "ExchangeRefreshtoken", - "value": "[concat('@Microsoft.KeyVault(SecretUri=https://',variables('uniqueResourceNameBase'), '.vault.azure.net/secrets/ExchangeRefreshToken)')]" - }, { "name": "TenantID", "value": "[concat('@Microsoft.KeyVault(SecretUri=https://',variables('uniqueResourceNameBase'), '.vault.azure.net/secrets/tenantid)')]" From 414d55782473a3ee383c087f72fd22a355cdf68c Mon Sep 17 00:00:00 2001 From: Roel van der Wegen Date: Tue, 28 Mar 2023 23:18:36 +0200 Subject: [PATCH 040/124] Removed ExchangeRefreshToken --- deployment/DevAzureDeploymentTemplate.json | 23 ---------------------- 1 file changed, 23 deletions(-) diff --git a/deployment/DevAzureDeploymentTemplate.json b/deployment/DevAzureDeploymentTemplate.json index a653cebc66dd..dee70ee11871 100644 --- a/deployment/DevAzureDeploymentTemplate.json +++ b/deployment/DevAzureDeploymentTemplate.json @@ -37,13 +37,6 @@ "description": "The Refresh token for your Secure Application Model." } }, - "ExchangeRefreshToken": { - "defaultValue": "LongRefreshtoken", - "type": "string", - "metadata": { - "description": "The Exchange Refresh token for your Secure Application Model." - } - }, "GithubRepository": { "defaultValue": "https://github.com/KelvinTegelaar/CIPP", "type": "string", @@ -150,18 +143,6 @@ "dependsOn": [ "[resourceId('Microsoft.KeyVault/vaults', variables('uniqueResourceNameBase'))]" ] - }, - { - "type": "secrets", - "name": "exchangerefreshtoken", - "apiVersion": "2015-06-01", - "properties": { - "contentType": "text/plain", - "value": "[parameters('exchangerefreshtoken')]" - }, - "dependsOn": [ - "[resourceId('Microsoft.KeyVault/vaults', variables('uniqueResourceNameBase'))]" - ] } ], "dependsOn": ["[resourceId('Microsoft.Web/sites', variables('funcAppName'))]"] @@ -213,10 +194,6 @@ "name": "RefreshToken", "value": "[concat('@Microsoft.KeyVault(SecretUri=https://',variables('uniqueResourceNameBase'), '.vault.azure.net/secrets/RefreshToken)')]" }, - { - "name": "ExchangeRefreshtoken", - "value": "[concat('@Microsoft.KeyVault(SecretUri=https://',variables('uniqueResourceNameBase'), '.vault.azure.net/secrets/ExchangeRefreshToken)')]" - }, { "name": "TenantID", "value": "[concat('@Microsoft.KeyVault(SecretUri=https://',variables('uniqueResourceNameBase'), '.vault.azure.net/secrets/tenantid)')]" From 3c71cdd879a60931d8026717d8dff299275bcd1a Mon Sep 17 00:00:00 2001 From: Roel van der Wegen Date: Tue, 28 Mar 2023 23:19:24 +0200 Subject: [PATCH 041/124] Removed ExchangeRefreshToken --- ...AzureDeploymentTemplate_regionoptions.json | 23 ------------------- 1 file changed, 23 deletions(-) diff --git a/deployment/DevAzureDeploymentTemplate_regionoptions.json b/deployment/DevAzureDeploymentTemplate_regionoptions.json index 7af2b9af4905..301d50d5437a 100644 --- a/deployment/DevAzureDeploymentTemplate_regionoptions.json +++ b/deployment/DevAzureDeploymentTemplate_regionoptions.json @@ -37,13 +37,6 @@ "description": "The Refresh token for your Secure Application Model." } }, - "ExchangeRefreshToken": { - "defaultValue": "LongRefreshtoken", - "type": "string", - "metadata": { - "description": "The Exchange Refresh token for your Secure Application Model." - } - }, "GithubRepository": { "defaultValue": "https://github.com/KelvinTegelaar/CIPP", "type": "string", @@ -150,18 +143,6 @@ "dependsOn": [ "[resourceId('Microsoft.KeyVault/vaults', variables('uniqueResourceNameBase'))]" ] - }, - { - "type": "secrets", - "name": "exchangerefreshtoken", - "apiVersion": "2015-06-01", - "properties": { - "contentType": "text/plain", - "value": "[parameters('exchangerefreshtoken')]" - }, - "dependsOn": [ - "[resourceId('Microsoft.KeyVault/vaults', variables('uniqueResourceNameBase'))]" - ] } ], "dependsOn": ["[resourceId('Microsoft.Web/sites', variables('funcAppName'))]"] @@ -213,10 +194,6 @@ "name": "RefreshToken", "value": "[concat('@Microsoft.KeyVault(SecretUri=https://',variables('uniqueResourceNameBase'), '.vault.azure.net/secrets/RefreshToken)')]" }, - { - "name": "ExchangeRefreshtoken", - "value": "[concat('@Microsoft.KeyVault(SecretUri=https://',variables('uniqueResourceNameBase'), '.vault.azure.net/secrets/ExchangeRefreshToken)')]" - }, { "name": "TenantID", "value": "[concat('@Microsoft.KeyVault(SecretUri=https://',variables('uniqueResourceNameBase'), '.vault.azure.net/secrets/tenantid)')]" From 953cd338f025932c2324a6adc27f68eacf1bdcf4 Mon Sep 17 00:00:00 2001 From: BNWEIN Date: Tue, 28 Mar 2023 23:08:17 +0100 Subject: [PATCH 042/124] Added "Invite Guest" function Added "Invite Guest" function Take two! :) --- src/routes.js | 6 + .../identity/administration/InviteGuest.js | 148 ++++++++++++++++++ src/views/identity/administration/Users.js | 15 +- 3 files changed, 167 insertions(+), 2 deletions(-) create mode 100644 src/views/identity/administration/InviteGuest.js diff --git a/src/routes.js b/src/routes.js index a71896e965cf..0290e512fbca 100644 --- a/src/routes.js +++ b/src/routes.js @@ -6,6 +6,7 @@ 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')) const AddUser = React.lazy(() => import('src/views/identity/administration/AddUser')) +const InviteGuest = React.lazy(() => import('src/views/identity/administration/InviteGuest')) const EditUser = React.lazy(() => import('src/views/identity/administration/EditUser')) const ViewUser = React.lazy(() => import('src/views/identity/administration/ViewUser')) const Groups = React.lazy(() => import('src/views/identity/administration/Groups')) @@ -228,6 +229,11 @@ const routes = [ { path: '/identity/administration/users/add', name: 'Add User', component: AddUser }, { path: '/identity/administration/users/edit', name: 'Edit User', component: EditUser }, { path: '/identity/administration/users/view', name: 'View User', component: ViewUser }, + { + path: '/identity/administration/users/InviteGuest', + name: 'Invite Guest', + component: InviteGuest, + }, { path: '/identity/administration/ViewBec', name: 'View BEC', component: ViewBEC }, { path: '/identity/administration', name: 'Administration' }, { path: '/identity/administration/users', name: 'Users', component: Users }, diff --git a/src/views/identity/administration/InviteGuest.js b/src/views/identity/administration/InviteGuest.js new file mode 100644 index 000000000000..2ea2ccce47a3 --- /dev/null +++ b/src/views/identity/administration/InviteGuest.js @@ -0,0 +1,148 @@ +import React from 'react' +import { + CButton, + CCard, + CCardBody, + CCardHeader, + CCardTitle, + CCol, + CForm, + CRow, + CCallout, +} from '@coreui/react' +import { Form } from 'react-final-form' +import { RFFCFormCheck, RFFCFormInput } from 'src/components/forms' +import { CippPage } from 'src/components/layout' +import { useListAdConnectSettingsQuery } from 'src/store/api/adconnect' +import { useLazyGenericPostRequestQuery } from 'src/store/api/app' +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' +import { faCircleNotch } from '@fortawesome/free-solid-svg-icons' +import { useSelector } from 'react-redux' +import { required } from 'src/validators' +import useQuery from 'src/hooks/useQuery' +import { useNavigate } from 'react-router-dom' + +const InviteGuest = () => { + let navigate = useNavigate() + + const tenant = useSelector((state) => state.app.currentTenant) + const { defaultDomainName: tenantDomain } = tenant + let query = useQuery() + const allQueryObj = {} + for (const [key, value] of query.entries()) { + allQueryObj[key] = value + } + const { + data: adconnectsettings = [], + isFetching: adcIsFetching, + error: adcError, + } = useListAdConnectSettingsQuery({ tenantDomain }) + + const [genericPostRequest, postResults] = useLazyGenericPostRequestQuery() + const onSubmit = (values) => { + const shippedValues = { + DisplayName: values.displayName, + Domain: values.primDomain, + Mail: values.mail, + PostalCode: values.postalCode, + RedirectURL: values.RedirectURL, + SendInvite: values.SendInvite, + tenantID: tenantDomain, + } + //window.alert(JSON.stringify(shippedValues)) + genericPostRequest({ path: '/api/AddGuest', values: shippedValues }) + } + + return ( + + {postResults.isSuccess && ( + + {postResults.data?.Results.map((result, index) => ( +
  • {result}
  • + ))} +
    + )} + + + + + Guest Details + + + {adcError && Unable to determine Azure AD Connect Settings} + {!adcIsFetching && adconnectsettings.dirSyncEnabled && ( + + Warning! {adconnectsettings.dirSyncEnabled} This tenant currently has Active + Directory Sync Enabled. This usually means users should be created in Active + Directory + + )} + { + return ( + + + + + + + + + + + + + + + + + + + + + Invite Guest + {postResults.isFetching && ( + + )} + + + + {postResults.isSuccess && ( + + {postResults.data.Results.map((message, idx) => { + return
  • {message}
  • + })} +
    + )} +
    + ) + }} + /> +
    +
    +
    +
    +
    + ) +} + +export default InviteGuest diff --git a/src/views/identity/administration/Users.js b/src/views/identity/administration/Users.js index 92f4ef1f6bd0..3b7a0e3a04e1 100644 --- a/src/views/identity/administration/Users.js +++ b/src/views/identity/administration/Users.js @@ -262,12 +262,23 @@ const columns = [ const Users = (row) => { const tenant = useSelector((state) => state.app.currentTenant) - const titleButton = + const titleButtons = ( +
    + +
    + +
    +
    + ) return ( Date: Wed, 29 Mar 2023 15:10:58 +0100 Subject: [PATCH 043/124] Added SharedMailbox with Account Enabled Report Added Feature Request: https://github.com/KelvinTegelaar/CIPP/issues/1440 --- src/_nav.js | 5 ++ src/routes.js | 8 +++ .../reports/SharedMailboxEnabledAccount.js | 65 +++++++++++++++++++ 3 files changed, 78 insertions(+) create mode 100644 src/views/email-exchange/reports/SharedMailboxEnabledAccount.js diff --git a/src/_nav.js b/src/_nav.js index 3177cc44935d..e5a5d4f3f548 100644 --- a/src/_nav.js +++ b/src/_nav.js @@ -606,6 +606,11 @@ const _nav = [ name: 'Phishing Policies', to: '/email/reports/phishing-policies', }, + { + component: CNavItem, + name: 'Shared Mailbox with Enabled Account', + to: '/email/reports/SharedMailboxEnabledAccount', + }, ], }, { diff --git a/src/routes.js b/src/routes.js index 0290e512fbca..bac1f9bf996f 100644 --- a/src/routes.js +++ b/src/routes.js @@ -173,6 +173,9 @@ const MailboxClientAccessSettingsList = React.lazy(() => const MailboxStatisticsList = React.lazy(() => import('src/views/email-exchange/reports/MailboxStatisticsList'), ) +const SharedMailboxEnabledAccount = React.lazy(() => + import('src/views/email-exchange/reports/SharedMailboxEnabledAccount'), +) const MessageTrace = React.lazy(() => import('src/views/email-exchange/reports/MessageTrace')) const PhishingPoliciesList = React.lazy(() => import('src/views/email-exchange/reports/PhishingPoliciesList'), @@ -574,6 +577,11 @@ const routes = [ path: '/email/reports/mailbox-statistics', component: MailboxStatisticsList, }, + { + name: 'Shared Mailbox Enabled Account', + path: '/email/reports/SharedMailboxEnabledAccount', + component: SharedMailboxEnabledAccount, + }, { name: 'Mailbox Client Access Settings', path: '/email/reports/mailbox-cas-settings', diff --git a/src/views/email-exchange/reports/SharedMailboxEnabledAccount.js b/src/views/email-exchange/reports/SharedMailboxEnabledAccount.js new file mode 100644 index 000000000000..8135b38a3655 --- /dev/null +++ b/src/views/email-exchange/reports/SharedMailboxEnabledAccount.js @@ -0,0 +1,65 @@ +import React from 'react' +import { useSelector } from 'react-redux' +import { CellTip, cellBooleanFormatter } from 'src/components/tables' +import { CippPageList } from 'src/components/layout' + +const columns = [ + { + selector: (row) => row['UserPrincipalName'], + name: 'User Prinicipal Name', + sortable: true, + cell: (row) => CellTip(row['UserPrincipalName']), + exportSelector: 'UserPrincipalName', + minWidth: '200px', + }, + { + selector: (row) => row['displayName'], + name: 'Display Name', + sortable: true, + cell: (row) => CellTip(row['displayName']), + exportSelector: 'displayName', + minWidth: '200px', + }, + { + selector: (row) => row['givenName'], + name: 'First Name', + sortable: true, + cell: (row) => CellTip(row['givenName']), + exportSelector: 'givenName', + minWidth: '200px', + }, + { + selector: (row) => row['surname'], + name: 'Surname', + sortable: true, + cell: (row) => CellTip(row['surname']), + exportSelector: 'surname', + minWidth: '200px', + }, + { + selector: (row) => row['accountEnabled'], + name: 'Account Enabled', + sortable: true, + cell: (row) => CellTip(row['accountEnabled']), + exportSelector: 'accountEnabled', + }, +] + +const SharedMailboxEnabledAccount = () => { + const tenant = useSelector((state) => state.app.currentTenant) + + return ( + + ) +} + +export default SharedMailboxEnabledAccount From 36d48d508efe1223def88559dd5ad35e07c391bc Mon Sep 17 00:00:00 2001 From: BNWEIN Date: Wed, 29 Mar 2023 17:29:07 +0100 Subject: [PATCH 044/124] Update InviteGuest.js Made Redirect URL optional and added some place holder text --- src/views/identity/administration/InviteGuest.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/views/identity/administration/InviteGuest.js b/src/views/identity/administration/InviteGuest.js index 2ea2ccce47a3..c1b46cbdf6fc 100644 --- a/src/views/identity/administration/InviteGuest.js +++ b/src/views/identity/administration/InviteGuest.js @@ -100,8 +100,11 @@ const InviteGuest = () => { From 36e512867c38ca2e13ec85ea84e361c0bfd74d9d Mon Sep 17 00:00:00 2001 From: BNWEIN Date: Wed, 29 Mar 2023 18:00:54 +0100 Subject: [PATCH 045/124] Update Logs.js Changed order of columns and fixed so it shows newest to oldest by default --- src/views/cipp/Logs.js | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/src/views/cipp/Logs.js b/src/views/cipp/Logs.js index 73a956b18b05..e7733a152fff 100644 --- a/src/views/cipp/Logs.js +++ b/src/views/cipp/Logs.js @@ -20,6 +20,20 @@ import { CippDatatable, cellDateFormatter, CellTip } from 'src/components/tables import { useNavigate } from 'react-router-dom' import DatePicker from 'react-datepicker' import 'react-datepicker/dist/react-datepicker.css' +const reverseSort = (rowA, rowB) => { + const a = rowA.DateTime.toLowerCase() + const b = rowB.DateTime.toLowerCase() + + if (a > b) { + return -1 + } + + if (b > a) { + return 1 + } + + return 0 +} const columns = [ { @@ -30,6 +44,7 @@ const columns = [ exportSelector: 'DateTime', minWidth: '145px', maxWidth: '145px', + sortFunction: reverseSort, }, { name: 'Tenant', @@ -41,11 +56,11 @@ const columns = [ maxWidth: '145px', }, { - name: 'API', - selector: (row) => row['API'], + name: 'User', + selector: (row) => row['User'], sortable: true, - cell: (row) => CellTip(row['API']), - exportSelector: 'API', + cell: (row) => CellTip(row['User']), + exportSelector: 'User', minWidth: '145px', maxWidth: '145px', }, @@ -57,11 +72,11 @@ const columns = [ exportSelector: 'Message', }, { - name: 'User', - selector: (row) => row['User'], + name: 'API', + selector: (row) => row['API'], sortable: true, - cell: (row) => CellTip(row['User']), - exportSelector: 'User', + cell: (row) => CellTip(row['API']), + exportSelector: 'API', minWidth: '145px', maxWidth: '145px', }, From 392b30eba7fb2b1abff118b32dfda469f49394e5 Mon Sep 17 00:00:00 2001 From: Roel van der Wegen Date: Fri, 31 Mar 2023 08:57:36 +0200 Subject: [PATCH 046/124] Removed ExchangeRefreshToken input during setup ExchangeRefreshToken has been deprecated --- src/views/cipp/Setup.js | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/views/cipp/Setup.js b/src/views/cipp/Setup.js index 5dd85f962c53..61f5c0f21db4 100644 --- a/src/views/cipp/Setup.js +++ b/src/views/cipp/Setup.js @@ -281,16 +281,6 @@ const Setup = () => { /> - - - - -
    From b28b177d33b02e8d2044a245df4dcd740b8c17cf Mon Sep 17 00:00:00 2001 From: Roel van der Wegen Date: Fri, 31 Mar 2023 09:00:17 +0200 Subject: [PATCH 047/124] Removed ExchangeRefreshToken from home ExchangeRefreshToken has been deprecated --- src/views/home/Home.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/views/home/Home.js b/src/views/home/Home.js index 974ab575da30..f0fc78f8e10a 100644 --- a/src/views/home/Home.js +++ b/src/views/home/Home.js @@ -80,14 +80,10 @@ const Home = () => { - +
    Refresh Token: {!isLoadingDash ? dashboard?.RefreshTokenDate : ''}
    - -
    - Exchange Token: {!isLoadingDash ? dashboard?.ExchangeTokenDate : ''} -
    From af08a60c4f1cf3c1a68b98ad312039929409dfca Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Fri, 31 Mar 2023 12:39:25 +0200 Subject: [PATCH 048/124] version up for release --- package-lock.json | 57 +++++++++++++++++++++------------------ public/version_latest.txt | 2 +- version_latest.txt | 2 +- 3 files changed, 33 insertions(+), 28 deletions(-) diff --git a/package-lock.json b/package-lock.json index 51ada863cb0a..08e6a9e247c5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7107,8 +7107,9 @@ } }, "node_modules/enhanced-resolve": { - "version": "5.9.2", - "license": "MIT", + "version": "5.12.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz", + "integrity": "sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==", "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" @@ -8824,7 +8825,8 @@ }, "node_modules/glob-to-regexp": { "version": "0.4.1", - "license": "BSD-2-Clause" + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" }, "node_modules/global-modules": { "version": "2.0.0", @@ -11851,10 +11853,6 @@ "node": ">=4" } }, - "node_modules/json-parse-better-errors": { - "version": "1.0.2", - "license": "MIT" - }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "license": "MIT" @@ -17528,8 +17526,9 @@ } }, "node_modules/watchpack": { - "version": "2.3.1", - "license": "MIT", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", + "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", "dependencies": { "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" @@ -17555,32 +17554,33 @@ } }, "node_modules/webpack": { - "version": "5.69.1", - "license": "MIT", + "version": "5.77.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.77.0.tgz", + "integrity": "sha512-sbGNjBr5Ya5ss91yzjeJTLKyfiwo5C628AFjEa6WSXcZa4E+F57om3Cc8xLb1Jh0b243AWuSYRf3dn7HVeFQ9Q==", "dependencies": { "@types/eslint-scope": "^3.7.3", "@types/estree": "^0.0.51", "@webassemblyjs/ast": "1.11.1", "@webassemblyjs/wasm-edit": "1.11.1", "@webassemblyjs/wasm-parser": "1.11.1", - "acorn": "^8.4.1", + "acorn": "^8.7.1", "acorn-import-assertions": "^1.7.6", "browserslist": "^4.14.5", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.8.3", + "enhanced-resolve": "^5.10.0", "es-module-lexer": "^0.9.0", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.2.9", - "json-parse-better-errors": "^1.0.2", + "json-parse-even-better-errors": "^2.3.1", "loader-runner": "^4.2.0", "mime-types": "^2.1.27", "neo-async": "^2.6.2", "schema-utils": "^3.1.0", "tapable": "^2.1.1", "terser-webpack-plugin": "^5.1.3", - "watchpack": "^2.3.1", + "watchpack": "^2.4.0", "webpack-sources": "^3.2.3" }, "bin": { @@ -22755,7 +22755,9 @@ "dev": true }, "enhanced-resolve": { - "version": "5.9.2", + "version": "5.12.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz", + "integrity": "sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==", "requires": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" @@ -23851,7 +23853,9 @@ } }, "glob-to-regexp": { - "version": "0.4.1" + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" }, "global-modules": { "version": "2.0.0", @@ -25730,9 +25734,6 @@ "jsesc": { "version": "2.5.2" }, - "json-parse-better-errors": { - "version": "1.0.2" - }, "json-parse-even-better-errors": { "version": "2.3.1" }, @@ -29235,7 +29236,9 @@ } }, "watchpack": { - "version": "2.3.1", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", + "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", "requires": { "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" @@ -29253,31 +29256,33 @@ "dev": true }, "webpack": { - "version": "5.69.1", + "version": "5.77.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.77.0.tgz", + "integrity": "sha512-sbGNjBr5Ya5ss91yzjeJTLKyfiwo5C628AFjEa6WSXcZa4E+F57om3Cc8xLb1Jh0b243AWuSYRf3dn7HVeFQ9Q==", "requires": { "@types/eslint-scope": "^3.7.3", "@types/estree": "^0.0.51", "@webassemblyjs/ast": "1.11.1", "@webassemblyjs/wasm-edit": "1.11.1", "@webassemblyjs/wasm-parser": "1.11.1", - "acorn": "^8.4.1", + "acorn": "^8.7.1", "acorn-import-assertions": "^1.7.6", "browserslist": "^4.14.5", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.8.3", + "enhanced-resolve": "^5.10.0", "es-module-lexer": "^0.9.0", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.2.9", - "json-parse-better-errors": "^1.0.2", + "json-parse-even-better-errors": "^2.3.1", "loader-runner": "^4.2.0", "mime-types": "^2.1.27", "neo-async": "^2.6.2", "schema-utils": "^3.1.0", "tapable": "^2.1.1", "terser-webpack-plugin": "^5.1.3", - "watchpack": "^2.3.1", + "watchpack": "^2.4.0", "webpack-sources": "^3.2.3" }, "dependencies": { diff --git a/public/version_latest.txt b/public/version_latest.txt index a4f52a5dbb5a..0fa4ae489037 100644 --- a/public/version_latest.txt +++ b/public/version_latest.txt @@ -1 +1 @@ -3.2.0 \ No newline at end of file +3.3.0 \ No newline at end of file diff --git a/version_latest.txt b/version_latest.txt index 0444f3207675..0fa4ae489037 100644 --- a/version_latest.txt +++ b/version_latest.txt @@ -1 +1 @@ -3.2.1 \ No newline at end of file +3.3.0 \ No newline at end of file From 34360562edaec7cf90d56d696d01a4be056c35a1 Mon Sep 17 00:00:00 2001 From: Roel van der Wegen Date: Sun, 2 Apr 2023 20:32:44 +0200 Subject: [PATCH 049/124] Changed mention of templates to alerts --- src/views/tenant/administration/ListAlertsQueue.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/views/tenant/administration/ListAlertsQueue.js b/src/views/tenant/administration/ListAlertsQueue.js index 4d6bf2e72e8f..485c11b5444c 100644 --- a/src/views/tenant/administration/ListAlertsQueue.js +++ b/src/views/tenant/administration/ListAlertsQueue.js @@ -167,11 +167,11 @@ const ListAlertsQueue = () => { selectableRows: true, actionsList: [ { - label: 'Delete Template', + label: 'Delete alerts', color: 'info', modal: true, modalUrl: `/api/RemoveQueuedAlert?ID=!tenantId`, - modalMessage: 'Are you sure you want to delete these templates?', + modalMessage: 'Are you sure you want to delete these alerts?', }, ], }, From 7925bba4076f901997967ec50c7270aad1738707 Mon Sep 17 00:00:00 2001 From: BNWEIN Date: Tue, 4 Apr 2023 10:20:22 +0100 Subject: [PATCH 050/124] Added Ability to disable MFA Nudges Standard Added Ability to disable MFA Nudges Standard @KelvinTegelaar please can you fix the output at the end of applying the standard --- src/data/standards.json | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/data/standards.json b/src/data/standards.json index 72b083fb4aaa..450f2cbc123f 100644 --- a/src/data/standards.json +++ b/src/data/standards.json @@ -161,11 +161,18 @@ }, { "cat": "AAD", - "name": "standards.NudgeMFA", + "name": "standards.NudgeMFA.enable", "helpText": "This is the default helptext", "addedComponent": null, "label": "Request to setup Authenticator if not setup yet." }, + { + "cat": "AAD", + "name": "standards.NudgeMFA.disable", + "helpText": "This is the default helptext", + "addedComponent": null, + "label": "Disables the request to setup Authenticator if setup." + }, { "cat": "AAD", "name": "standards.DisableSelfServiceLicenses", From e7187660af96e9deeda19ca7c16afd02ee8a2264 Mon Sep 17 00:00:00 2001 From: John Duprey Date: Fri, 7 Apr 2023 21:01:55 -0400 Subject: [PATCH 051/124] GDAP Role Wizard Break out GDAP Role to Group mapping to separate wizard --- src/_nav.js | 10 ++ src/adminRoutes.js | 12 ++ .../tenant/administration/GDAPRoleWizard.js | 139 ++++++++++++++++++ src/views/tenant/administration/GDAPWizard.js | 16 +- .../tenant/administration/ListGDAPRoles.js | 38 +++++ 5 files changed, 205 insertions(+), 10 deletions(-) create mode 100644 src/views/tenant/administration/GDAPRoleWizard.js create mode 100644 src/views/tenant/administration/ListGDAPRoles.js diff --git a/src/_nav.js b/src/_nav.js index e5a5d4f3f548..2f6644b6ac11 100644 --- a/src/_nav.js +++ b/src/_nav.js @@ -649,6 +649,16 @@ const _nav = [ to: '/cipp/gdap', icon: , items: [ + { + component: CNavItem, + name: 'Role Wizard', + to: '/tenant/administration/gdap-role-wizard', + }, + { + component: CNavItem, + name: 'GDAP Roles', + to: '/tenant/administration/gdap-roles', + }, { component: CNavItem, name: 'Migration Wizard', diff --git a/src/adminRoutes.js b/src/adminRoutes.js index fab00d4080e5..e33468c53952 100644 --- a/src/adminRoutes.js +++ b/src/adminRoutes.js @@ -4,6 +4,8 @@ const Setup = React.lazy(() => import('src/views/cipp/Setup')) const ApplyStandard = React.lazy(() => import('src/views/tenant/standards/ApplyStandard')) const GDAPStatus = React.lazy(() => import('src/views/tenant/administration/ListGDAPQueue')) const GDAP = React.lazy(() => import('src/views/tenant/administration/GDAPWizard')) +const GDAPRoleWizard = React.lazy(() => import('src/views/tenant/administration/GDAPRoleWizard')) +const GDAPRoles = React.lazy(() => import('src/views/tenant/administration/ListGDAPRoles')) const appapproval = React.lazy(() => import('src/views/cipp/AppApproval')) const adminRoutes = [ @@ -12,6 +14,16 @@ const adminRoutes = [ { path: '/cipp/settings', name: 'Settings', component: CIPPSettings }, { path: '/cipp/setup', name: 'Setup', component: Setup }, { path: '/tenant/administration/gdap', name: 'GDAP Wizard', component: GDAP }, + { + path: '/tenant/administration/gdap-role-wizard', + name: 'GDAP Role Wizard', + component: GDAPRoleWizard, + }, + { + path: '/tenant/administration/gdap-roles', + name: 'GDAP Roles', + component: GDAPRoles, + }, { path: '/tenant/administration/appapproval', name: 'App Approval', component: appapproval }, { path: '/tenant/administration/gdap-status', name: 'GDAP Status', component: GDAPStatus }, { path: '/tenant/standards/apply-standard', name: 'Apply Standard', component: ApplyStandard }, diff --git a/src/views/tenant/administration/GDAPRoleWizard.js b/src/views/tenant/administration/GDAPRoleWizard.js new file mode 100644 index 000000000000..ec44a8c5ab50 --- /dev/null +++ b/src/views/tenant/administration/GDAPRoleWizard.js @@ -0,0 +1,139 @@ +import React from 'react' +import { CCol, CRow, CForm, CCallout, CSpinner, CButton } from '@coreui/react' +import { Field, FormSpy } from 'react-final-form' +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' +import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons' +import { CippWizard } from 'src/components/layout' +import { WizardTableField } from 'src/components/tables' +import PropTypes from 'prop-types' +import { useLazyGenericGetRequestQuery, useLazyGenericPostRequestQuery } from 'src/store/api/app' + +const Error = ({ name }) => ( + + touched && error ? ( + + + {error} + + ) : null + } + /> +) + +Error.propTypes = { + name: PropTypes.string.isRequired, +} + +const requiredArray = (value) => (value && value.length !== 0 ? undefined : 'Required') + +const GDAPRoleWizard = () => { + const [genericPostRequest, postResults] = useLazyGenericPostRequestQuery() + const [genericGetRequest, getResults] = useLazyGenericGetRequestQuery() + + const handleSubmit = async (values) => { + genericPostRequest({ path: '/api/ExecAddGDAPRole', values: values }) + } + + const formValues = {} + + return ( + + +
    +

    Step 1

    +
    + Select which roles you want to map to Groups in your Partner Tenant +
    +
    +
    + + + For each role you select a new group will be created inside of your partner tenant + called "M365 GDAP RoleName". Add your users to these new groups to set their GDAP + permissions. + + + {(props) => ( + row['Name'], + sortable: true, + exportselector: 'Name', + }, + { + name: 'Description', + selector: (row) => row['Description'], + sortable: true, + }, + ]} + fieldProps={props} + /> + )} + + + +
    +
    + +
    +

    Step 2

    +
    Confirm and apply
    +
    +
    + {!postResults.isSuccess && ( + + {(props) => { + return ( + <> + + + +
    Roles and group names
    + + {props.values.gdapRoles.map((role, idx) => ( +
  • + {role.Name} - M365 GDAP {role.Name} +
  • + ))} +
    +
    +
    + + ) + }} +
    + )} + {postResults.isFetching && ( + + Loading + + )} + {postResults.isSuccess && ( + + {postResults.data.Results.map((message, idx) => { + return
  • {message}
  • + })} +
    + )} +
    +
    +
    + ) +} + +export default GDAPRoleWizard diff --git a/src/views/tenant/administration/GDAPWizard.js b/src/views/tenant/administration/GDAPWizard.js index 6ccac1b57599..adbfa782ed43 100644 --- a/src/views/tenant/administration/GDAPWizard.js +++ b/src/views/tenant/administration/GDAPWizard.js @@ -120,7 +120,7 @@ const GDAPWizard = () => {

    Step 3

    @@ -131,10 +131,6 @@ const GDAPWizard = () => {
    - For each role you select a new group will be created inside of your partner tenant - called "M365 GDAP RoleName". Add your users to these new groups to set their GDAP - permissions. -

    CIPP will create a single relationship with all roles you've selected for the maximum duration of 730 days using a GUID as a random name for the relationship.
    It is recommend to put CIPP user in the correct GDAP Role Groups to manage your @@ -145,17 +141,17 @@ const GDAPWizard = () => { row['Name'], + selector: (row) => row['RoleName'], sortable: true, exportselector: 'Name', }, { - name: 'Description', - selector: (row) => row['Description'], + name: 'Group', + selector: (row) => row['GroupName'], sortable: true, }, ]} @@ -193,7 +189,7 @@ const GDAPWizard = () => { {props.values.gdapRoles.map((role, idx) => (
  • - {role.Name} - M365 GDAP {role.Name} + {role.RoleName} - {role.GroupName}
  • ))}
    diff --git a/src/views/tenant/administration/ListGDAPRoles.js b/src/views/tenant/administration/ListGDAPRoles.js new file mode 100644 index 000000000000..e3e953e13352 --- /dev/null +++ b/src/views/tenant/administration/ListGDAPRoles.js @@ -0,0 +1,38 @@ +import React from 'react' +import { useSelector } from 'react-redux' +import { CSpinner, CCallout } from '@coreui/react' +import { CippPageList } from 'src/components/layout' + +const ListGDAPRoles = () => { + const columns = [ + { + name: 'Role', + selector: (row) => row['RoleName'], + sortable: true, + exportSelector: 'RoleName', + }, + { + name: 'Group', + selector: (row) => row['GroupName'], + sortable: true, + exportSelector: 'GroupName', + }, + ] + return ( +
    + +
    + ) +} + +export default ListGDAPRoles From ebd1268265d29032df07747cbe08cc42ff4d2bb4 Mon Sep 17 00:00:00 2001 From: John Duprey Date: Sat, 8 Apr 2023 07:46:35 -0400 Subject: [PATCH 052/124] Reorder GDAP wizard steps Put role selection before tenants --- src/views/tenant/administration/GDAPWizard.js | 77 ++++++++++--------- 1 file changed, 39 insertions(+), 38 deletions(-) diff --git a/src/views/tenant/administration/GDAPWizard.js b/src/views/tenant/administration/GDAPWizard.js index adbfa782ed43..708666bce6cd 100644 --- a/src/views/tenant/administration/GDAPWizard.js +++ b/src/views/tenant/administration/GDAPWizard.js @@ -45,7 +45,7 @@ const GDAPWizard = () => { onSubmit={handleSubmit} wizardTitle="GDAP Migration Wizard" > - +

    Step 1

    Setup GDAP Migration tool
    @@ -82,48 +82,13 @@ const GDAPWizard = () => { )}
    - -
    -

    Step 2

    -
    Choose a tenant
    -
    -
    - - {(props) => ( - row['displayName'], - sortable: true, - exportselector: 'displayName', - }, - { - name: 'Default Domain Name', - selector: (row) => row['defaultDomainName'], - sortable: true, - exportselector: 'mail', - }, - ]} - fieldProps={props} - /> - )} - - -
    -
    +
    -

    Step 3

    +

    Step 2

    Select which roles you want to add to GDAP relationship.
    @@ -163,6 +128,42 @@ const GDAPWizard = () => {
    + +
    +

    Step 3

    +
    Choose a tenant
    +
    +
    + + {(props) => ( + row['displayName'], + sortable: true, + exportselector: 'displayName', + }, + { + name: 'Default Domain Name', + selector: (row) => row['defaultDomainName'], + sortable: true, + exportselector: 'mail', + }, + ]} + fieldProps={props} + /> + )} + + +
    +

    Step 4

    From 54f1009802b2eab3edc4514a2fbf7422297aa0ad Mon Sep 17 00:00:00 2001 From: John Duprey Date: Sat, 8 Apr 2023 07:56:10 -0400 Subject: [PATCH 053/124] Add Map GDAP roles button --- src/views/tenant/administration/ListGDAPRoles.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/views/tenant/administration/ListGDAPRoles.js b/src/views/tenant/administration/ListGDAPRoles.js index e3e953e13352..f7279740b20c 100644 --- a/src/views/tenant/administration/ListGDAPRoles.js +++ b/src/views/tenant/administration/ListGDAPRoles.js @@ -2,6 +2,7 @@ import React from 'react' import { useSelector } from 'react-redux' import { CSpinner, CCallout } from '@coreui/react' import { CippPageList } from 'src/components/layout' +import { TitleButton } from 'src/components/buttons' const ListGDAPRoles = () => { const columns = [ @@ -23,6 +24,9 @@ const ListGDAPRoles = () => { + } tenantSelector={false} datatable={{ keyField: 'id', From 71119fcc993acea16c43fbc7a456358ff377428a Mon Sep 17 00:00:00 2001 From: John Duprey Date: Sat, 8 Apr 2023 17:54:28 -0400 Subject: [PATCH 054/124] Add link to Role wizard in GDAP wizard --- src/views/tenant/administration/GDAPWizard.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/views/tenant/administration/GDAPWizard.js b/src/views/tenant/administration/GDAPWizard.js index 708666bce6cd..b8c110be6c9c 100644 --- a/src/views/tenant/administration/GDAPWizard.js +++ b/src/views/tenant/administration/GDAPWizard.js @@ -5,6 +5,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons' import { CippWizard } from 'src/components/layout' import { WizardTableField } from 'src/components/tables' +import { TitleButton } from 'src/components/buttons' import PropTypes from 'prop-types' import { useLazyGenericGetRequestQuery, useLazyGenericPostRequestQuery } from 'src/store/api/app' @@ -101,6 +102,9 @@ const GDAPWizard = () => {
    It is recommend to put CIPP user in the correct GDAP Role Groups to manage your environment secure after deployment of GDAP. +
    + +
    {(props) => ( Date: Sat, 8 Apr 2023 20:11:32 -0400 Subject: [PATCH 055/124] Job History offcanvas --- src/components/header/AppHeaderDropdown.js | 62 ++++++++++++++++++++-- 1 file changed, 59 insertions(+), 3 deletions(-) diff --git a/src/components/header/AppHeaderDropdown.js b/src/components/header/AppHeaderDropdown.js index bb0a0246ca72..f2baf4c25c0e 100644 --- a/src/components/header/AppHeaderDropdown.js +++ b/src/components/header/AppHeaderDropdown.js @@ -1,4 +1,4 @@ -import React, { useState } from 'react' +import React, { useState, useEffect } from 'react' import { CAvatar, CDropdown, @@ -7,15 +7,49 @@ import { CDropdownToggle, CLink, } from '@coreui/react' -import { faUser, faBook, faSignOutAlt } from '@fortawesome/free-solid-svg-icons' +import { faUser, faBook, faSignOutAlt, faHistory, faTrash } from '@fortawesome/free-solid-svg-icons' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { Link } from 'react-router-dom' import { authApi } from 'src/store/api/auth' -import { CippProfile, CippOffcanvas } from 'src/components/utilities' +import { CippProfile, CippOffcanvas, CippActionsOffcanvas } from 'src/components/utilities' +import { useLazyGenericGetRequestQuery } from 'src/store/api/app' const AppHeaderDropdown = () => { const [profileVisible, setProfileVisible] = useState(false) + const [cippQueueExtendedInfo, setCippQueueExtendedInfo] = useState([]) + const [cippQueueVisible, setCippQueueVisible] = useState(false) + const [cippQueueRefresh, setCippQueueRefresh] = useState('') const { data: profile } = authApi.endpoints.loadClientPrincipal.useQueryState() + + const [getCippQueueList, cippQueueList] = useLazyGenericGetRequestQuery() + + function loadCippQueue() { + setCippQueueVisible(true) + setCippQueueRefresh((Math.random() + 1).toString(36).substring(7)) + getCippQueueList({ path: `api/ListCippQueue?refresh=${cippQueueRefresh}` }) + } + + useEffect(() => { + if (cippQueueList.isFetching) { + setCippQueueExtendedInfo([{ label: 'Fetching recent jobs', value: 'Please wait' }]) + } + if ( + cippQueueList.isSuccess && + Array.isArray(cippQueueList.data) && + cippQueueList.data.length > 0 + ) { + setCippQueueExtendedInfo( + cippQueueList.data?.map((job) => ({ + label: `${job.Name}`, + value: job.Status, + })), + ) + } else { + setCippQueueExtendedInfo([{ label: 'No jobs to display', value: '' }]) + } + console.log(cippQueueList) + }, [cippQueueList]) + return ( <> @@ -30,6 +64,10 @@ const AppHeaderDropdown = () => { Profile + loadCippQueue()}> + + Recent Jobs + Logbook @@ -49,6 +87,24 @@ const AppHeaderDropdown = () => { > + , + }, + ]} + placement="end" + visible={cippQueueVisible} + id="cipp-queue" + hideFunction={() => setCippQueueVisible(false)} + /> ) } From 4dd059016e3e576a636c29694e60f351417ea74a Mon Sep 17 00:00:00 2001 From: John Duprey Date: Sun, 9 Apr 2023 21:25:42 -0400 Subject: [PATCH 056/124] Add custom suffix feature --- .../tenant/administration/GDAPRoleWizard.js | 72 ++++++++++++------- 1 file changed, 48 insertions(+), 24 deletions(-) diff --git a/src/views/tenant/administration/GDAPRoleWizard.js b/src/views/tenant/administration/GDAPRoleWizard.js index ec44a8c5ab50..b225d5cb0751 100644 --- a/src/views/tenant/administration/GDAPRoleWizard.js +++ b/src/views/tenant/administration/GDAPRoleWizard.js @@ -1,5 +1,5 @@ import React from 'react' -import { CCol, CRow, CForm, CCallout, CSpinner, CButton } from '@coreui/react' +import { CCol, CRow, CForm, CCallout, CSpinner } from '@coreui/react' import { Field, FormSpy } from 'react-final-form' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons' @@ -7,6 +7,7 @@ import { CippWizard } from 'src/components/layout' import { WizardTableField } from 'src/components/tables' import PropTypes from 'prop-types' import { useLazyGenericGetRequestQuery, useLazyGenericPostRequestQuery } from 'src/store/api/app' +import { RFFCFormInput } from 'src/components/forms' const Error = ({ name }) => ( { For each role you select a new group will be created inside of your partner tenant called "M365 GDAP RoleName". Add your users to these new groups to set their GDAP - permissions. + permissions. If you need to segment your groups for different teams or to define custom + permissions, use the Custom Suffix to create additional group mappings per role. - - {(props) => ( - row['Name'], - sortable: true, - exportselector: 'Name', - }, - { - name: 'Description', - selector: (row) => row['Description'], - sortable: true, - }, - ]} - fieldProps={props} + + + - )} - + + + + + + {(props) => ( + row['Name'], + sortable: true, + exportselector: 'Name', + }, + { + name: 'Description', + selector: (row) => row['Description'], + sortable: true, + }, + ]} + fieldProps={props} + /> + )} + + +
    @@ -111,6 +127,14 @@ const GDAPRoleWizard = () => { ))} + {props.values.customSuffix != null && ( + <> +
    Custom Group Suffix
    + +
  • {props.values.customSuffix}
  • +
    + + )} From 3aa0882f9f07c1a47e0f78359af1f39256a5dba7 Mon Sep 17 00:00:00 2001 From: John Duprey Date: Mon, 10 Apr 2023 16:12:09 -0400 Subject: [PATCH 057/124] Add start gdap migration button to role wizard --- .../tenant/administration/GDAPRoleWizard.js | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/views/tenant/administration/GDAPRoleWizard.js b/src/views/tenant/administration/GDAPRoleWizard.js index b225d5cb0751..26c56de51a4d 100644 --- a/src/views/tenant/administration/GDAPRoleWizard.js +++ b/src/views/tenant/administration/GDAPRoleWizard.js @@ -1,5 +1,5 @@ import React from 'react' -import { CCol, CRow, CForm, CCallout, CSpinner } from '@coreui/react' +import { CCol, CRow, CForm, CCallout, CSpinner, CButton } from '@coreui/react' import { Field, FormSpy } from 'react-final-form' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons' @@ -8,6 +8,7 @@ import { WizardTableField } from 'src/components/tables' import PropTypes from 'prop-types' import { useLazyGenericGetRequestQuery, useLazyGenericPostRequestQuery } from 'src/store/api/app' import { RFFCFormInput } from 'src/components/forms' +import { Link } from 'react-router-dom' const Error = ({ name }) => ( { )} {postResults.isSuccess && ( - - {postResults.data.Results.map((message, idx) => { - return
  • {message}
  • - })} -
    + <> + + {postResults.data.Results.map((message, idx) => { + return
  • {message}
  • + })} +
    + + Start GDAP Migration + + )}
    From 5f80792de0db85fc39ecdb02a1144fd8fb61bb4c Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Thu, 13 Apr 2023 15:35:28 +0200 Subject: [PATCH 058/124] updated text. --- 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 450f2cbc123f..65db91dab662 100644 --- a/src/data/standards.json +++ b/src/data/standards.json @@ -150,7 +150,7 @@ "name": "standards.LegacyMFA", "helpText": "This is the default helptext", "addedComponent": null, - "label": "Enable per-user MFA for all user (Legacy)" + "label": "Enable per-user MFA for all user (Legacy, Requires DAP.)" }, { "cat": "AAD", From c1b7a4d77970f9b94a840ac377fc1d148e7bc00b Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Mon, 17 Apr 2023 14:53:05 +0200 Subject: [PATCH 059/124] added execution of current file as priority for local dev. --- .vscode/launch.json | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.vscode/launch.json b/.vscode/launch.json index fcd6fc8d6c56..e8f4c409c8fb 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,6 +1,13 @@ { "version": "0.2.0", "configurations": [ + { + "name": "PowerShell: Execute current file", + "type": "PowerShell", + "request": "launch", + "script": "${file}", + "cwd": "${file}" + }, { "command": "npm run start-api", "name": "Run emulator", From e7fdcb2af057e40467c52139457a1455bca3bcfe Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Mon, 17 Apr 2023 22:39:16 +0200 Subject: [PATCH 060/124] modern readme --- README.md | 142 +----------------------------------------------------- 1 file changed, 1 insertion(+), 141 deletions(-) diff --git a/README.md b/README.md index 9e42be1b45e1..7cbd7845e426 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,6 @@

    ![OIT](github_assets/img/oitpsonsor_light.png)     -![Genuine Technology Services](github_assets/img/Genuine-logo-vertical-light.png)     ![Immybot](github_assets/img/Immybot.png)     ![NinjaOne](github_assets/img/NinjaOne-Light.png#gh-dark-mode-only) ![NinjaOne](github_assets/img/NinjaOne-Dark.png#gh-light-mode-only)     @@ -31,143 +30,4 @@ The CyberDrain Improved Partner Portal is a portal to help manage administration This project is a way to help you with administration, with user management, and deploying your own preferred standards. It's not a replacement for security tools, or a way to cut costs on specific subscriptions. The tool should assist you in removing the gripes with standard partner management and save you several hours per engineer per month. -# Deployment and Getting Started - -If you want to self-host, check out the installation manual [here](https://cipp.app/GettingStarted/Installation/). You will need some knowledge of Static Web Apps, Azure Functions, and Azure Keyvault - -# Why are you making this? - -I'm kind of done waiting for vendors to catch up to what we actually need. All RMM vendors are dramaticaly slow adopting cloud management. Microsoft themselves don't understand the Managed services markets, there are vendors that have tried jumping into the gap but either have unreasonable fees, weird constructions, require Global Admins without MFA, or just don't innovate at a pace that is required of cloud services right now. - -I'm also annoyed the untransparent behaviour that many companies in our market are showing. Most are claiming that working with the Microsoft Partner APIs is difficult, and requires a very heavy development team. I'm a guy that had no webdesign knowledge before this and created the first release of this app in 3 weekends. Vendors that claim high difficulty or issues with integration are simply not giving this _any_ priority. - -I was recently on a call with one of my friends and he said he was changing the world. That insipred me to change the world just a little bit too. :) I'm hoping that this is one of the tools that make you smile. - -# What's the pricing? - -This project is **FREE** but we do have a **Sponsorware** component. The sponsorware structure for this project is pretty simple; the code is available to everyone and free to use. You will need some technical know-how to put it all together. Sponsors receive the following benefits - -### For users of the project that sponsor: - -- The project will be hosted for you. -- The hosted version will always be the latest release and automatically updated. -- You'll also receive a staging environment with the latest (nightly/beta) build, to see new features before anyone else. -- You will receive priority on support issues reported on GitHub. -- You will be able to make 1 priortized feature request per month. - -Sponsorship allows me to sink some more time into this project and keep it free, so please consider it. :) - -### For company sponsors, depending on sponsor level you can get the following benefits; - -- Your company logo will be featured on this readme page at the top. -- Your company logo will be featured on https://cyberdrain.com -- A small version of your company logo with a link to your homepage will be on the footer, each user will see this on each page. - -# How does it look?! - -Check out the GIFs below to see how some of the workflows work. - - - - - - - - - -# What is the functionality? - -The current build functionality is described below, also check out our Changelog in the documentation folder, as the tool has a very rapid development schedule the list below might be out of date. - -## Identity Management - -- Manage M365 users - - List users, email addreses, and licenses. - - View & Edit user settings - - Research if user has been compromised - - Send user an MFA push to confirm their identity - - Convert a user to a shared mailbox - - Block signin, reset passwords - - Delete users -- Manage M365 groups - - List all M365 groups, group types, and e-mail addresses. - - Edit members and group owners -- Offboard users via an easy wizard - - Remove user licenses - - Convert user to shared mailbox - - Disable user sign-in - - Reset user password - - Remove user from all groups - - Hide user from address list - - Set Out of Office - - Give other user access to mailbox, and OneDrive - -## Tenants - -- Manage M365 tenants - - List all tenants and quick-links to the most user portals using delegated access. - - Edit Partner tenant names and default domain for your CSP partner environment - - List tenant conditional access policies - - Apply standard configuration to tenant on a repeat schedule. - - Execute a best practice analysis daily and report on best practice settings - - Analyse current domains, and domains outside of M365 for optimal security settings - - List alerts for tenants - -## Endpoint Management - -- Applications - - List all applications in tenants - - List installation status of a specific application per device - - Add Office Apps to multiple tenants - - Add/Remove Chocolatey Apps to multiple tenants - - Assign Apps to All Devices or All Users - - Report on installation status -- Autopilot - - Manage and create autopilot devices, profiles, status pages. -- Intune - - List Intune policies - - Apply Intune Policies - - Add Intune Policy Templates to deploy over multiple tenants - -## Teams & SharePoint - -- List OneDrive, Teams, and SharePoint usage -- View current Teams, installed applications, Team owners, members, and channels -- Add and edit Teams, members, owners and apps. -- Tenant Alerting - -## Exchange - -- View mailboxes and contacts -- View user mobile devices -- Convert mailboxes to shared or user mailboxes -- Report mailbox statistics, client access settings -- Perform message traces -- Change and view phishing policies. - -## Application settings - -- Use multiple user levels (readonly, editor, admin) to manage access -- Allow excluding of tenants -- Send automated alert emails to webhook or e-mail - -# Security - -Authentication is handled by Azure AD using static web apps security. This means the API is only reachable for authenticated users you've invited. For most of the security info related to that check out our staticwebapp.config.json and/or the doc pages on static web apps. Do you see something that might be a security risk, even the smallest? report it and we will handle it asap. Check out our security reporting options [here](https://github.com/KelvinTegelaar/CIPP/security) - -# Contributions - -Feel free to send pull requests or fill out issues when you encounter them, sponsors get a priority on issues and bugs. I'm also completely open to adding direct maintainers/contributors and working together. - -If you decide to contribute; remember that keeping the portal fast is a key component. CIPP is supposed to go brrrrr, any improvements that help with speed are welcomed. - -## Special thanks - -I'd like to give special thanks to the people that made this project possible; - -- [Kyle Hanslovan](https://huntress.com) -- [Ray Orsini](https://oit.co) -- The Team at [MSP.zone/MSP'R'Us](https://msp.zone) -- Gavin Stone at [MSPGeek](https://mspgeek.org) -- MSP2.0 for helping with some visual input. -- Scott, Chris, Jon, and others that helped me with some of the internals of the app. +for more information, we recommend checking out our website [here](https://cipp.app) From 93d8f3cebac72c2a81d569eaf0ece2618b46c2f6 Mon Sep 17 00:00:00 2001 From: BNWEIN Date: Tue, 18 Apr 2023 14:17:57 +0100 Subject: [PATCH 061/124] Fixed Device Compliance, and added ability to subscriber users to Office 365 Groups Fixed Device Compliance, and added ability to subscriber users to Office 365 Groups --- src/components/tables/CellBoolean.js | 6 ++++-- src/views/identity/administration/EditGroup.js | 8 ++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/components/tables/CellBoolean.js b/src/components/tables/CellBoolean.js index 30962b8ec8aa..98f69dfa1adc 100644 --- a/src/components/tables/CellBoolean.js +++ b/src/components/tables/CellBoolean.js @@ -44,13 +44,15 @@ export default function CellBoolean({ cell.toLowerCase() === 'success' || cell.toLowerCase() === 'enabled' || cell.toLowerCase() === 'pass' || - cell.toLowerCase() === 'true' + cell.toLowerCase() === 'true' || + cell.toLowerCase() === 'compliant' ) { normalized = true } else if ( cell.toLowerCase() === 'fail' || cell.toLowerCase() === 'default' || - cell.toLowerCase() === 'false' + cell.toLowerCase() === 'false' || + cell.toLowerCase() === 'noncompliant' ) { normalized = false } diff --git a/src/views/identity/administration/EditGroup.js b/src/views/identity/administration/EditGroup.js index 796992213c1a..bc27feebc675 100644 --- a/src/views/identity/administration/EditGroup.js +++ b/src/views/identity/administration/EditGroup.js @@ -110,6 +110,8 @@ const EditGroup = () => { AddContacts: values.AddContacts ? values.AddContacts : '', RemoveContacts: values.RemoveContacts ? values.RemoveContacts : '', allowExternal: values.allowExternal, + sendCopies: values.sendCopies, + mail: group[0].mail, } //window.alert(JSON.stringify(shippedValues)) genericPostRequest({ path: '/api/EditGroup', values: shippedValues }) @@ -235,6 +237,12 @@ const EditGroup = () => { label="Let people outside the organization email the group" /> )} + {group[0].calculatedGroupType === 'Microsoft 365' && ( + + )} From 38d806d2b7ef79f1909f6dc399545a4afebf96d9 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Tue, 18 Apr 2023 19:32:01 +0200 Subject: [PATCH 062/124] Update README.md --- README.md | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/README.md b/README.md index 9e42be1b45e1..6b350fa81646 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,6 @@ ![CyberDrain Light](github_assets/img/CIPP.png#gh-dark-mode-only) ![CyberDrain Dark](github_assets/img/CIPP-Light.png#gh-light-mode-only) -


    - -[![GitHub Latest Release](https://img.shields.io/github/v/release/KelvinTegelaar/CIPP?label=Latest%20Release&style=for-the-badge)](https://github.com/KelvinTegelaar/CIPP/releases) -![CodeQL Security Analysis Status](https://img.shields.io/github/workflow/status/KelvinTegelaar/CIPP/CodeQL?label=CodeQL%20Security&style=for-the-badge) -[![GitHub Enhancement Requests](https://img.shields.io/github/issues/KelvinTegelaar/CIPP/enhancement?label=Enhancement%20Requests&style=for-the-badge)](https://github.com/KelvinTegelaar/CIPP/issues?q=is%3Aopen+is%3Aissue+label%3Aenhancement) -[![GitHub Bugs](https://img.shields.io/github/issues/KelvinTegelaar/CIPP/bug?label=Bugs&style=for-the-badge)](https://github.com/KelvinTegelaar/CIPP/issues?q=is%3Aopen+is%3Aissue+label%3Aenhancement+label%3Abug) -[![Discord](https://img.shields.io/discord/905453405936447518?label=Discord&style=for-the-badge)](https://discord.com/invite/cyberdrain) -[![GitHub Sponsors](https://img.shields.io/github/sponsors/KelvinTegelaar?label=Public%20Sponsors&style=for-the-badge)](https://github.com/sponsors/KelvinTegelaar) - -
    -

    Sponsored by

    From 99579683f35b2f1522935709fcc6b0b3cfc1541a Mon Sep 17 00:00:00 2001 From: BNWEIN Date: Thu, 20 Apr 2023 10:02:39 +0100 Subject: [PATCH 063/124] Added New Functionality MobileDeviceList Page Added New Functionality Mobile Device List Page Allow Device Block Device Remove Device --- .../administration/ViewMobileDevices.js | 251 ++++++++++++------ 1 file changed, 173 insertions(+), 78 deletions(-) diff --git a/src/views/email-exchange/administration/ViewMobileDevices.js b/src/views/email-exchange/administration/ViewMobileDevices.js index 71e410efbb7e..f257c64bdb5f 100644 --- a/src/views/email-exchange/administration/ViewMobileDevices.js +++ b/src/views/email-exchange/administration/ViewMobileDevices.js @@ -1,89 +1,184 @@ -import React from 'react' +import React, { useState } from 'react' import { useSelector } from 'react-redux' import { CippPageList } from 'src/components/layout' import useQuery from 'src/hooks/useQuery' +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { CellTip, cellDateFormatter } from 'src/components/tables' +import { faEye, faEdit, faEllipsisV, faMobileAlt } from '@fortawesome/free-solid-svg-icons' +import { CippActionsOffcanvas } from 'src/components/utilities' +import { Link } from 'react-router-dom' +import { CButton } from '@coreui/react' //TODO: Add CellBoolean -const columns = [ - { - selector: (row) => row['clientType'], - name: 'Client Type', - sortable: true, - cell: (row) => CellTip(row['clientType']), - exportSelector: 'clientType', - }, - { - selector: (row) => row['clientVersion'], - name: 'Client Version', - sortable: true, - exportSelector: 'clientVersion', - }, - { - selector: (row) => row['deviceAccessState'], - name: 'Access State', - sortable: true, - exportSelector: 'deviceAccessState', - }, - { - selector: (row) => row['deviceFriendlyName'], - name: 'Friendly Name', - sortable: true, - cell: (row) => CellTip(row['deviceFriendlyName']), - exportSelector: 'deviceFriendlyName', - }, - { - selector: (row) => row['deviceModel'], - name: 'Model', - sortable: true, - cell: (row) => CellTip(row['deviceModel']), - exportSelector: 'deviceModel', - }, - { - selector: (row) => row['deviceOS'], - name: 'OS', - sortable: true, - cell: (row) => CellTip(row['deviceOS']), - exportSelector: 'deviceOS', - }, - { - selector: (row) => row['deviceType'], - name: 'Device Type', - sortable: true, - cell: (row) => CellTip(row['deviceType']), - exportSelector: 'deviceType', - }, - { - selector: (row) => row['firstSync'], - name: 'First Sync', - sortable: true, - exportSelector: 'firstSync', - cell: cellDateFormatter(), - }, - { - selector: (row) => row['lastSyncAttempt'], - name: 'Last Sync Attempt', - sortable: true, - exportSelector: 'lastSyncAttempt', - cell: cellDateFormatter(), - }, - { - selector: (row) => row['lastSuccessSync'], - name: 'Last Succesfull Sync', - sortable: true, - exportSelector: 'lastSuccessSync', - cell: cellDateFormatter(), - }, - { - selector: (row) => row['status'], - name: 'Status', - sortable: true, - exportSelector: 'status', - }, -] const MobileDeviceList = () => { const tenant = useSelector((state) => state.app.currentTenant) + + const Offcanvas = (row, rowIndex, formatExtraData) => { + const [ocVisible, setOCVisible] = useState(false) + return ( + <> + setOCVisible(true)}> + + + setOCVisible(false)} + /> + + ) + } + + const columns = [ + { + selector: (row) => query.get('userId'), + name: 'User ID', + sortable: true, + cell: (row) => CellTip(query.get('userId')), + exportSelector: 'userId', + }, + { + selector: (row) => row['clientType'], + name: 'Client Type', + sortable: true, + cell: (row) => CellTip(row['clientType']), + exportSelector: 'clientType', + }, + { + selector: (row) => row['clientVersion'], + name: 'Client Version', + sortable: true, + exportSelector: 'clientVersion', + }, + { + selector: (row) => row['deviceAccessState'], + name: 'Access State', + sortable: true, + exportSelector: 'deviceAccessState', + }, + { + selector: (row) => row['deviceFriendlyName'], + name: 'Friendly Name', + sortable: true, + cell: (row) => CellTip(row['deviceFriendlyName']), + exportSelector: 'deviceFriendlyName', + }, + { + selector: (row) => row['deviceModel'], + name: 'Model', + sortable: true, + cell: (row) => CellTip(row['deviceModel']), + exportSelector: 'deviceModel', + }, + { + selector: (row) => row['deviceOS'], + name: 'OS', + sortable: true, + cell: (row) => CellTip(row['deviceOS']), + exportSelector: 'deviceOS', + }, + { + selector: (row) => row['deviceType'], + name: 'Device Type', + sortable: true, + cell: (row) => CellTip(row['deviceType']), + exportSelector: 'deviceType', + }, + { + selector: (row) => row['deviceID'], + name: 'Device ID', + sortable: true, + exportSelector: 'deviceID', + cell: cellDateFormatter(), + }, + { + selector: (row) => row['firstSync'], + name: 'First Sync', + sortable: true, + exportSelector: 'firstSync', + cell: cellDateFormatter(), + }, + { + selector: (row) => row['lastSyncAttempt'], + name: 'Last Sync Attempt', + sortable: true, + exportSelector: 'lastSyncAttempt', + cell: cellDateFormatter(), + }, + { + selector: (row) => row['lastSuccessSync'], + name: 'Last Succesfull Sync', + sortable: true, + exportSelector: 'lastSuccessSync', + cell: cellDateFormatter(), + }, + { + selector: (row) => row['status'], + name: 'Status', + sortable: true, + exportSelector: 'status', + }, + { + selector: (row) => row['Guid'], + name: 'Guid', + sortable: true, + exportSelector: 'Guid', + }, + { + name: 'Actions', + cell: Offcanvas, + maxWidth: '75px', + }, + ] + let query = useQuery() const userId = query.get('userId') return ( @@ -96,9 +191,9 @@ const MobileDeviceList = () => { path: '/api/ListMailboxMobileDevices', columns, params: { TenantFilter: tenant?.defaultDomainName, mailbox: userId }, + selectableRows: true, }} /> ) } - export default MobileDeviceList From f279c795ec98c28c7373dc939dc7589d2508d7b1 Mon Sep 17 00:00:00 2001 From: BNWEIN Date: Thu, 20 Apr 2023 17:54:29 +0100 Subject: [PATCH 064/124] Added "Enable Online Archive" To user Actions Added "Enable Online Archive" To user Actions --- src/views/identity/administration/UserActions.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/views/identity/administration/UserActions.js b/src/views/identity/administration/UserActions.js index 4bb0d3818e35..78ca9e360fe8 100644 --- a/src/views/identity/administration/UserActions.js +++ b/src/views/identity/administration/UserActions.js @@ -8,6 +8,7 @@ import { faLockOpen, faUserTimes, faEllipsisH, + faEnvelope, } from '@fortawesome/free-solid-svg-icons' import { ActionContentCard } from 'src/components/contentcards' import { useLazyGenericGetRequestQuery } from 'src/store/api/app' @@ -46,6 +47,16 @@ export default function UserActions({ tenantDomain, userId, userEmail, className `/api/ExecSendPush?TenantFilter=${tenantDomain}&UserEmail=${userEmail}`, ), }, + { + label: 'Enable Online Archive ', + link: '#', + icon: faEnvelope, + onClick: () => + handleModal( + 'Are you sure you want to enable the online archive for this user?', + `/api/ExecEnableArchive?TenantFilter=${tenantDomain}&ID=${userEmail}`, + ), + }, { label: 'Convert to Shared Mailbox', link: '#', From a3074058188d387f0fb90a6c01a5f0e3df7ee335 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Thu, 20 Apr 2023 20:22:33 +0200 Subject: [PATCH 065/124] added all tenants --- src/views/email-exchange/reports/MailboxStatisticsList.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/views/email-exchange/reports/MailboxStatisticsList.js b/src/views/email-exchange/reports/MailboxStatisticsList.js index 5a4432e026c2..6d80e5c3d569 100644 --- a/src/views/email-exchange/reports/MailboxStatisticsList.js +++ b/src/views/email-exchange/reports/MailboxStatisticsList.js @@ -75,6 +75,7 @@ const MailboxStatsList = () => { return ( Date: Thu, 20 Apr 2023 20:52:25 +0200 Subject: [PATCH 066/124] added allusers --- src/views/identity/administration/Users.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/views/identity/administration/Users.js b/src/views/identity/administration/Users.js index 3b7a0e3a04e1..993dc433638f 100644 --- a/src/views/identity/administration/Users.js +++ b/src/views/identity/administration/Users.js @@ -276,7 +276,7 @@ const Users = (row) => { ) return ( Date: Thu, 20 Apr 2023 22:32:20 +0200 Subject: [PATCH 067/124] updates to cards for queues --- src/components/header/AppHeaderDropdown.js | 5 ++- src/components/tables/CippOffcanvasTable.js | 2 +- .../utilities/CippActionsOffcanvas.js | 32 +++++++++++++++++-- 3 files changed, 35 insertions(+), 4 deletions(-) diff --git a/src/components/header/AppHeaderDropdown.js b/src/components/header/AppHeaderDropdown.js index f2baf4c25c0e..e6589af9697b 100644 --- a/src/components/header/AppHeaderDropdown.js +++ b/src/components/header/AppHeaderDropdown.js @@ -42,6 +42,8 @@ const AppHeaderDropdown = () => { cippQueueList.data?.map((job) => ({ label: `${job.Name}`, value: job.Status, + link: job.Link, + timestamp: job.Timestamp, })), ) } else { @@ -89,7 +91,8 @@ const AppHeaderDropdown = () => { ( + <> + + + Report Name: {action.label} + + Status: {action.value} + + + Generated on {action.timestamp.split('T')[0]} at {action.timestamp.split('T')[1]} + + + + + )) + } catch (error) { + console.error('An error occored building OCanvas actions' + error.toString()) + } + const extendedInfoContent = let actionsContent try { @@ -176,7 +202,9 @@ export default function CippActionsOffcanvas(props) { {getResults.isError && ( Could not connect to API: {getResults.error.message} )} + Extended Information + {cardContent && cardContent} {extendedInfoContent} {Actions} @@ -193,7 +221,7 @@ const CippActionsOffcanvasPropTypes = { label: PropTypes.string, value: PropTypes.any, }), - ).isRequired, + ), actions: PropTypes.arrayOf( PropTypes.shape({ label: PropTypes.string, From 020c2f5895e87b0321eed1d691b3b2b4b865e78d Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Thu, 20 Apr 2023 23:10:21 +0200 Subject: [PATCH 068/124] added visible tenants --- src/views/identity/administration/Users.js | 147 ++++++++++++--------- 1 file changed, 86 insertions(+), 61 deletions(-) diff --git a/src/views/identity/administration/Users.js b/src/views/identity/administration/Users.js index 993dc433638f..ca19f07ef253 100644 --- a/src/views/identity/administration/Users.js +++ b/src/views/identity/administration/Users.js @@ -1,4 +1,4 @@ -import React, { useState } from 'react' +import React, { useEffect, useState } from 'react' import { CButton } from '@coreui/react' import { Link } from 'react-router-dom' import { useSelector } from 'react-redux' @@ -200,68 +200,93 @@ const Offcanvas = (row, rowIndex, formatExtraData) => { ) } -const columns = [ - { - name: 'Display Name', - selector: (row) => row['displayName'], - sortable: true, - cell: (row) => CellTip(row['displayName']), - exportSelector: 'displayName', - minWidth: '300px', - }, - { - name: 'Email', - selector: (row) => row['mail'], - sortable: true, - cell: (row) => CellTip(row['mail']), - exportSelector: 'mail', - minWidth: '250px', - }, - { - name: 'User Type', - selector: (row) => row['userType'], - sortable: true, - exportSelector: 'userType', - minWidth: '140px', - }, - { - name: 'Enabled', - selector: (row) => row['accountEnabled'], - cell: cellBooleanFormatter({ colourless: true }), - sortable: true, - exportSelector: 'accountEnabled', - minWidth: '100px', - }, - { - name: 'AD Synced', - selector: (row) => row['onPremisesSyncEnabled'], - cell: cellBooleanFormatter({ colourless: true }), - sortable: true, - exportSelector: 'onPremisesSyncEnabled', - minWidth: '120px', - }, - { - name: 'Licenses', - selector: (row) => row['LicJoined'], - exportSelector: 'LicJoined', - sortable: true, - grow: 5, - wrap: true, - minWidth: '200px', - }, - { - name: 'id', - selector: (row) => row['id'], - omit: true, - }, - { - name: 'Actions', - cell: Offcanvas, - }, -] - const Users = (row) => { + const [tenantColumnSet, setTenantColumn] = useState(true) + 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, + }, + { + name: 'Display Name', + selector: (row) => row['displayName'], + sortable: true, + cell: (row) => CellTip(row['displayName']), + exportSelector: 'displayName', + minWidth: '300px', + }, + { + name: 'Email', + selector: (row) => row['mail'], + sortable: true, + cell: (row) => CellTip(row['mail']), + exportSelector: 'mail', + minWidth: '250px', + }, + { + name: 'User Type', + selector: (row) => row['userType'], + sortable: true, + exportSelector: 'userType', + minWidth: '140px', + }, + { + name: 'Enabled', + selector: (row) => row['accountEnabled'], + cell: cellBooleanFormatter({ colourless: true }), + sortable: true, + exportSelector: 'accountEnabled', + minWidth: '100px', + }, + { + name: 'AD Synced', + selector: (row) => row['onPremisesSyncEnabled'], + cell: cellBooleanFormatter({ colourless: true }), + sortable: true, + exportSelector: 'onPremisesSyncEnabled', + minWidth: '120px', + }, + { + name: 'Licenses', + selector: (row) => row['LicJoined'], + exportSelector: 'LicJoined', + sortable: true, + grow: 5, + wrap: true, + minWidth: '200px', + }, + { + name: 'id', + selector: (row) => row['id'], + omit: true, + }, + { + name: 'Actions', + cell: Offcanvas, + }, + ] const tenant = useSelector((state) => state.app.currentTenant) + useEffect(() => { + if (tenant.defaultDomainName === 'AllTenants') { + setTenantColumn(false) + } + if (tenant.defaultDomainName !== 'AllTenants') { + setTenantColumn(true) + } + }, [tenantColumnSet]) + const titleButtons = (

    From 07b8ae49714f86639ad47b8d2d8015a066a9399b Mon Sep 17 00:00:00 2001 From: John Duprey Date: Thu, 20 Apr 2023 21:32:55 -0400 Subject: [PATCH 069/124] Add ReactTimeAgo --- package-lock.json | 65 +++++++++++++++++++ package.json | 2 + .../utilities/CippActionsOffcanvas.js | 13 ++-- 3 files changed, 76 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 08e6a9e247c5..619b33124282 100644 --- a/package-lock.json +++ b/package-lock.json @@ -30,6 +30,7 @@ "enzyme": "^3.11.0", "final-form": "^4.20.4", "fuzzysort": "^1.1.4", + "javascript-time-ago": "^2.5.9", "jspdf": "^2.4.0", "jspdf-autotable": "^3.5.23", "moment": "^2.29.1", @@ -53,6 +54,7 @@ "react-select": "^5.3.0", "react-select-search": "^3.0.8", "react-syntax-highlighter": "^15.4.5", + "react-time-ago": "^7.2.1", "redux": "4.1.1", "redux-persist": "^6.0.0", "simplebar-react": "^2.3.6", @@ -10065,6 +10067,14 @@ "node": ">=8" } }, + "node_modules/javascript-time-ago": { + "version": "2.5.9", + "resolved": "https://registry.npmjs.org/javascript-time-ago/-/javascript-time-ago-2.5.9.tgz", + "integrity": "sha512-pQ8mNco/9g9TqWXWWjP0EWl6i/lAQScOyEeXy5AB+f7MfLSdgyV9BJhiOD1zrIac/lrxPYOWNbyl/IW8CW5n0A==", + "dependencies": { + "relative-time-format": "^1.1.6" + } + }, "node_modules/jest": { "version": "27.5.1", "dev": true, @@ -15163,6 +15173,26 @@ "react": "17.0.2" } }, + "node_modules/react-time-ago": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/react-time-ago/-/react-time-ago-7.2.1.tgz", + "integrity": "sha512-X5zwJDZHa1fsMwMvh8mrHN31g85s84zMCp+d7YL6IX50kNnr6YMAS2wpt1BmO9OxBV2Ue5J1ptD6JI8Zjd35HA==", + "dependencies": { + "memoize-one": "^6.0.0", + "prop-types": "^15.8.1", + "raf": "^3.4.1" + }, + "peerDependencies": { + "javascript-time-ago": "^2.3.7", + "react": ">=0.16.8", + "react-dom": ">=0.16.8" + } + }, + "node_modules/react-time-ago/node_modules/memoize-one": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz", + "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==" + }, "node_modules/react-transition-group": { "version": "4.4.2", "license": "BSD-3-Clause", @@ -15500,6 +15530,11 @@ "node": ">= 0.10" } }, + "node_modules/relative-time-format": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/relative-time-format/-/relative-time-format-1.1.6.tgz", + "integrity": "sha512-aCv3juQw4hT1/P/OrVltKWLlp15eW1GRcwP1XdxHrPdZE9MtgqFpegjnTjLhi2m2WI9MT/hQQtE+tjEWG1hgkQ==" + }, "node_modules/renderkid": { "version": "3.0.0", "dev": true, @@ -24586,6 +24621,14 @@ } } }, + "javascript-time-ago": { + "version": "2.5.9", + "resolved": "https://registry.npmjs.org/javascript-time-ago/-/javascript-time-ago-2.5.9.tgz", + "integrity": "sha512-pQ8mNco/9g9TqWXWWjP0EWl6i/lAQScOyEeXy5AB+f7MfLSdgyV9BJhiOD1zrIac/lrxPYOWNbyl/IW8CW5n0A==", + "requires": { + "relative-time-format": "^1.1.6" + } + }, "jest": { "version": "27.5.1", "dev": true, @@ -27687,6 +27730,23 @@ "scheduler": "^0.20.2" } }, + "react-time-ago": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/react-time-ago/-/react-time-ago-7.2.1.tgz", + "integrity": "sha512-X5zwJDZHa1fsMwMvh8mrHN31g85s84zMCp+d7YL6IX50kNnr6YMAS2wpt1BmO9OxBV2Ue5J1ptD6JI8Zjd35HA==", + "requires": { + "memoize-one": "^6.0.0", + "prop-types": "^15.8.1", + "raf": "^3.4.1" + }, + "dependencies": { + "memoize-one": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz", + "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==" + } + } + }, "react-transition-group": { "version": "4.4.2", "requires": { @@ -27914,6 +27974,11 @@ "version": "0.2.7", "dev": true }, + "relative-time-format": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/relative-time-format/-/relative-time-format-1.1.6.tgz", + "integrity": "sha512-aCv3juQw4hT1/P/OrVltKWLlp15eW1GRcwP1XdxHrPdZE9MtgqFpegjnTjLhi2m2WI9MT/hQQtE+tjEWG1hgkQ==" + }, "renderkid": { "version": "3.0.0", "dev": true, diff --git a/package.json b/package.json index d9e64244f095..7d4a99103c8f 100644 --- a/package.json +++ b/package.json @@ -49,6 +49,7 @@ "enzyme": "^3.11.0", "final-form": "^4.20.4", "fuzzysort": "^1.1.4", + "javascript-time-ago": "^2.5.9", "jspdf": "^2.4.0", "jspdf-autotable": "^3.5.23", "moment": "^2.29.1", @@ -72,6 +73,7 @@ "react-select": "^5.3.0", "react-select-search": "^3.0.8", "react-syntax-highlighter": "^15.4.5", + "react-time-ago": "^7.2.1", "redux": "4.1.1", "redux-persist": "^6.0.0", "simplebar-react": "^2.3.6", diff --git a/src/components/utilities/CippActionsOffcanvas.js b/src/components/utilities/CippActionsOffcanvas.js index cbf9125a0b6f..9e712289e6b7 100644 --- a/src/components/utilities/CippActionsOffcanvas.js +++ b/src/components/utilities/CippActionsOffcanvas.js @@ -19,6 +19,11 @@ import { CippOffcanvasTable } from 'src/components/tables' import { useLazyGenericGetRequestQuery, useLazyGenericPostRequestQuery } from 'src/store/api/app' import { Link, useNavigate } from 'react-router-dom' import { stringCamelCase } from 'src/components/utilities/CippCamelCase' +import TimeAgo from 'javascript-time-ago' + +import en from 'javascript-time-ago/locale/en.json' +TimeAgo.addDefaultLocale(en) +import ReactTimeAgo from 'react-time-ago' export default function CippActionsOffcanvas(props) { const inputRef = useRef('') @@ -107,14 +112,14 @@ export default function CippActionsOffcanvas(props) { Status: {action.value} - Generated on {action.timestamp.split('T')[0]} at {action.timestamp.split('T')[1]} + )) } catch (error) { - console.error('An error occored building OCanvas actions' + error.toString()) + console.error('An error occurred building OCanvas actions' + error.toString()) } const extendedInfoContent = @@ -144,7 +149,7 @@ export default function CippActionsOffcanvas(props) { )) } catch (error) { - console.error('An error occored building OCanvas actions' + error.toString()) + console.error('An error occurred building OCanvas actions' + error.toString()) } let actionsSelectorsContent try { @@ -169,7 +174,7 @@ export default function CippActionsOffcanvas(props) { } catch (error) { // When we create an Off Canvas control without selectors we will get this if (!error.toString().includes("Cannot read properties of undefined (reading '")) { - console.error('An error occored building OCanvas selectors' + error.toString()) + console.error('An error occurred building OCanvas selectors' + error.toString()) } } return ( From 9759c6791e6591b3b7599450ecc0eb1d5f055d1a Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Fri, 21 Apr 2023 10:20:41 +0200 Subject: [PATCH 070/124] fix minor bug with date calc --- src/components/header/AppHeaderDropdown.js | 14 +++++++++++--- src/components/utilities/CippActionsOffcanvas.js | 6 ++---- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/components/header/AppHeaderDropdown.js b/src/components/header/AppHeaderDropdown.js index e6589af9697b..568e03211542 100644 --- a/src/components/header/AppHeaderDropdown.js +++ b/src/components/header/AppHeaderDropdown.js @@ -31,7 +31,14 @@ const AppHeaderDropdown = () => { useEffect(() => { if (cippQueueList.isFetching) { - setCippQueueExtendedInfo([{ label: 'Fetching recent jobs', value: 'Please wait' }]) + setCippQueueExtendedInfo([ + { + label: 'Fetching recent jobs', + value: 'Please wait', + timpestamp: Date(), + link: '#', + }, + ]) } if ( cippQueueList.isSuccess && @@ -47,9 +54,10 @@ const AppHeaderDropdown = () => { })), ) } else { - setCippQueueExtendedInfo([{ label: 'No jobs to display', value: '' }]) + setCippQueueExtendedInfo([ + { label: 'No jobs to display', value: '', timpestamp: Date(), link: '#' }, + ]) } - console.log(cippQueueList) }, [cippQueueList]) return ( diff --git a/src/components/utilities/CippActionsOffcanvas.js b/src/components/utilities/CippActionsOffcanvas.js index 9e712289e6b7..b24aa1a28c12 100644 --- a/src/components/utilities/CippActionsOffcanvas.js +++ b/src/components/utilities/CippActionsOffcanvas.js @@ -109,11 +109,9 @@ export default function CippActionsOffcanvas(props) { Report Name: {action.label} - Status: {action.value} + {action.value && Status: {action.value}} - - - + {action.timestamp && } From 45ace28e378082fdee4cb52434f6aafe6c3f781d Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Fri, 21 Apr 2023 10:28:04 +0200 Subject: [PATCH 071/124] add tenant column --- .../reports/MailboxStatisticsList.js | 158 ++++++++++-------- 1 file changed, 91 insertions(+), 67 deletions(-) diff --git a/src/views/email-exchange/reports/MailboxStatisticsList.js b/src/views/email-exchange/reports/MailboxStatisticsList.js index 6d80e5c3d569..febb16cc0062 100644 --- a/src/views/email-exchange/reports/MailboxStatisticsList.js +++ b/src/views/email-exchange/reports/MailboxStatisticsList.js @@ -1,77 +1,101 @@ -import React from 'react' +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 conditionalRowStyles = [ - { - when: (row) => (row.UsedGB / row.QuotaGB) * 100 > 80 && (row.UsedGB / row.QuotaGB) * 100 < 90, - classNames: ['mbusage-warning'], - }, - { - when: (row) => (row.UsedGB / row.QuotaGB) * 100 > 90 && (row.UsedGB / row.QuotaGB) * 100 < 100, - classNames: ['mbusage-danger'], - }, -] - -const columns = [ - { - selector: (row) => row['UPN'], - name: 'User Prinicipal Name', - sortable: true, - cell: (row) => CellTip(row['UPN']), - exportSelector: 'UPN', - minWidth: '200px', - }, - { - selector: (row) => row['displayName'], - name: 'Display Name', - sortable: true, - cell: (row) => CellTip(row['displayName']), - exportSelector: 'displayName', - }, - { - selector: (row) => row['MailboxType'], - name: 'Mailbox Type', - sortable: true, - exportSelector: 'MailboxType', - }, - { - selector: (row) => row['LastActive'], - name: 'Last Active', - sortable: true, - exportSelector: 'LastActive', - }, - { - selector: (row) => row['UsedGB'], - name: 'Used Space(GB)', - sortable: true, - exportSelector: 'UsedGB', - }, - { - selector: (row) => row['QuotaGB'], - name: 'Quota (GB)', - sortable: true, - exportSelector: 'QuotaGB', - }, - { - selector: (row) => row['ItemCount'], - name: 'Item Count (Total)', - sortable: true, - exportSelector: 'ItemCount', - }, - { - selector: (row) => row['HasArchive'], - name: 'Archiving Enabled', - sortable: true, - cell: cellBooleanFormatter({ colourless: true }), - exportSelector: 'HasArchive', - }, -] - const MailboxStatsList = () => { + const [tenantColumnSet, setTenantColumn] = useState(true) const tenant = useSelector((state) => state.app.currentTenant) + const conditionalRowStyles = [ + { + when: (row) => (row.UsedGB / row.QuotaGB) * 100 > 80 && (row.UsedGB / row.QuotaGB) * 100 < 90, + classNames: ['mbusage-warning'], + }, + { + when: (row) => + (row.UsedGB / row.QuotaGB) * 100 > 90 && (row.UsedGB / row.QuotaGB) * 100 < 100, + classNames: ['mbusage-danger'], + }, + ] + 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['UPN'], + name: 'User Prinicipal Name', + sortable: true, + cell: (row) => CellTip(row['UPN']), + exportSelector: 'UPN', + minWidth: '200px', + }, + { + selector: (row) => row['displayName'], + name: 'Display Name', + sortable: true, + cell: (row) => CellTip(row['displayName']), + exportSelector: 'displayName', + }, + { + selector: (row) => row['MailboxType'], + name: 'Mailbox Type', + sortable: true, + exportSelector: 'MailboxType', + }, + { + selector: (row) => row['LastActive'], + name: 'Last Active', + sortable: true, + exportSelector: 'LastActive', + }, + { + selector: (row) => row['UsedGB'], + name: 'Used Space(GB)', + sortable: true, + exportSelector: 'UsedGB', + }, + { + selector: (row) => row['QuotaGB'], + name: 'Quota (GB)', + sortable: true, + exportSelector: 'QuotaGB', + }, + { + selector: (row) => row['ItemCount'], + name: 'Item Count (Total)', + sortable: true, + exportSelector: 'ItemCount', + }, + { + selector: (row) => row['HasArchive'], + name: 'Archiving Enabled', + sortable: true, + cell: cellBooleanFormatter({ colourless: true }), + exportSelector: 'HasArchive', + }, + ] + useEffect(() => { + if (tenant.defaultDomainName === 'AllTenants') { + setTenantColumn(false) + } + if (tenant.defaultDomainName !== 'AllTenants') { + setTenantColumn(true) + } + }, [tenantColumnSet]) return ( Date: Fri, 21 Apr 2023 10:29:39 +0200 Subject: [PATCH 072/124] upped version --- 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 15a279981720..fbcbf7380658 100644 --- a/public/version_latest.txt +++ b/public/version_latest.txt @@ -1 +1 @@ -3.3.0 +3.4.0 \ No newline at end of file diff --git a/version_latest.txt b/version_latest.txt index 0fa4ae489037..fbcbf7380658 100644 --- a/version_latest.txt +++ b/version_latest.txt @@ -1 +1 @@ -3.3.0 \ No newline at end of file +3.4.0 \ No newline at end of file From 2f42141de6fc3c3aae84d9c2e6579eb1f10c7439 Mon Sep 17 00:00:00 2001 From: BNWEIN Date: Fri, 21 Apr 2023 09:58:47 +0100 Subject: [PATCH 073/124] Changed wording Changed Wording --- src/views/email-exchange/administration/ViewMobileDevices.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/views/email-exchange/administration/ViewMobileDevices.js b/src/views/email-exchange/administration/ViewMobileDevices.js index f257c64bdb5f..c0a66d0e66be 100644 --- a/src/views/email-exchange/administration/ViewMobileDevices.js +++ b/src/views/email-exchange/administration/ViewMobileDevices.js @@ -51,7 +51,7 @@ const MobileDeviceList = () => { color: 'info', modal: true, modalUrl: `/api/ExecMailboxMobileDevices?TenantFilter=${tenant.defaultDomainName}&DeviceID=${row.deviceID}&UserID=${userId}&quarantine=false`, - modalMessage: 'Are you sure you want to remove device from quarantine?', + modalMessage: 'Are you sure you want to allow the device?', }, { label: 'Block Device', From 1f7ff77baf6d883ded0c31248c246ba211d15320 Mon Sep 17 00:00:00 2001 From: Roel van der Wegen Date: Fri, 21 Apr 2023 22:30:20 +0200 Subject: [PATCH 074/124] Updated "tokens" references to token --- src/views/cipp/Setup.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/views/cipp/Setup.js b/src/views/cipp/Setup.js index 61f5c0f21db4..aa4e37c18a89 100644 --- a/src/views/cipp/Setup.js +++ b/src/views/cipp/Setup.js @@ -106,12 +106,12 @@ const Setup = () => {
    @@ -124,7 +124,7 @@ const Setup = () => { - Click the buttons below to refresh your tokens. + Click the buttons below to refresh your token.
    Remember to login under a account that has been added to the correct GDAP groups or the group 'AdminAgents'. After confirmation that the refresh is successful, the token cache must be cleared. From 5e2983de16594e6a36d68784accba1481cb8fac8 Mon Sep 17 00:00:00 2001 From: Roel van der Wegen Date: Fri, 21 Apr 2023 22:52:14 +0200 Subject: [PATCH 075/124] Replaced AAD portal with Entra --- src/views/tenant/administration/Tenants.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/views/tenant/administration/Tenants.js b/src/views/tenant/administration/Tenants.js index ef2ccef56a2d..f7bbca703c32 100644 --- a/src/views/tenant/administration/Tenants.js +++ b/src/views/tenant/administration/Tenants.js @@ -100,10 +100,10 @@ const Offcanvas = (row, rowIndex, formatExtraData) => { }, { icon: , - label: 'AAD Portal', + label: 'Entra Portal', color: 'info', external: true, - link: `https://aad.portal.azure.com/${row.defaultDomainName}`, + link: `https://entra.microsoft.com/${row.defaultDomainName}`, }, { icon: , From 9dead54376c2ff471234bb85c5d5d755102d377d Mon Sep 17 00:00:00 2001 From: Roel van der Wegen Date: Sat, 22 Apr 2023 13:48:21 +0200 Subject: [PATCH 076/124] Update User365Management.js --- .../identity/administration/User365Management.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/views/identity/administration/User365Management.js b/src/views/identity/administration/User365Management.js index fc84d338af80..dbe7711f4892 100644 --- a/src/views/identity/administration/User365Management.js +++ b/src/views/identity/administration/User365Management.js @@ -5,18 +5,18 @@ import PropTypes from 'prop-types' import { ActionContentCard } from 'src/components/contentcards' export default function User365Management({ tenantDomain, userId, className }) { - const azureADLink = `https://portal.azure.com/${tenantDomain}/#blade/Microsoft_AAD_IAM/UserDetailsMenuBlade/Profile/userId/${userId}` - const endpointManagerLink = `https://endpoint.microsoft.com/${tenantDomain}/#blade/Microsoft_AAD_IAM/UserDetailsMenuBlade/Profile/userId/${userId}` + const entraLink = `https://entra.microsoft.com/${tenantDomain}/#view/Microsoft_AAD_UsersAndTenants/UserProfileMenuBlade/~/overview/userId/${userId}` + const intuneLink = `https://intune.microsoft.com/${tenantDomain}/#view/Microsoft_AAD_UsersAndTenants/UserProfileMenuBlade/~/overview/userId/${userId}` const actions = [ { - label: 'View in Azure AD', - link: azureADLink, + label: 'View in Entra', + link: entraLink, icon: faUsers, target: '_blank', }, { - label: 'View in Endpoint Manager', - link: endpointManagerLink, + label: 'View in Intune', + link: intuneLink, icon: faLaptop, target: '_blank', }, From 02274d4df1d7043cd60c4659fafe511749e37db7 Mon Sep 17 00:00:00 2001 From: Roel van der Wegen Date: Sat, 22 Apr 2023 13:50:20 +0200 Subject: [PATCH 077/124] Update Tenants.js --- src/views/tenant/administration/Tenants.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/views/tenant/administration/Tenants.js b/src/views/tenant/administration/Tenants.js index f7bbca703c32..a181ae12a798 100644 --- a/src/views/tenant/administration/Tenants.js +++ b/src/views/tenant/administration/Tenants.js @@ -124,7 +124,7 @@ const Offcanvas = (row, rowIndex, formatExtraData) => { label: 'MEM (Intune) Portal', color: 'info', external: true, - link: `https://endpoint.microsoft.com/${row.defaultDomainName}`, + link: `https://intune.microsoft.com/${row.defaultDomainName}`, }, { icon: , From 04bf99c4882593b4cc5436fd281504e85dc6baed Mon Sep 17 00:00:00 2001 From: Roel van der Wegen Date: Sat, 22 Apr 2023 13:52:39 +0200 Subject: [PATCH 078/124] Update UserGroups.js --- src/views/identity/administration/UserGroups.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/views/identity/administration/UserGroups.js b/src/views/identity/administration/UserGroups.js index 36fbc047b528..fc1a006fa4c8 100644 --- a/src/views/identity/administration/UserGroups.js +++ b/src/views/identity/administration/UserGroups.js @@ -18,7 +18,7 @@ const columns = [ formatter: (cell, row) => { return ( {row.DisplayName} From ac7301720e75538cc238dc828699724da460deb4 Mon Sep 17 00:00:00 2001 From: Roel van der Wegen Date: Sat, 22 Apr 2023 13:56:29 +0200 Subject: [PATCH 079/124] Update UserDevices.js --- src/views/identity/administration/UserDevices.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/views/identity/administration/UserDevices.js b/src/views/identity/administration/UserDevices.js index 57a9c1206fbf..b0ad63d8c5be 100644 --- a/src/views/identity/administration/UserDevices.js +++ b/src/views/identity/administration/UserDevices.js @@ -20,7 +20,7 @@ const columns = [ return ( {row.displayName} From 74b218b73374adf05231a3e6595b3d9ac8c44ef0 Mon Sep 17 00:00:00 2001 From: John Duprey Date: Sat, 22 Apr 2023 19:48:19 -0400 Subject: [PATCH 080/124] Graph Filter support --- src/components/tables/CippDatatable.js | 4 +- src/components/tables/CippTable.js | 57 +++++++++++++++++++--- src/views/identity/administration/Users.js | 5 ++ 3 files changed, 57 insertions(+), 9 deletions(-) diff --git a/src/components/tables/CippDatatable.js b/src/components/tables/CippDatatable.js index 1506e93676a8..77b0e5208f7a 100644 --- a/src/components/tables/CippDatatable.js +++ b/src/components/tables/CippDatatable.js @@ -6,11 +6,12 @@ import { CippTablePropTypes } from 'src/components/tables/CippTable' export default function CippDatatable({ path, params, ...rest }) { const [refreshGuid, setRefreshGuid] = React.useState('') + const [graphFilter, setGraphFilter] = React.useState('') const { data = [], isFetching, error, - } = useListDatatableQuery({ path, params: { refreshGuid, ...params } }) + } = useListDatatableQuery({ path, params: { refreshGuid, graphFilter, ...params } }) return ( ) } diff --git a/src/components/tables/CippTable.js b/src/components/tables/CippTable.js index f941927a01fa..a025dcaae217 100644 --- a/src/components/tables/CippTable.js +++ b/src/components/tables/CippTable.js @@ -25,7 +25,14 @@ import { ModalService } from '../utilities' import { useLazyGenericGetRequestQuery, useLazyGenericPostRequestQuery } from 'src/store/api/app' import { ConfirmModal } from '../utilities/SharedModal' -const FilterComponent = ({ filterText, onFilter, onClear, filterlist, onFilterPreset }) => ( +const FilterComponent = ({ + filterText, + onFilter, + onClear, + filterlist, + onFilterPreset, + onFilterGraph, +}) => ( <> @@ -38,14 +45,29 @@ const FilterComponent = ({ filterText, onFilter, onClear, filterlist, onFilterPr - onFilterPreset('')}>Clear Filter + { + onFilterPreset('') + onFilterGraph('') + }} + > + Clear Filter + {filterlist && filterlist.map((item, idx) => { - return ( - onFilterPreset(item.filter)}> - {item.filterName} - - ) + if (item.hasOwnProperty('graphFilter') && item.graphFilter == true) { + return ( + onFilterGraph(item.filter)}> + {item.filterName} + + ) + } else { + return ( + onFilterPreset(item.filter)}> + {item.filterName} + + ) + } })} @@ -69,6 +91,7 @@ FilterComponent.propTypes = { onClear: PropTypes.func, filterlist: PropTypes.arrayOf(PropTypes.object), onFilterPreset: PropTypes.func, + onFilterGraph: PropTypes.func, } const customSort = (rows, selector, direction) => { @@ -99,6 +122,7 @@ export default function CippTable({ error, reportName, refreshFunction = null, + graphFilterFunction = null, columns = [], dynamicColumns = true, filterlist, @@ -142,6 +166,16 @@ export default function CippTable({ const filteredItems = data.filter( (item) => JSON.stringify(item).toLowerCase().indexOf(filterText.toLowerCase()) !== -1, ) + const applyFilter = (e) => { + setFilterText(e.target.value) + } + + const setGraphFilter = (e) => { + if (graphFilterFunction) { + graphFilterFunction(e) + } + } + useEffect(() => { if (columns !== updatedColumns) { setUpdatedColumns(columns) @@ -400,7 +434,14 @@ export default function CippTable({
    setFilterText(e.target.value)} - onFilterPreset={(e) => setFilterText(e)} + onFilterPreset={(e) => { + setFilterText(e) + setGraphFilter('') + }} + onFilterGraph={(e) => { + setFilterText('') + setGraphFilter(e) + }} onClear={handleClear} filterText={filterText} filterlist={filterlist} diff --git a/src/views/identity/administration/Users.js b/src/views/identity/administration/Users.js index ca19f07ef253..d2e845b0641c 100644 --- a/src/views/identity/administration/Users.js +++ b/src/views/identity/administration/Users.js @@ -313,6 +313,11 @@ const Users = (row) => { { filterName: 'Guest users', filter: '"usertype":"guest"' }, { filterName: 'Users with a license', filter: '"assignedLicenses":[{' }, { filterName: 'Users without a license', filter: '"assignedLicenses":[]' }, + { + filterName: 'Users with a license (Graph)', + filter: 'assignedLicenses/$count ne 0', + graphFilter: true, + }, ], columns, path: '/api/ListUsers', From 603a567aaa5c7b7fe9277966dc422727d8143897 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Mon, 24 Apr 2023 11:40:48 +0200 Subject: [PATCH 081/124] Improved SAM Wizard navigation --- src/_nav.js | 45 +++++++++++++++++++++++++++-------------- src/views/cipp/Setup.js | 10 +++++++-- 2 files changed, 38 insertions(+), 17 deletions(-) diff --git a/src/_nav.js b/src/_nav.js index 2f6644b6ac11..3ad3f8a01ca3 100644 --- a/src/_nav.js +++ b/src/_nav.js @@ -18,6 +18,7 @@ import { faExclamationTriangle, faUserShield, faEnvelope, + faToolbox, } from '@fortawesome/free-solid-svg-icons' const _nav = [ @@ -134,6 +135,35 @@ const _nav = [ }, ], }, + { + component: CNavGroup, + name: 'Tools', + section: 'Tools', + to: '/tenant/administration', + icon: , + items: [ + { + component: CNavItem, + name: 'Graph Explorer', + to: '/tenant/administration/graph-explorer', + }, + { + component: CNavItem, + name: 'Application Approval', + to: '/tenant/administration/appapproval', + }, + { + component: CNavItem, + name: 'Tenant Lookup', + to: '/tenant/administration/tenantlookup', + }, + { + component: CNavItem, + name: 'Individual Domain Check', + to: '/tenant/standards/individual-domains', + }, + ], + }, { component: CNavGroup, name: 'Standards', @@ -161,11 +191,6 @@ const _nav = [ name: 'Domains Analyser', to: '/tenant/standards/domains-analyser', }, - { - component: CNavItem, - name: 'Individual Domain Check', - to: '/tenant/standards/individual-domains', - }, ], }, { @@ -214,11 +239,6 @@ const _nav = [ to: '/tenant/reports', icon: , items: [ - { - component: CNavItem, - name: 'Graph Explorer', - to: '/tenant/administration/graph-explorer', - }, { component: CNavItem, name: 'Licence Report', @@ -669,11 +689,6 @@ const _nav = [ name: 'GDAP Migration Status', to: '/tenant/administration/gdap-status', }, - { - component: CNavItem, - name: 'Application Approval', - to: '/tenant/administration/appapproval', - }, { component: CNavItem, name: 'Documentation', diff --git a/src/views/cipp/Setup.js b/src/views/cipp/Setup.js index aa4e37c18a89..6f2646c87768 100644 --- a/src/views/cipp/Setup.js +++ b/src/views/cipp/Setup.js @@ -67,12 +67,12 @@ const Setup = () => { path: 'api/ExecSAMSetup', params: { CreateSAM: true, partnersetup: partner }, }) - setNoSubmit(true) + setSetupdone(false) } useInterval( async () => { - if (getResults.data?.step < 7 && getResults.data?.step > 0) { + if (getResults.data?.step < 5 && getResults.data?.step > 0) { genericGetRequest({ path: 'api/ExecSAMSetup', params: { CheckSetupProcess: true, step: getResults.data?.step }, @@ -175,6 +175,12 @@ const Setup = () => { > Start Setup Wizard +
    From f34b1d70edc739cc358357c58fecca0db4e2bc19 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Mon, 24 Apr 2023 11:44:06 +0200 Subject: [PATCH 082/124] remove non-partner setup from the options. --- src/views/cipp/Setup.js | 140 ++++++++++++---------------------------- 1 file changed, 43 insertions(+), 97 deletions(-) diff --git a/src/views/cipp/Setup.js b/src/views/cipp/Setup.js index 6f2646c87768..dafe6b66ac5a 100644 --- a/src/views/cipp/Setup.js +++ b/src/views/cipp/Setup.js @@ -65,7 +65,7 @@ const Setup = () => { const startCIPPSetup = (partner) => { genericGetRequest({ path: 'api/ExecSAMSetup', - params: { CreateSAM: true, partnersetup: partner }, + params: { CreateSAM: true, partnersetup: true }, }) setSetupdone(false) } @@ -147,102 +147,48 @@ const Setup = () => { - - - - -

    - When clicking the button below, the setup wizard starts. This is a 5 step process. - Please use a Global Administrator to perform these tasks. You can restart the - process at any time, by clicking on the start button once more. -

    - - startCIPPSetup(true)} - validate={valbutton} - > - Start Setup Wizard - - - - -
    -
    - - - {getResults.isFetching && Loading} - {getResults.isSuccess && ( - <> - {getResults.data?.step < 5 ? ( - - ) : ( - - )} - Step {getResults.data?.step} - {getResults.data.message}{' '} - {getResults.data.url && ( - - HERE - - )} - - )} - - -
    - - - - startCIPPSetup(false)} - > - Start Setup Wizard - - - -
    -
    - - - {getResults.isFetching && Loading} - {getResults.isSuccess && ( - <> - {getResults.data?.step < 5 ? ( - - ) : ( - - )} - Step {getResults.data?.step} - {getResults.data.message}{' '} - {getResults.data.url && ( - - HERE - - )} - - )} - - -
    + +

    + When clicking the button below, the setup wizard starts. This is a 5 step process. + Please use a Global Administrator to perform these tasks. You can restart the process + at any time, by clicking on the start button once more. +

    + + startCIPPSetup(true)} + validate={valbutton} + > + Start Setup Wizard + + + + +
    +
    + + + {getResults.isFetching && Loading} + {getResults.isSuccess && ( + <> + {getResults.data?.step < 5 ? ( + + ) : ( + + )} + Step {getResults.data?.step} - {getResults.data.message}{' '} + {getResults.data.url && ( + + HERE + + )} + + )} + +
    you may enter your secrets below, if you only want to update a single value, leave the From ac393d7c8cfb3c6fa8683adc5cfe4b93bf3163bc Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Mon, 24 Apr 2023 11:46:57 +0200 Subject: [PATCH 083/124] textual changes --- src/views/cipp/Setup.js | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/views/cipp/Setup.js b/src/views/cipp/Setup.js index dafe6b66ac5a..10c48cd86dde 100644 --- a/src/views/cipp/Setup.js +++ b/src/views/cipp/Setup.js @@ -97,21 +97,23 @@ const Setup = () => {
    Choose Options

    - This wizard will guide you through setting up a SAM application and using the correct keys. + This wizard will guide you through setting up CIPPs access to your client tenants. If this + is your first time setting up CIPP you will want to choose the option "I'd like CIPP to + create an application for me".
    From 8bd20a3367f318b6f8dcda053cc3c33677a6c2c6 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Mon, 24 Apr 2023 11:48:19 +0200 Subject: [PATCH 084/124] more text changes --- src/views/cipp/Setup.js | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/src/views/cipp/Setup.js b/src/views/cipp/Setup.js index 10c48cd86dde..0304e311993e 100644 --- a/src/views/cipp/Setup.js +++ b/src/views/cipp/Setup.js @@ -98,23 +98,25 @@ const Setup = () => {

    This wizard will guide you through setting up CIPPs access to your client tenants. If this - is your first time setting up CIPP you will want to choose the option "I'd like CIPP to + is your first time setting up CIPP you will want to choose the option "I would like CIPP to create an application for me". - - - + + + + +
    From e442cbdabd09542e7509ffbb79d08bb9e5aa98b0 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Mon, 24 Apr 2023 17:04:56 +0200 Subject: [PATCH 085/124] new alerts via header --- src/components/layout/AppHeader.js | 83 +++++++++++++++++++----------- 1 file changed, 53 insertions(+), 30 deletions(-) diff --git a/src/components/layout/AppHeader.js b/src/components/layout/AppHeader.js index 2751e43d4e50..aada922fa839 100644 --- a/src/components/layout/AppHeader.js +++ b/src/components/layout/AppHeader.js @@ -1,6 +1,8 @@ import React from 'react' import { useSelector, useDispatch } from 'react-redux' import { + CAlert, + CAlertLink, CContainer, CHeader, CHeaderNav, @@ -17,46 +19,67 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { faCaretSquareLeft, faCaretSquareRight } from '@fortawesome/free-solid-svg-icons' import { toggleSidebarShow } from 'src/store/features/app' import { useMediaPredicate } from 'react-media-hook' +import { useGenericGetRequestQuery } from 'src/store/api/app' const AppHeader = () => { const dispatch = useDispatch() const sidebarShow = useSelector((state) => state.app.sidebarShow) const currentTheme = useSelector((state) => state.app.currentTheme) const preferredTheme = useMediaPredicate('(prefers-color-scheme: dark)') ? 'impact' : 'cyberdrain' + const { + data: dashboard, + isLoading: isLoadingDash, + isSuccess: issuccessDash, + } = useGenericGetRequestQuery({ path: '/api/GetCippAlerts' }) + return ( - - - - - - dispatch(toggleSidebarShow({ sidebarShow }))} - > - + + + + + + - - + onClick={() => dispatch(toggleSidebarShow({ sidebarShow }))} + > + + + + + + + + + - + + - - - - - - + {issuccessDash && + dashboard.map((item, index) => ( +
    + + {item.Alert} Link + +
    + ))} + ) } From fa3476438fdbf100f9ec1af2de2632af7d9d3d85 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Mon, 24 Apr 2023 17:09:48 +0200 Subject: [PATCH 086/124] alert stuff --- src/components/layout/AppHeader.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/layout/AppHeader.js b/src/components/layout/AppHeader.js index aada922fa839..3c5838a73652 100644 --- a/src/components/layout/AppHeader.js +++ b/src/components/layout/AppHeader.js @@ -68,7 +68,7 @@ const AppHeader = () => { - {issuccessDash && + {dashboard && dashboard.map((item, index) => (
    Date: Tue, 25 Apr 2023 00:23:22 +0200 Subject: [PATCH 087/124] new apis --- src/views/cipp/CIPPSettings.js | 44 ++++++- src/views/home/Home.js | 227 +++++++++++++++++++++------------ 2 files changed, 189 insertions(+), 82 deletions(-) diff --git a/src/views/cipp/CIPPSettings.js b/src/views/cipp/CIPPSettings.js index 55de4cd0580d..8bf6cf9cf74e 100644 --- a/src/views/cipp/CIPPSettings.js +++ b/src/views/cipp/CIPPSettings.js @@ -29,6 +29,7 @@ import { useLazyGenericGetRequestQuery, useLazyGenericPostRequestQuery, useLazyListNotificationConfigQuery, + useLoadVersionsQuery, } from 'src/store/api/app' import { useExecAddExcludeTenantMutation, @@ -66,7 +67,12 @@ import { import { Form } from 'react-final-form' import useConfirmModal from 'src/hooks/useConfirmModal' import { setCurrentTenant } from 'src/store/features/app' -import { CippCodeBlock, ModalService, TenantSelectorMultiple } from 'src/components/utilities' +import { + CippCodeBlock, + ModalService, + StatusIcon, + TenantSelectorMultiple, +} from 'src/components/utilities' import CippListOffcanvas from 'src/components/utilities/CippListOffcanvas' import { TitleButton } from 'src/components/buttons' import Skeleton from 'react-loading-skeleton' @@ -136,6 +142,8 @@ const checkAccessColumns = [ ] const GeneralSettings = () => { + const { data: versions, isSuccess: isSuccessVersion } = useLoadVersionsQuery() + const { data: tenants = [] } = useListTenantsQuery({ AllTenantSelector: false }) const [checkPermissions, permissionsResult] = useLazyExecPermissionsAccessCheckQuery() const [clearCache, clearCacheResult] = useLazyExecClearCacheQuery() @@ -278,7 +286,39 @@ const GeneralSettings = () => { return (
    - + + + + Frontend Version + + + +
    Latest: {isSuccessVersion ? versions.RemoteCIPPVersion : }
    +
    Current: {isSuccessVersion ? versions.LocalCIPPVersion : }
    +
    +
    +
    + + + + API Version + + + +
    Latest: {isSuccessVersion ? versions.RemoteCIPPAPIVersion : }
    +
    Current: {isSuccessVersion ? versions.LocalCIPPAPIVersion : }
    +
    +
    +
    +
    + + Permissions Check diff --git a/src/views/home/Home.js b/src/views/home/Home.js index f0fc78f8e10a..0a8bfc6d5f46 100644 --- a/src/views/home/Home.js +++ b/src/views/home/Home.js @@ -1,7 +1,29 @@ import React from 'react' -import { faBook, faExclamation, faSearch } from '@fortawesome/free-solid-svg-icons' -import { CButton, CCallout, CCol, CRow } from '@coreui/react' -import { useLoadDashQuery, useLoadVersionsQuery } from 'src/store/api/app' +import { + faBook, + faExclamation, + faHotel, + faLaptop, + faLaptopCode, + faSearch, + faUsers, + faWrench, +} from '@fortawesome/free-solid-svg-icons' +import { + CButton, + CCallout, + CCol, + CDropdown, + CDropdownToggle, + CListGroup, + CListGroupItem, + CRow, +} from '@coreui/react' +import { + useGenericGetRequestQuery, + useLoadDashQuery, + useLoadVersionsQuery, +} from 'src/store/api/app' import { FastSwitcher, StatusIcon } from 'src/components/utilities' import { CippContentCard } from 'src/components/layout' import { CippTable } from 'src/components/tables' @@ -9,10 +31,29 @@ import { Link } from 'react-router-dom' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import Skeleton from 'react-loading-skeleton' import { UniversalSearch } from 'src/components/utilities/UniversalSearch' +import { ListGroupContentCard } from 'src/components/contentcards' +import { useSelector } from 'react-redux' const Home = () => { + const currentTenant = useSelector((state) => state.app.currentTenant) + const { + data: organization, + isLoading: isLoadingOrg, + isSuccess: issuccessOrg, + } = useGenericGetRequestQuery({ + path: '/api/ListOrg', + params: { tenantFilter: currentTenant.defaultDomainName }, + }) + + const { + data: dashboard, + isLoading: isLoadingUserCounts, + isSuccess: issuccessUserCounts, + } = useGenericGetRequestQuery({ + path: '/api/ListuserCounts', + params: { tenantFilter: currentTenant.defaultDomainName }, + }) const { data: versions, isSuccess: isSuccessVersion } = useLoadVersionsQuery() - const { data: dashboard, isLoading: isLoadingDash, isSuccess: issuccessDash } = useLoadDashQuery() const tableColumns = [ { name: 'Tenant', @@ -27,8 +68,22 @@ const Home = () => { ] return ( <> - - + + + + + Actions + + + + + + @@ -38,90 +93,102 @@ const Home = () => { - - - - {!isLoadingDash && dashboard.Alerts ? ( - dashboard.Alerts.map((mappedAlert, idx) => ( - - {mappedAlert} - - )) - ) : ( - No Active Alerts - )} - - - - - -
    {!isLoadingDash ? dashboard?.NextStandardsRun : }
    + + + +
    {!isLoadingUserCounts ? dashboard?.Users : }
    - - -
    {!isLoadingDash ? dashboard?.NextBPARun : }
    + + +
    {!isLoadingUserCounts ? dashboard?.LicUsers : }
    {' '}
    - - -
    {!isLoadingDash ? dashboard?.queuedApps : }
    + + +
    {!isLoadingUserCounts ? dashboard?.Gas : }
    {' '}
    - - -
    {!isLoadingDash ? dashboard?.queuedStandards : }
    -
    -
    - - -
    {!isLoadingDash ? dashboard?.tenantCount : }
    -
    -
    - - -
    - Refresh Token: {!isLoadingDash ? dashboard?.RefreshTokenDate : ''} -
    -
    -
    - - - -
    Latest: {isSuccessVersion ? versions.RemoteCIPPVersion : }
    -
    Current: {isSuccessVersion ? versions.LocalCIPPVersion : }
    -
    -
    - - - -
    Latest: {isSuccessVersion ? versions.RemoteCIPPAPIVersion : }
    -
    Current: {isSuccessVersion ? versions.LocalCIPPAPIVersion : }
    -
    -
    - - - {!isLoadingDash && issuccessDash && ( - - )} - {isLoadingDash && } - - - Jump to log - - + + +
    {!isLoadingUserCounts ? dashboard?.Guests : }
    {' '}
    + + + + +

    Tenant Name

    + {currentTenant?.displayName} +
    + +

    Tenant ID

    + {currentTenant?.customerId} +
    + +

    Default Domain Name

    + {currentTenant?.defaultDomainName} +
    +
    + + +

    Tenant Status

    + {currentTenant?.delegatedPrivilegeStatus} +
    + +

    Creation Date

    + {isLoadingOrg && } + {organization && organization?.createdDateTime} +
    + +

    Current Secure Score

    + {isLoadingOrg && } +
    +
    + + +

    AD Connect Status

    + {isLoadingOrg && } + {JSON.stringify(organization?.onPremisesSyncStatus)} +
    + +

    Domain(s)

    + {isLoadingOrg && } + {organization?.verifiedDomains.map((item) => ( +
  • {item.name}
  • + ))} +
    + +

    Capabilities

    + {isLoadingOrg && } + {organization && + JSON.stringify(organization.assignedPlans).includes('AADPremiumService') && ( +
  • AAD Premium
  • + )} + {organization && + JSON.stringify(organization.assignedPlans).includes('WindowsDefenderATP') && ( +
  • Windows Defender
  • + )} +
    +
    + + +

    Applied Standards

    + {isLoadingOrg && } +
    + +

    Last Results

    + {isLoadingOrg && } +
    + +

    Access Type

    + {isLoadingOrg && } +
    +
    +
    +
    ) } From c34ff126ce17dd304e782571e851380e45a74cec Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Tue, 25 Apr 2023 15:21:49 +0200 Subject: [PATCH 088/124] added standard --- src/data/standards.json | 7 ++ src/views/home/Home.js | 233 ++++++++++++++++++++++++---------------- 2 files changed, 146 insertions(+), 94 deletions(-) diff --git a/src/data/standards.json b/src/data/standards.json index 65db91dab662..a5a8f4bfcfea 100644 --- a/src/data/standards.json +++ b/src/data/standards.json @@ -71,6 +71,13 @@ "addedComponent": null, "label": "Disable Basic Authentication" }, + { + "name": "standards.laps", + "cat": "AAD", + "helpText": "Enables the tenant to use LAPS", + "addedComponent": null, + "label": "Enable LAPs on the tenant" + }, { "name": "standards.PWnumberMatchingRequiredState", "cat": "AAD", diff --git a/src/views/home/Home.js b/src/views/home/Home.js index 0a8bfc6d5f46..f4e45cc88da8 100644 --- a/src/views/home/Home.js +++ b/src/views/home/Home.js @@ -1,11 +1,17 @@ import React from 'react' import { + faBan, faBook, + faCog, + faEllipsisH, + faEnvelope, faExclamation, faHotel, faLaptop, faLaptopCode, faSearch, + faShareAlt, + faSync, faUsers, faWrench, } from '@fortawesome/free-solid-svg-icons' @@ -31,7 +37,7 @@ import { Link } from 'react-router-dom' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import Skeleton from 'react-loading-skeleton' import { UniversalSearch } from 'src/components/utilities/UniversalSearch' -import { ListGroupContentCard } from 'src/components/contentcards' +import { ActionContentCard, ListGroupContentCard } from 'src/components/contentcards' import { useSelector } from 'react-redux' const Home = () => { @@ -53,35 +59,64 @@ const Home = () => { path: '/api/ListuserCounts', params: { tenantFilter: currentTenant.defaultDomainName }, }) - const { data: versions, isSuccess: isSuccessVersion } = useLoadVersionsQuery() - const tableColumns = [ + + const actions1 = [ + { + label: 'M365 Admin', + link: '#', + icon: faCog, + }, + { + label: 'Exchange', + link: '#', + icon: faSync, + }, + { + label: 'Intune', + link: '#', + icon: faEnvelope, + }, { - name: 'Tenant', - selector: (row) => row['Tenant'], - sortable: true, + label: 'Entra', + link: '#', + icon: faEnvelope, }, { - name: 'Message', - selector: (row) => row['Message'], - sortable: true, + label: 'Security', + link: '#', + icon: faEnvelope, + }, + ] + + const actions2 = [ + { + label: 'Edit Tenant', + link: `/tenant/administration/tenants/Edit?customerId=${currentTenant.customerId}&tenantFilter=${currentTenant.defaultDomainName}`, + icon: faCog, + }, + { + label: 'List Users', + link: '#', + icon: faSync, + }, + { + label: 'List Groups', + link: '#', + icon: faSync, + }, + { + label: 'Create User', + link: '#', + icon: faSync, + }, + { + label: 'Create Group', + link: '#', + icon: faEnvelope, }, ] return ( <> - - - - - Actions - - - - @@ -117,77 +152,87 @@ const Home = () => { - - - -

    Tenant Name

    - {currentTenant?.displayName} -
    - -

    Tenant ID

    - {currentTenant?.customerId} -
    - -

    Default Domain Name

    - {currentTenant?.defaultDomainName} -
    -
    - - -

    Tenant Status

    - {currentTenant?.delegatedPrivilegeStatus} -
    - -

    Creation Date

    - {isLoadingOrg && } - {organization && organization?.createdDateTime} -
    - -

    Current Secure Score

    - {isLoadingOrg && } -
    -
    - - -

    AD Connect Status

    - {isLoadingOrg && } - {JSON.stringify(organization?.onPremisesSyncStatus)} -
    - -

    Domain(s)

    - {isLoadingOrg && } - {organization?.verifiedDomains.map((item) => ( -
  • {item.name}
  • - ))} -
    - -

    Capabilities

    - {isLoadingOrg && } - {organization && - JSON.stringify(organization.assignedPlans).includes('AADPremiumService') && ( -
  • AAD Premium
  • - )} - {organization && - JSON.stringify(organization.assignedPlans).includes('WindowsDefenderATP') && ( -
  • Windows Defender
  • - )} -
    -
    - - -

    Applied Standards

    - {isLoadingOrg && } -
    - -

    Last Results

    - {isLoadingOrg && } -
    - -

    Access Type

    - {isLoadingOrg && } -
    -
    -
    + + + + +

    Tenant Name

    + {currentTenant?.displayName} +
    + +

    Tenant ID

    + {currentTenant?.customerId} +
    + +

    Default Domain Name

    + {currentTenant?.defaultDomainName} +
    +
    + + +

    Tenant Status

    + {currentTenant?.delegatedPrivilegeStatus} +
    + +

    Creation Date

    + {isLoadingOrg && } + {organization && organization?.createdDateTime} +
    + +

    Current Secure Score

    + {isLoadingOrg && } +
    +
    + + +

    AD Connect Status

    + {isLoadingOrg && } + {JSON.stringify(organization?.onPremisesSyncStatus)} +
    + +

    Domain(s)

    + {isLoadingOrg && } + {organization?.verifiedDomains.map((item) => ( +
  • {item.name}
  • + ))} +
    + +

    Capabilities

    + {isLoadingOrg && } + {organization && + JSON.stringify(organization.assignedPlans).includes('AADPremiumService') && ( +
  • AAD Premium
  • + )} + {organization && + JSON.stringify(organization.assignedPlans).includes('WindowsDefenderATP') && ( +
  • Windows Defender
  • + )} +
    +
    + + +

    Applied Standards

    + {isLoadingOrg && } +
    + +

    Last Results

    + {isLoadingOrg && } +
    + +

    Access Type

    + {isLoadingOrg && } +
    +
    +
    +
    +
    + + + + + + + ) From 0cb5596373cf8daf97b2948d5eda1911ecdaaa1a Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Tue, 25 Apr 2023 17:54:16 +0200 Subject: [PATCH 089/124] added devices functions --- src/views/endpoint/intune/Devices.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/views/endpoint/intune/Devices.js b/src/views/endpoint/intune/Devices.js index 7d618378a044..35ad9f2c3b8c 100644 --- a/src/views/endpoint/intune/Devices.js +++ b/src/views/endpoint/intune/Devices.js @@ -44,6 +44,22 @@ const Offcanvas = (row, rowIndex, formatExtraData) => { modalUrl: `/api/ExecDeviceAction?TenantFilter=${tenant.defaultDomainName}&GUID=${row.id}&Action=locateDevice`, modalMessage: 'Are you sure you want to locate this device?', }, + { + label: 'Retrieve LAPs password', + color: 'info', + modal: true, + modalUrl: `/api/ExecGetLocalAdminPassword?TenantFilter=${tenant.defaultDomainName}&GUID=${row.azureADDeviceId}`, + modalMessage: 'Are you sure you want to retrieve the Bitlocker keys?', + }, + { + label: 'Rotate Local Admin Password', + color: 'info', + modal: true, + modalType: 'POST', + modalBody: {}, + modalUrl: `/api/ExecDeviceAction?TenantFilter=${tenant.defaultDomainName}&GUID=${row.id}&Action=RotateLocalAdminPassword`, + modalMessage: 'Are you sure you want to rotate the password for this device?', + }, { label: 'Retrieve Bitlocker Keys', color: 'info', From 807e259d65b33fa835ebbcbbd8f741138ad1823c Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Tue, 25 Apr 2023 18:18:28 +0200 Subject: [PATCH 090/124] removed old logging --- src/components/tables/CellGenericFormat.js | 1 - src/components/tables/CippTable.js | 1 - src/components/utilities/ReportImage.js | 2 -- src/views/cipp/CIPPSettings.js | 2 -- 4 files changed, 6 deletions(-) diff --git a/src/components/tables/CellGenericFormat.js b/src/components/tables/CellGenericFormat.js index 4386c3eafbc7..6c31e2d6f4b4 100644 --- a/src/components/tables/CellGenericFormat.js +++ b/src/components/tables/CellGenericFormat.js @@ -79,7 +79,6 @@ export const cellGenericFormatter = return CellTip(cell) } if (Array.isArray(cell) || typeof cell === 'object') { - console.log(cell) return CellTip(JSON.stringify(cell)) } } diff --git a/src/components/tables/CippTable.js b/src/components/tables/CippTable.js index a025dcaae217..0d3f0549d96f 100644 --- a/src/components/tables/CippTable.js +++ b/src/components/tables/CippTable.js @@ -285,7 +285,6 @@ export default function CippTable({ } const newModalBody = {} for (let [objName, objValue] of Object.entries(modalBody)) { - console.log(objValue) if (objValue.toString().startsWith('!')) { newModalBody[objName] = row[objValue.replace('!', '')] } diff --git a/src/components/utilities/ReportImage.js b/src/components/utilities/ReportImage.js index ed6084dca692..d5aead2b9069 100644 --- a/src/components/utilities/ReportImage.js +++ b/src/components/utilities/ReportImage.js @@ -14,9 +14,7 @@ const ReportImage = () => { const reader = new FileReader() reader.readAsDataURL(e.target.files[0]) reader.onloadend = () => { - console.log(reader.result) dispatch(setReportImage({ reportImage: reader.result })) - console.log(ReportImage) } } diff --git a/src/views/cipp/CIPPSettings.js b/src/views/cipp/CIPPSettings.js index 8bf6cf9cf74e..1ecb75605980 100644 --- a/src/views/cipp/CIPPSettings.js +++ b/src/views/cipp/CIPPSettings.js @@ -943,7 +943,6 @@ const NotificationsSettings = () => { const [configNotifications, notificationConfigResult] = useLazyExecNotificationConfigQuery() const [listNotification, notificationListResult] = useLazyListNotificationConfigQuery() const onSubmit = (values) => { - console.log(values) configNotifications(values) } return ( @@ -1278,7 +1277,6 @@ const Maintenance = () => { } const handleGetLink = () => { - console.log('Making link') listScriptLink({ path: 'api/ExecMaintenanceScripts', params: { ScriptFile: selectedScript, MakeLink: 'True' }, From 423890b3fe14e54feb3ac3cba6b5a8a6b28644c8 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Tue, 25 Apr 2023 18:27:50 +0200 Subject: [PATCH 091/124] fixed crash on home --- src/views/home/Home.js | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/src/views/home/Home.js b/src/views/home/Home.js index f4e45cc88da8..60057a4416d7 100644 --- a/src/views/home/Home.js +++ b/src/views/home/Home.js @@ -1,40 +1,22 @@ import React from 'react' import { - faBan, faBook, faCog, faEllipsisH, faEnvelope, - faExclamation, faHotel, - faLaptop, faLaptopCode, faSearch, - faShareAlt, faSync, faUsers, - faWrench, } from '@fortawesome/free-solid-svg-icons' -import { - CButton, - CCallout, - CCol, - CDropdown, - CDropdownToggle, - CListGroup, - CListGroupItem, - CRow, -} from '@coreui/react' +import { CCol, CRow } from '@coreui/react' import { useGenericGetRequestQuery, useLoadDashQuery, useLoadVersionsQuery, } from 'src/store/api/app' -import { FastSwitcher, StatusIcon } from 'src/components/utilities' import { CippContentCard } from 'src/components/layout' -import { CippTable } from 'src/components/tables' -import { Link } from 'react-router-dom' -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import Skeleton from 'react-loading-skeleton' import { UniversalSearch } from 'src/components/utilities/UniversalSearch' import { ActionContentCard, ListGroupContentCard } from 'src/components/contentcards' From bafe5d61121c813fa9b295952e3792b9ed9024ef Mon Sep 17 00:00:00 2001 From: BNWEIN Date: Wed, 26 Apr 2023 13:34:56 +0100 Subject: [PATCH 092/124] Fixed "Do you want to retrieve Bitlocker key" to "Local Admin Password" Fixed "Do you want to retrieve Bitlocker key" to "Local Admin Password" --- src/views/endpoint/intune/Devices.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/views/endpoint/intune/Devices.js b/src/views/endpoint/intune/Devices.js index 35ad9f2c3b8c..06d28a18c558 100644 --- a/src/views/endpoint/intune/Devices.js +++ b/src/views/endpoint/intune/Devices.js @@ -49,7 +49,7 @@ const Offcanvas = (row, rowIndex, formatExtraData) => { color: 'info', modal: true, modalUrl: `/api/ExecGetLocalAdminPassword?TenantFilter=${tenant.defaultDomainName}&GUID=${row.azureADDeviceId}`, - modalMessage: 'Are you sure you want to retrieve the Bitlocker keys?', + modalMessage: 'Are you sure you want to retrieve the local admin password?', }, { label: 'Rotate Local Admin Password', From 81c9f2788e5abe2fc6a3e771ba4156f0851dd431 Mon Sep 17 00:00:00 2001 From: John Duprey Date: Wed, 26 Apr 2023 11:17:34 -0400 Subject: [PATCH 093/124] Tenant overview tweaks --- src/views/home/Home.js | 51 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 42 insertions(+), 9 deletions(-) diff --git a/src/views/home/Home.js b/src/views/home/Home.js index 60057a4416d7..5bb25ce30471 100644 --- a/src/views/home/Home.js +++ b/src/views/home/Home.js @@ -21,6 +21,11 @@ import Skeleton from 'react-loading-skeleton' import { UniversalSearch } from 'src/components/utilities/UniversalSearch' import { ActionContentCard, ListGroupContentCard } from 'src/components/contentcards' import { useSelector } from 'react-redux' +import TimeAgo from 'javascript-time-ago' + +import en from 'javascript-time-ago/locale/en.json' +TimeAgo.addDefaultLocale(en) +import ReactTimeAgo from 'react-time-ago' const Home = () => { const currentTenant = useSelector((state) => state.app.currentTenant) @@ -169,7 +174,28 @@ const Home = () => {

    AD Connect Status

    {isLoadingOrg && } - {JSON.stringify(organization?.onPremisesSyncStatus)} + {!isLoadingOrg && organization?.onPremisesSyncEnabled ? ( + <> +
  • + Directory Sync: + {organization?.onPremisesLastSyncDateTime ? ( + + ) : ( + 'Never' + )} +
  • +
  • + Password Sync: + {organization?.onPremisesLastPasswordSyncDateTime ? ( + + ) : ( + 'Never' + )} +
  • + + ) : ( + 'Disabled' + )}

    Domain(s)

    @@ -181,14 +207,21 @@ const Home = () => {

    Capabilities

    {isLoadingOrg && } - {organization && - JSON.stringify(organization.assignedPlans).includes('AADPremiumService') && ( -
  • AAD Premium
  • - )} - {organization && - JSON.stringify(organization.assignedPlans).includes('WindowsDefenderATP') && ( -
  • Windows Defender
  • - )} + {organization?.assignedPlans + .filter((p) => p.capabilityStatus == 'Enabled') + .reduce((plan, curr) => { + if (!plan.includes(curr.service)) { + plan.push(curr.service) + } + return plan + }, []) + .map((plan) => ( + <> + {plan == 'exchange' &&
  • Exchange
  • } + {plan == 'AADPremiumService' &&
  • AAD Premium
  • } + {plan == 'WindowsDefenderATP' &&
  • Windows Defender
  • } + + ))}
    From 05408a1a311e910e1d973f2b558be0386e7a8135 Mon Sep 17 00:00:00 2001 From: John Duprey Date: Thu, 27 Apr 2023 17:27:47 -0400 Subject: [PATCH 094/124] Tenant selector tweaks --- src/components/header/AppHeaderSearch.js | 4 +- src/components/layout/AppHeader.js | 59 ++++++++++++---------- src/components/utilities/TenantSelector.js | 12 ++++- src/scss/_custom.scss | 1 - src/scss/_tenantselector.scss | 2 +- src/views/home/Home.js | 46 ++++++++--------- 6 files changed, 67 insertions(+), 57 deletions(-) diff --git a/src/components/header/AppHeaderSearch.js b/src/components/header/AppHeaderSearch.js index d6d33b383420..6b4ab4b50d9a 100644 --- a/src/components/header/AppHeaderSearch.js +++ b/src/components/header/AppHeaderSearch.js @@ -12,8 +12,8 @@ const AppHeaderSearch = () => { }, [dispatch]) return ( <> - - + + ) diff --git a/src/components/layout/AppHeader.js b/src/components/layout/AppHeader.js index 3c5838a73652..c74f51eec2b1 100644 --- a/src/components/layout/AppHeader.js +++ b/src/components/layout/AppHeader.js @@ -4,8 +4,10 @@ import { CAlert, CAlertLink, CContainer, + CCollapse, CHeader, CHeaderNav, + CNavItem, CHeaderToggler, CImage, CSidebarBrand, @@ -35,37 +37,38 @@ const AppHeader = () => { return ( <> - - - - - + + + dispatch(toggleSidebarShow({ sidebarShow }))} + > + dispatch(toggleSidebarShow({ sidebarShow }))} - > - - - - - - - + /> + + + + + + + + - - + + {dashboard && diff --git a/src/components/utilities/TenantSelector.js b/src/components/utilities/TenantSelector.js index 78acb972038e..9a93ea7348eb 100644 --- a/src/components/utilities/TenantSelector.js +++ b/src/components/utilities/TenantSelector.js @@ -7,6 +7,8 @@ import { setCurrentTenant } from 'src/store/features/app' import { CDropdown, CDropdownMenu, CDropdownToggle } from '@coreui/react' import { useNavigate, useSearchParams } from 'react-router-dom' import { queryString } from 'src/helpers' +import { faBuilding } from '@fortawesome/free-solid-svg-icons' +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' const TenantSelector = ({ action, showAllTenantSelector = true, NavSelector = false }) => { const currentTenant = useSelector((state) => state.app.currentTenant) @@ -73,11 +75,17 @@ const TenantSelector = ({ action, showAllTenantSelector = true, NavSelector = fa return ( <> {NavSelector && ( - + + {currentTenant?.defaultDomainName ? ( <> - Selected Tenant: {currentTenant.displayName} + {currentTenant.displayName} ) : ( placeholder diff --git a/src/scss/_custom.scss b/src/scss/_custom.scss index 17dd5c4b8ca1..95f65a7aa949 100644 --- a/src/scss/_custom.scss +++ b/src/scss/_custom.scss @@ -530,7 +530,6 @@ } .dropdown-menu.show.tenantDropdown { padding: 1px; - margin-left: 15px; } .header.header-sticky { diff --git a/src/scss/_tenantselector.scss b/src/scss/_tenantselector.scss index 2a8969d4e149..20affa6d0cdc 100644 --- a/src/scss/_tenantselector.scss +++ b/src/scss/_tenantselector.scss @@ -199,6 +199,6 @@ } .tenantDropdown { - min-width: 30rem; + min-width: 25rem; } diff --git a/src/views/home/Home.js b/src/views/home/Home.js index 5bb25ce30471..f968d8a90992 100644 --- a/src/views/home/Home.js +++ b/src/views/home/Home.js @@ -116,23 +116,23 @@ const Home = () => {
    - - + +
    {!isLoadingUserCounts ? dashboard?.Users : }
    - +
    {!isLoadingUserCounts ? dashboard?.LicUsers : }
    {' '}
    - +
    {!isLoadingUserCounts ? dashboard?.Gas : }
    {' '}
    - +
    {!isLoadingUserCounts ? dashboard?.Guests : }
    {' '}
    @@ -141,37 +141,37 @@ const Home = () => { - - + +

    Tenant Name

    {currentTenant?.displayName}
    - +

    Tenant ID

    {currentTenant?.customerId}
    - +

    Default Domain Name

    {currentTenant?.defaultDomainName}
    - - + +

    Tenant Status

    {currentTenant?.delegatedPrivilegeStatus}
    - +

    Creation Date

    {isLoadingOrg && } {organization && organization?.createdDateTime}
    - +

    Current Secure Score

    {isLoadingOrg && }
    - - + +

    AD Connect Status

    {isLoadingOrg && } {!isLoadingOrg && organization?.onPremisesSyncEnabled ? ( @@ -197,14 +197,14 @@ const Home = () => { 'Disabled' )}
    - +

    Domain(s)

    {isLoadingOrg && } {organization?.verifiedDomains.map((item) => (
  • {item.name}
  • ))}
    - +

    Capabilities

    {isLoadingOrg && } {organization?.assignedPlans @@ -224,16 +224,16 @@ const Home = () => { ))}
    - - + +

    Applied Standards

    {isLoadingOrg && }
    - +

    Last Results

    {isLoadingOrg && }
    - +

    Access Type

    {isLoadingOrg && }
    @@ -242,10 +242,10 @@ const Home = () => {
    - + - + From 143df2810e79019f2285a31cf91227f0eaa94cb5 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Thu, 27 Apr 2023 23:35:16 +0200 Subject: [PATCH 095/124] added cal standard --- src/data/standards.json | 70 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/src/data/standards.json b/src/data/standards.json index a5a8f4bfcfea..7ba5398d61b2 100644 --- a/src/data/standards.json +++ b/src/data/standards.json @@ -314,6 +314,76 @@ }, "label": "Set Sharing Level for OneDrive and Sharepoint" }, + { + "name": "standards.calDefault.Enabled", + "cat": "Exchange", + "helpText": "This is the default helptext", + "addedComponent": { + "type": "Select", + "label": "Select Sharing Level", + "name": "standards.calDefault.permissionlevel", + "values": [ + { + "label": "Owner - The user can create, read, edit, and delete all items in the folder, and create subfolders. The user is both folder owner and folder contact.", + "value": "Owner" + }, + { + "label": "Publishing Editor - The user can create, read, edit, and delete all items in the folder, and create subfolders.", + "value": "PublishingEditor" + }, + { + "label": "Reviewer - The user can read all items in the folder.", + "value": "Reviewer" + }, + { + "label": "Editor - The user can create items in the folder. The contents of the folder do not appear.", + "value": "Contributor" + }, + { + "label": "Free Busy Time And Subject And Location - The user can view free/busy time within the calendar and the subject and location of appointments.", + "value": "FreeBusyTimeAndSubjectAndLocation" + }, + { + "label": "Indicates that the user can view only free/busy time within the calendar.", + "value": "FreeBusyTimeOnly" + }, + { + "label": "None - The user has no permissions on the folder.", + "value": "none" + } + ] + }, + "label": "Set Sharing Level for OneDrive and Sharepoint" + }, + { + "name": "standards.sharingCapability.Enabled", + "cat": "SharePoint", + "helpText": "This is the default helptext", + "addedComponent": { + "type": "Select", + "label": "Select Sharing Level", + "name": "standards.sharingCapability.Level", + "values": [ + { + "label": "Users can share only with people in the organization. No external sharing is allowed.", + "value": "disabled" + }, + { + "label": "Users can share with new and existing guests. Guests must sign in or provide a verification code.", + "value": "externalUserSharingOnly" + }, + { + "label": "Users can share with anyone by using links that do not require sign-in.", + "value": "externalUserAndGuestSharing" + }, + { + "label": "Users can share with existing guests (those already in the directory of the organization).", + "value": "existingExternalUserSharingOnly" + } + ] + }, + "label": "Set Sharing Level for OneDrive and Sharepoint" + }, { "name": "standards.ExcludedfileExt.Enabled", "cat": "SharePoint", From 81f89d52a79518529ed3cdaf061c2dd6fc19ba44 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Thu, 27 Apr 2023 23:55:15 +0200 Subject: [PATCH 096/124] added caldefault --- 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 7ba5398d61b2..b500086e7b37 100644 --- a/src/data/standards.json +++ b/src/data/standards.json @@ -353,7 +353,7 @@ } ] }, - "label": "Set Sharing Level for OneDrive and Sharepoint" + "label": "Set Sharing Level for Default calendar" }, { "name": "standards.sharingCapability.Enabled", From ccab7bae3ba0de8824f2beeaa93987dcc2c055b7 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Fri, 28 Apr 2023 00:11:51 +0200 Subject: [PATCH 097/124] added maximum devices --- src/data/standards.json | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/data/standards.json b/src/data/standards.json index b500086e7b37..cfefef351539 100644 --- a/src/data/standards.json +++ b/src/data/standards.json @@ -78,6 +78,17 @@ "addedComponent": null, "label": "Enable LAPs on the tenant" }, + { + "name": "standards.intuneDeviceReg.Enabled", + "cat": "AAD", + "helpText": "This is the default helptext", + "addedComponent": { + "type": "input", + "name": "standards.intuneDeviceReg.max", + "label": "Maximum devices (Enter 2147483647 for unlimited.)" + }, + "label": "Set Maximum Number of Devices per user" + }, { "name": "standards.PWnumberMatchingRequiredState", "cat": "AAD", From 5cc03d0ea1c240653a836cdad026187c68f5ca8c Mon Sep 17 00:00:00 2001 From: John Duprey Date: Sun, 30 Apr 2023 19:31:03 -0400 Subject: [PATCH 098/124] GDAP Relationships --- src/_nav.js | 5 ++ src/adminRoutes.js | 10 ++- src/components/tables/CellDate.js | 67 +++++++++++------- .../administration/ListGDAPRelationships.js | 68 +++++++++++++++++++ 4 files changed, 126 insertions(+), 24 deletions(-) create mode 100644 src/views/tenant/administration/ListGDAPRelationships.js diff --git a/src/_nav.js b/src/_nav.js index 3ad3f8a01ca3..f0768034e29a 100644 --- a/src/_nav.js +++ b/src/_nav.js @@ -689,6 +689,11 @@ const _nav = [ name: 'GDAP Migration Status', to: '/tenant/administration/gdap-status', }, + { + component: CNavItem, + name: 'GDAP Relationships', + to: '/tenant/administration/gdap-relationships', + }, { component: CNavItem, name: 'Documentation', diff --git a/src/adminRoutes.js b/src/adminRoutes.js index e33468c53952..7bc567c1aa56 100644 --- a/src/adminRoutes.js +++ b/src/adminRoutes.js @@ -1,11 +1,14 @@ import React from 'react' -const CIPPSettings = React.lazy(() => import('src/views/cipp/CIPPSettings')) +const CIPPSettings = import('src/views/cipp/CIPPSettings') const Setup = React.lazy(() => import('src/views/cipp/Setup')) const ApplyStandard = React.lazy(() => import('src/views/tenant/standards/ApplyStandard')) const GDAPStatus = React.lazy(() => import('src/views/tenant/administration/ListGDAPQueue')) const GDAP = React.lazy(() => import('src/views/tenant/administration/GDAPWizard')) const GDAPRoleWizard = React.lazy(() => import('src/views/tenant/administration/GDAPRoleWizard')) const GDAPRoles = React.lazy(() => import('src/views/tenant/administration/ListGDAPRoles')) +const GDAPRelationships = React.lazy(() => + import('./views/tenant/administration/ListGDAPRelationships'), +) const appapproval = React.lazy(() => import('src/views/cipp/AppApproval')) const adminRoutes = [ @@ -24,6 +27,11 @@ const adminRoutes = [ name: 'GDAP Roles', component: GDAPRoles, }, + { + path: '/tenant/administration/gdap-relationships', + name: 'GDAP Relationships', + component: GDAPRelationships, + }, { path: '/tenant/administration/appapproval', name: 'App Approval', component: appapproval }, { path: '/tenant/administration/gdap-status', name: 'GDAP Status', component: GDAPStatus }, { path: '/tenant/standards/apply-standard', name: 'Apply Standard', component: ApplyStandard }, diff --git a/src/components/tables/CellDate.js b/src/components/tables/CellDate.js index 91b45eea2f1b..c3934ffcb83d 100644 --- a/src/components/tables/CellDate.js +++ b/src/components/tables/CellDate.js @@ -2,10 +2,14 @@ import React from 'react' import moment from 'moment' import PropTypes from 'prop-types' import { CTooltip } from '@coreui/react' +import TimeAgo from 'javascript-time-ago' +import en from 'javascript-time-ago/locale/en.json' +TimeAgo.addDefaultLocale(en) +import ReactTimeAgo from 'react-time-ago' /** * - * @param format ['short', 'long'] + * @param format ['short', 'long', 'relative'] * @param value * @returns {JSX.Element} * @constructor @@ -27,35 +31,52 @@ export const CellDate = ({ format = 'short', showTime = true, showDate = true, c ] const dateTimeFormatOptions = {} + if (format == 'relative') { + try { + return ( + + + + ) + } catch (error) { + console.error('Error formatting date, fallback to string value', { date: cell, error }) + return ( + +
    {String(cell)}
    +
    + ) + } + } else { + if (showTime) { + dateTimeFormatOptions.timeStyle = format + } + if (showDate) { + dateTimeFormatOptions.dateStyle = format + } - if (showTime) { - dateTimeFormatOptions.timeStyle = format - } - if (showDate) { - dateTimeFormatOptions.dateStyle = format - } + dateTimeArgs.push(dateTimeFormatOptions) - dateTimeArgs.push(dateTimeFormatOptions) + let formatted - let formatted - try { - // lots of dates returned are unreliably parsable (e.g. non ISO8601 format) - // fallback using moment to parse into date object - formatted = new Intl.DateTimeFormat(...dateTimeArgs).format(moment(cell).toDate()) - } catch (error) { - console.error('Error formatting date, fallback to string value', { date: cell, error }) - formatted = cell - } + try { + // lots of dates returned are unreliably parsable (e.g. non ISO8601 format) + // fallback using moment to parse into date object + formatted = new Intl.DateTimeFormat(...dateTimeArgs).format(moment(cell).toDate()) + } catch (error) { + console.error('Error formatting date, fallback to string value', { date: cell, error }) + formatted = cell + } - return ( - -
    {String(formatted)}
    -
    - ) + return ( + +
    {String(formatted)}
    +
    + ) + } } CellDate.propTypes = { - format: PropTypes.oneOf(['short', 'medium', 'long', 'full']), + format: PropTypes.oneOf(['short', 'medium', 'long', 'full', 'relative']), cell: PropTypes.oneOfType([PropTypes.string, PropTypes.instanceOf(Date)]), showTime: PropTypes.bool, showDate: PropTypes.bool, diff --git a/src/views/tenant/administration/ListGDAPRelationships.js b/src/views/tenant/administration/ListGDAPRelationships.js new file mode 100644 index 000000000000..564de823ede8 --- /dev/null +++ b/src/views/tenant/administration/ListGDAPRelationships.js @@ -0,0 +1,68 @@ +import React from 'react' +import { useSelector } from 'react-redux' +import { CSpinner, CCallout } from '@coreui/react' +import { CippPageList } from 'src/components/layout' +import { cellDateFormatter, cellNullTextFormatter } from 'src/components/tables' + +const GDAPRelationships = () => { + const columns = [ + { + name: 'Tenant', + selector: (row) => row.customer?.displayName, + sortable: true, + exportSelector: 'customer', + cell: cellNullTextFormatter(), + }, + { + name: 'Relationship Name', + selector: (row) => row['displayName'], + sortable: true, + exportSelector: 'displayName', + }, + { + name: 'Status', + selector: (row) => row['status'], + sortable: true, + exportSelector: 'status', + }, + { + name: 'Created', + selector: (row) => row['createdDateTime'], + sortable: true, + exportSelector: 'createdDateTime', + cell: cellDateFormatter({ format: 'short' }), + }, + { + name: 'Activated', + selector: (row) => row['activatedDateTime'], + sortable: true, + exportSelector: 'activatedDateTime', + cell: cellDateFormatter({ format: 'short' }), + }, + { + name: 'End', + selector: (row) => row['endDateTime'], + sortable: true, + exportSelector: 'endDateTime', + cell: cellDateFormatter({ format: 'short' }), + }, + ] + return ( +
    + +
    + ) +} + +export default GDAPRelationships From 1cbfe22d2a4ed73b4432ba640d292bbd674dade8 Mon Sep 17 00:00:00 2001 From: John Duprey Date: Sun, 30 Apr 2023 19:33:30 -0400 Subject: [PATCH 099/124] Update adminRoutes.js --- src/adminRoutes.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/adminRoutes.js b/src/adminRoutes.js index 7bc567c1aa56..7fb235df0e0e 100644 --- a/src/adminRoutes.js +++ b/src/adminRoutes.js @@ -1,5 +1,5 @@ import React from 'react' -const CIPPSettings = import('src/views/cipp/CIPPSettings') +const CIPPSettings = React.lazy(() => import('src/views/cipp/CIPPSettings')) const Setup = React.lazy(() => import('src/views/cipp/Setup')) const ApplyStandard = React.lazy(() => import('src/views/tenant/standards/ApplyStandard')) const GDAPStatus = React.lazy(() => import('src/views/tenant/administration/ListGDAPQueue')) From e23d68f9f2dc4c0e2affd6b93334785103d745a9 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Mon, 1 May 2023 13:34:20 +0200 Subject: [PATCH 100/124] updated app approval text --- src/views/cipp/AppApproval.js | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/src/views/cipp/AppApproval.js b/src/views/cipp/AppApproval.js index 25febefe28dd..9c957db0707b 100644 --- a/src/views/cipp/AppApproval.js +++ b/src/views/cipp/AppApproval.js @@ -130,20 +130,16 @@ const GraphExplorer = () => { - This tool helps you to retrieve the approval links required for each - tenant. This is required to use 'Application Permissions' within these - tenants when GDAP is deployed. - - This is a temporary measure as Microsoft is adding this as a feature - to GDAP. - -
    -
    - The approval URL might lead to an error page with the error "Admin Role - not found" or not load any page at all after clicking confirm - This is - expected behavior. -
    -
    +

    + This tool helps you to retrieve the approval links required for each + tenant. This is required to use 'Application Permissions' within these + tenants when GDAP is deployed. +

    +

    + The approval URL might lead to an error page with the error "Admin + Role not found" or not load any page at all after clicking confirm - + This is expected behavior. +

    @@ -152,7 +148,7 @@ const GraphExplorer = () => { type="text" name="applicationid" label="Application ID:" - placeholder="Enter the application ID to generate the approval URLs for. This can be any application. Leave blank to generate this for CIPP." + placeholder="Enter the application ID to generate the approval URLs for. This can be any application." />
    From a63672a8cdda790c0d6497de6a65e9baa16e2f6e Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Mon, 1 May 2023 15:22:24 +0200 Subject: [PATCH 101/124] added tenant lookup --- src/routes.js | 6 + .../tenant/administration/TentantLookup.js | 152 ++++++++++++++++++ 2 files changed, 158 insertions(+) create mode 100644 src/views/tenant/administration/TentantLookup.js diff --git a/src/routes.js b/src/routes.js index bac1f9bf996f..509686c24715 100644 --- a/src/routes.js +++ b/src/routes.js @@ -17,6 +17,7 @@ const AddGroupTemplates = React.lazy(() => const DeployGroupTemplates = React.lazy(() => import('src/views/identity/administration/DeployGroupTemplate'), ) +const TenantLookup = React.lazy(() => import('src/views/tenant/administration/TentantLookup')) const GroupTemplates = React.lazy(() => import('src/views/identity/administration/GroupTemplates')) const EditGroup = React.lazy(() => import('src/views/identity/administration/EditGroup')) @@ -368,6 +369,11 @@ const routes = [ name: 'Individual Domain Check', component: IndividualDomain, }, + { + path: '/tenant/administration/tenantlookup', + name: 'Tenant Lookup', + component: TenantLookup, + }, { path: '/tenant/standards/alert-list', name: 'Alert List (Alpha)', component: ListAlerts }, { path: '/endpoint', name: 'Endpoint' }, { path: '/endpoint/applications', name: 'Applications' }, diff --git a/src/views/tenant/administration/TentantLookup.js b/src/views/tenant/administration/TentantLookup.js new file mode 100644 index 000000000000..f23ebb665054 --- /dev/null +++ b/src/views/tenant/administration/TentantLookup.js @@ -0,0 +1,152 @@ +import React, { useEffect, useState } from 'react' +import { + CButton, + CCard, + CCardBody, + CCardHeader, + CCardTitle, + CCol, + CCollapse, + CForm, + CFormInput, + CInputGroup, + CRow, + CSpinner, +} from '@coreui/react' +import useQuery from 'src/hooks/useQuery' +import { Field, Form } from 'react-final-form' +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' +import { faBook, faSearch } from '@fortawesome/free-solid-svg-icons' +import { useSelector } from 'react-redux' +import { useNavigate } from 'react-router-dom' +import { useLazyGenericGetRequestQuery } from 'src/store/api/app' +import { CippContentCard } from 'src/components/layout' +import Skeleton from 'react-loading-skeleton' +import { domainsApi } from 'src/store/api/domains' + +const GraphExplorer = () => { + let navigate = useNavigate() + const tenant = useSelector((state) => state.app.currentTenant) + let query = useQuery() + const tenantdomain = query.get('tenant') + const SearchNow = query.get('SearchNow') + const [visibleA, setVisibleA] = useState(true) + const handleSubmit = async (values) => { + setVisibleA(false) + + const shippedValues = { + tenant: values.domain, + SearchNow: true, + random: (Math.random() + 1).toString(36).substring(7), + } + var queryString = Object.keys(shippedValues) + .map((key) => key + '=' + shippedValues[key]) + .join('&') + + navigate(`?${queryString}`) + } + const [execGraphRequest, graphrequest] = useLazyGenericGetRequestQuery() + + useEffect(() => { + if (tenantdomain) { + execGraphRequest({ + path: 'api/ListExternalTenantInfo', + params: { + tenant: tenantdomain, + }, + }) + } + }, [execGraphRequest, tenant.defaultDomainName, query, tenantdomain]) + const isValidDomain = (value) => + /^(((?!-))(xn--|_{1,1})?[a-z0-9-]{0,61}[a-z0-9]{1,1}\.)*(xn--)?([a-z0-9][a-z0-9-]{0,60}|[a-z0-9-]{1,30}\.[a-z]{2,})$/i.test( + value, + ) + ? undefined + : value + + return ( + + + + + + + Domain + + + + { + return ( + + + {({ input, meta }) => { + return ( + <> + + + + Check{graphrequest.isFetching && } + + + + ) + }} + + + ) + }} + /> + + + + + + + +

    Tenant Name

    + {graphrequest.isFetching && } + {graphrequest.data?.GraphRequest.displayName} +
    + +

    Tenant ID

    + {graphrequest.isFetching && } + {graphrequest.data?.GraphRequest.tenantId} +
    + +

    Default Domain Name

    + {graphrequest.isFetching && } + {graphrequest.data?.GraphRequest.defaultDomainName} +
    +
    + + +

    Tenant Brand Name

    + {graphrequest.isFetching && } + {graphrequest.data?.GraphRequest.federationBrandName} +
    + +

    Domains

    + {graphrequest.isFetching && } + {graphrequest.data?.Domains && + graphrequest.data?.Domains.map((domainname) =>
  • {domainname}
  • )} +
    +
    +
    +
    +
    + ) +} + +export default GraphExplorer From 5b5a89e00f15c10c7b678755eed246ef179527df Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Mon, 1 May 2023 15:26:26 +0200 Subject: [PATCH 102/124] interface changes --- .../tenant/administration/TentantLookup.js | 72 ++++++++++--------- 1 file changed, 38 insertions(+), 34 deletions(-) diff --git a/src/views/tenant/administration/TentantLookup.js b/src/views/tenant/administration/TentantLookup.js index f23ebb665054..a9faad2d0cc4 100644 --- a/src/views/tenant/administration/TentantLookup.js +++ b/src/views/tenant/administration/TentantLookup.js @@ -111,40 +111,44 @@ const GraphExplorer = () => {
    - - - - -

    Tenant Name

    - {graphrequest.isFetching && } - {graphrequest.data?.GraphRequest.displayName} -
    - -

    Tenant ID

    - {graphrequest.isFetching && } - {graphrequest.data?.GraphRequest.tenantId} -
    - -

    Default Domain Name

    - {graphrequest.isFetching && } - {graphrequest.data?.GraphRequest.defaultDomainName} -
    -
    - - -

    Tenant Brand Name

    - {graphrequest.isFetching && } - {graphrequest.data?.GraphRequest.federationBrandName} -
    - -

    Domains

    - {graphrequest.isFetching && } - {graphrequest.data?.Domains && - graphrequest.data?.Domains.map((domainname) =>
  • {domainname}
  • )} -
    -
    -
    -
    + {tenantdomain && ( + + + + +

    Tenant Name

    + {graphrequest.isFetching && } + {graphrequest.data?.GraphRequest.displayName} +
    + +

    Tenant ID

    + {graphrequest.isFetching && } + {graphrequest.data?.GraphRequest.tenantId} +
    + +

    Default Domain Name

    + {graphrequest.isFetching && } + {graphrequest.data?.GraphRequest.defaultDomainName} +
    +
    + + +

    Tenant Brand Name

    + {graphrequest.isFetching && } + {graphrequest.data?.GraphRequest.federationBrandName} + {graphrequest.data?.GraphRequest.federationBrandName === null && + 'No brand name set'} +
    + +

    Domains

    + {graphrequest.isFetching && } + {graphrequest.data?.Domains && + graphrequest.data?.Domains.map((domainname) =>
  • {domainname}
  • )} +
    +
    +
    +
    + )}
    ) } From 4fcbe6728ee36325913a589a6e2794469b096ae4 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Mon, 1 May 2023 16:59:29 +0200 Subject: [PATCH 103/124] fixed typo --- src/routes.js | 2 +- .../tenant/administration/{TentantLookup.js => TenantLookup.js} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename src/views/tenant/administration/{TentantLookup.js => TenantLookup.js} (100%) diff --git a/src/routes.js b/src/routes.js index 509686c24715..b0a689c0a112 100644 --- a/src/routes.js +++ b/src/routes.js @@ -17,7 +17,7 @@ const AddGroupTemplates = React.lazy(() => const DeployGroupTemplates = React.lazy(() => import('src/views/identity/administration/DeployGroupTemplate'), ) -const TenantLookup = React.lazy(() => import('src/views/tenant/administration/TentantLookup')) +const TenantLookup = React.lazy(() => import('src/views/tenant/administration/TenantLookup')) const GroupTemplates = React.lazy(() => import('src/views/identity/administration/GroupTemplates')) const EditGroup = React.lazy(() => import('src/views/identity/administration/EditGroup')) diff --git a/src/views/tenant/administration/TentantLookup.js b/src/views/tenant/administration/TenantLookup.js similarity index 100% rename from src/views/tenant/administration/TentantLookup.js rename to src/views/tenant/administration/TenantLookup.js From 7b03d2b2fe8a62bb71609955e0cbed3acffb17cf Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Mon, 1 May 2023 17:21:02 +0200 Subject: [PATCH 104/124] added delete relationship --- .../administration/ListGDAPRelationships.js | 43 ++++++++++++++++++- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/src/views/tenant/administration/ListGDAPRelationships.js b/src/views/tenant/administration/ListGDAPRelationships.js index 564de823ede8..1db32b336c1a 100644 --- a/src/views/tenant/administration/ListGDAPRelationships.js +++ b/src/views/tenant/administration/ListGDAPRelationships.js @@ -1,8 +1,42 @@ -import React from 'react' +import { CButton } from '@coreui/react' +import { faEllipsisV, faTrashAlt } from '@fortawesome/free-solid-svg-icons' +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' +import React, { useState } from 'react' import { useSelector } from 'react-redux' -import { CSpinner, CCallout } from '@coreui/react' import { CippPageList } from 'src/components/layout' import { cellDateFormatter, cellNullTextFormatter } from 'src/components/tables' +import { CippActionsOffcanvas } from 'src/components/utilities' + +const Actions = (row, rowIndex, formatExtraData) => { + const [ocVisible, setOCVisible] = useState(false) + + const tenant = useSelector((state) => state.app.currentTenant) + return ( + <> + setOCVisible(true)}> + + + , + modalUrl: `/api/ExecDeleteGDAPRelationship?&GDAPID=${row.id}`, + modalMessage: 'Are you sure you want to delete this relationship?', + }, + ]} + placement="end" + visible={ocVisible} + id={row.id} + hideFunction={() => setOCVisible(false)} + /> + + ) +} const GDAPRelationships = () => { const columns = [ @@ -46,6 +80,11 @@ const GDAPRelationships = () => { exportSelector: 'endDateTime', cell: cellDateFormatter({ format: 'short' }), }, + { + name: 'Actions', + cell: Actions, + maxWidth: '80px', + }, ] return (
    From 2b0330719722714914801d26a0201c8b72f857a1 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Mon, 1 May 2023 20:29:18 +0200 Subject: [PATCH 105/124] added filters, fixed link --- .../administration/ListGDAPRelationships.js | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/views/tenant/administration/ListGDAPRelationships.js b/src/views/tenant/administration/ListGDAPRelationships.js index 1db32b336c1a..f44b5da4d144 100644 --- a/src/views/tenant/administration/ListGDAPRelationships.js +++ b/src/views/tenant/administration/ListGDAPRelationships.js @@ -25,7 +25,7 @@ const Actions = (row, rowIndex, formatExtraData) => { color: 'danger', modal: true, icon: , - modalUrl: `/api/ExecDeleteGDAPRelationship?&GDAPID=${row.id}`, + modalUrl: `/api/ExecDeleteGDAPRelationship?GDAPID=${row.id}`, modalMessage: 'Are you sure you want to delete this relationship?', }, ]} @@ -93,6 +93,22 @@ const GDAPRelationships = () => { title="GDAP Relationship List" tenantSelector={false} datatable={{ + filterlist: [ + { filterName: 'Active Relationships', filter: '"status":"active"' }, + { filterName: 'Terminated Relationships', filter: '"status":"Terminated"' }, + { filterName: 'Pending Relationships', filter: 'Pending' }, + ], + tableProps: { + selectableRows: true, + actionsList: [ + { + label: 'Terminate Relationship', + modal: true, + modalUrl: `/api/ExecDeleteGDAPRelationship?&GDAPID=!id`, + modalMessage: 'Are you sure you want to terminate these relationships?', + }, + ], + }, keyField: 'id', columns, reportName: `GDAP-Relationships`, From abf8d045a38298bf549652abee5783600e6b481b Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Tue, 2 May 2023 11:14:54 +0200 Subject: [PATCH 106/124] added standards display names --- src/views/home/Home.js | 57 +++++++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 23 deletions(-) diff --git a/src/views/home/Home.js b/src/views/home/Home.js index f968d8a90992..75db730c58f7 100644 --- a/src/views/home/Home.js +++ b/src/views/home/Home.js @@ -11,17 +11,14 @@ import { faUsers, } from '@fortawesome/free-solid-svg-icons' import { CCol, CRow } from '@coreui/react' -import { - useGenericGetRequestQuery, - useLoadDashQuery, - useLoadVersionsQuery, -} from 'src/store/api/app' +import { useGenericGetRequestQuery } from 'src/store/api/app' import { CippContentCard } from 'src/components/layout' import Skeleton from 'react-loading-skeleton' import { UniversalSearch } from 'src/components/utilities/UniversalSearch' -import { ActionContentCard, ListGroupContentCard } from 'src/components/contentcards' +import { ActionContentCard } from 'src/components/contentcards' import { useSelector } from 'react-redux' import TimeAgo from 'javascript-time-ago' +import allStandardsList from 'src/data/standards' import en from 'javascript-time-ago/locale/en.json' TimeAgo.addDefaultLocale(en) @@ -47,6 +44,15 @@ const Home = () => { params: { tenantFilter: currentTenant.defaultDomainName }, }) + const { + data: standards, + isLoading: isLoadingStandards, + isSuccess: issuccessStandards, + } = useGenericGetRequestQuery({ + path: '/api/ListStandards', + params: {}, + }) + const actions1 = [ { label: 'M365 Admin', @@ -165,12 +171,6 @@ const Home = () => { {isLoadingOrg && } {organization && organization?.createdDateTime} - -

    Current Secure Score

    - {isLoadingOrg && } -
    - -

    AD Connect Status

    {isLoadingOrg && } @@ -197,6 +197,8 @@ const Home = () => { 'Disabled' )}
    +
    +

    Domain(s)

    {isLoadingOrg && } @@ -223,19 +225,28 @@ const Home = () => { ))}
    -
    -

    Applied Standards

    - {isLoadingOrg && } -
    - -

    Last Results

    - {isLoadingOrg && } -
    - -

    Access Type

    - {isLoadingOrg && } + {isLoadingStandards && } + {issuccessStandards && + standards + .filter( + (p) => + p.displayName == 'AllTenants' || + p.displayName == currentTenant.defaultDomainName, + ) + .flatMap((tenant) => { + return Object.keys(tenant.standards).map((standard) => { + const standardDisplayname = allStandardsList.filter((p) => + p.name.includes(standard), + ) + return ( +
  • + {standardDisplayname[0].label} ({tenant.displayName}) +
  • + ) + }) + })}
    From 81aeb777089c8e2016f8310ff9789e8837e41f88 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Tue, 2 May 2023 11:30:36 +0200 Subject: [PATCH 107/124] improved home screen --- src/views/home/Home.js | 40 +++++++++++-------- src/views/tenant/administration/EditTenant.js | 2 +- 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/src/views/home/Home.js b/src/views/home/Home.js index 75db730c58f7..4716ee2eea53 100644 --- a/src/views/home/Home.js +++ b/src/views/home/Home.js @@ -6,8 +6,14 @@ import { faEnvelope, faHotel, faLaptopCode, + faMailBulk, faSearch, + faShieldAlt, faSync, + faUser, + faUserAlt, + faUserFriends, + faUserPlus, faUsers, } from '@fortawesome/free-solid-svg-icons' import { CCol, CRow } from '@coreui/react' @@ -56,28 +62,28 @@ const Home = () => { const actions1 = [ { label: 'M365 Admin', - link: '#', + link: `https://portal.office.com/Partner/BeginClientSession.aspx?CTID=${currentTenant.customerId}&CSDEST=o365admincenter`, icon: faCog, }, { label: 'Exchange', - link: '#', - icon: faSync, + link: `https://admin.exchange.microsoft.com/?landingpage=homepage&form=mac_sidebar&delegatedOrg=${currentTenant.defaultDomainName}#`, + icon: faMailBulk, }, { label: 'Intune', - link: '#', - icon: faEnvelope, + link: `https://intune.microsoft.com/${currentTenant.defaultDomainName}`, + icon: faLaptopCode, }, { label: 'Entra', - link: '#', - icon: faEnvelope, + link: `https://entra.microsoft.com/${currentTenant.defaultDomainName}`, + icon: faUsers, }, { label: 'Security', - link: '#', - icon: faEnvelope, + link: `https://security.microsoft.com/?tid=${currentTenant.customerId}`, + icon: faShieldAlt, }, ] @@ -89,23 +95,23 @@ const Home = () => { }, { label: 'List Users', - link: '#', - icon: faSync, + link: `/identity/administration/users?customerId=${currentTenant.customerId}`, + icon: faUser, }, { label: 'List Groups', - link: '#', - icon: faSync, + link: `/identity/administration/groups?customerId=${currentTenant.customerId}`, + icon: faUsers, }, { label: 'Create User', - link: '#', - icon: faSync, + link: `/identity/administration/users/add?customerId=${currentTenant.customerId}`, + icon: faUserPlus, }, { label: 'Create Group', - link: '#', - icon: faEnvelope, + link: `/identity/administration/groups/add?customerId=${currentTenant.customerId}`, + icon: faUserFriends, }, ] return ( diff --git a/src/views/tenant/administration/EditTenant.js b/src/views/tenant/administration/EditTenant.js index 93d32285f76f..868ed0e77ba2 100644 --- a/src/views/tenant/administration/EditTenant.js +++ b/src/views/tenant/administration/EditTenant.js @@ -40,7 +40,7 @@ const EditTenant = () => { useEffect(() => { if (!tenantDomain || !customerId) { ModalService.open({ - body: 'Error: INvalid request. Could not load requested tenant.', + body: 'Error: Invalid request. Could not load requested tenant.', title: 'Invalid Request', }) setQueryError(true) From 179dcb7f83bd9e539465e998493bfdf17bb97b63 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Wed, 3 May 2023 10:31:36 +0200 Subject: [PATCH 108/124] prettier homepage --- src/views/home/Home.js | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/src/views/home/Home.js b/src/views/home/Home.js index 4716ee2eea53..da8c6afcceab 100644 --- a/src/views/home/Home.js +++ b/src/views/home/Home.js @@ -36,6 +36,7 @@ const Home = () => { data: organization, isLoading: isLoadingOrg, isSuccess: issuccessOrg, + isFetching: isFetchingOrg, } = useGenericGetRequestQuery({ path: '/api/ListOrg', params: { tenantFilter: currentTenant.defaultDomainName }, @@ -45,6 +46,7 @@ const Home = () => { data: dashboard, isLoading: isLoadingUserCounts, isSuccess: issuccessUserCounts, + isFetching: isFetchingUserCount, } = useGenericGetRequestQuery({ path: '/api/ListuserCounts', params: { tenantFilter: currentTenant.defaultDomainName }, @@ -54,6 +56,7 @@ const Home = () => { data: standards, isLoading: isLoadingStandards, isSuccess: issuccessStandards, + isFetching: isFetchingStandards, } = useGenericGetRequestQuery({ path: '/api/ListStandards', params: {}, @@ -131,22 +134,28 @@ const Home = () => { -
    {!isLoadingUserCounts ? dashboard?.Users : }
    +
    + {issuccessUserCounts && !isFetchingUserCount ? dashboard?.Users : } +
    -
    {!isLoadingUserCounts ? dashboard?.LicUsers : }
    {' '} +
    + {issuccessUserCounts && !isFetchingUserCount ? dashboard?.LicUsers : } +
    -
    {!isLoadingUserCounts ? dashboard?.Gas : }
    {' '} +
    {issuccessUserCounts && !isFetchingUserCount ? dashboard?.Gas : }
    -
    {!isLoadingUserCounts ? dashboard?.Guests : }
    {' '} +
    + {issuccessUserCounts && !isFetchingUserCount ? dashboard?.Guests : } +
    @@ -174,12 +183,12 @@ const Home = () => {

    Creation Date

    - {isLoadingOrg && } + {(isLoadingOrg || isFetchingOrg) && } {organization && organization?.createdDateTime}

    AD Connect Status

    - {isLoadingOrg && } + {(isLoadingOrg || isFetchingOrg) && } {!isLoadingOrg && organization?.onPremisesSyncEnabled ? ( <>
  • @@ -207,14 +216,14 @@ const Home = () => {

    Domain(s)

    - {isLoadingOrg && } + {(isLoadingOrg || isFetchingOrg) && } {organization?.verifiedDomains.map((item) => (
  • {item.name}
  • ))}

    Capabilities

    - {isLoadingOrg && } + {(isLoadingOrg || isFetchingOrg) && } {organization?.assignedPlans .filter((p) => p.capabilityStatus == 'Enabled') .reduce((plan, curr) => { @@ -233,8 +242,9 @@ const Home = () => {

    Applied Standards

    - {isLoadingStandards && } + {(isLoadingStandards || isFetchingStandards) && } {issuccessStandards && + !isFetchingStandards && standards .filter( (p) => From aae53f035d37b6e777208efa62ab245383cada70 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Wed, 3 May 2023 10:36:55 +0200 Subject: [PATCH 109/124] prettification --- src/views/home/Home.js | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/src/views/home/Home.js b/src/views/home/Home.js index da8c6afcceab..c2bbc28aaa0a 100644 --- a/src/views/home/Home.js +++ b/src/views/home/Home.js @@ -184,12 +184,12 @@ const Home = () => {

    Creation Date

    {(isLoadingOrg || isFetchingOrg) && } - {organization && organization?.createdDateTime} + {organization && !isFetchingOrg && organization?.createdDateTime}

    AD Connect Status

    {(isLoadingOrg || isFetchingOrg) && } - {!isLoadingOrg && organization?.onPremisesSyncEnabled ? ( + {!isLoadingOrg && !isFetchingOrg && organization?.onPremisesSyncEnabled ? ( <>
  • Directory Sync: @@ -217,28 +217,28 @@ const Home = () => {

    Domain(s)

    {(isLoadingOrg || isFetchingOrg) && } - {organization?.verifiedDomains.map((item) => ( -
  • {item.name}
  • - ))} + {!isFetchingOrg && + organization?.verifiedDomains.map((item) =>
  • {item.name}
  • )}

    Capabilities

    {(isLoadingOrg || isFetchingOrg) && } - {organization?.assignedPlans - .filter((p) => p.capabilityStatus == 'Enabled') - .reduce((plan, curr) => { - if (!plan.includes(curr.service)) { - plan.push(curr.service) - } - return plan - }, []) - .map((plan) => ( - <> - {plan == 'exchange' &&
  • Exchange
  • } - {plan == 'AADPremiumService' &&
  • AAD Premium
  • } - {plan == 'WindowsDefenderATP' &&
  • Windows Defender
  • } - - ))} + {!isFetchingOrg && + organization?.assignedPlans + .filter((p) => p.capabilityStatus == 'Enabled') + .reduce((plan, curr) => { + if (!plan.includes(curr.service)) { + plan.push(curr.service) + } + return plan + }, []) + .map((plan) => ( + <> + {plan == 'exchange' &&
  • Exchange
  • } + {plan == 'AADPremiumService' &&
  • AAD Premium
  • } + {plan == 'WindowsDefenderATP' &&
  • Windows Defender
  • } + + ))}

    Applied Standards

    From 2cee5436714fc754e4696038347ff922f43789d2 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Wed, 3 May 2023 11:21:35 +0200 Subject: [PATCH 110/124] small design change --- src/views/cipp/CIPPSettings.js | 42 +++++++++++++++++----------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/views/cipp/CIPPSettings.js b/src/views/cipp/CIPPSettings.js index 1ecb75605980..c29575f64b76 100644 --- a/src/views/cipp/CIPPSettings.js +++ b/src/views/cipp/CIPPSettings.js @@ -814,11 +814,11 @@ const SecuritySettings = () => { <> - + Resource Group - + The Resource group contains all the CIPP resources in your tenant, except the SAM Application @@ -834,11 +834,11 @@ const SecuritySettings = () => { - + Key Vault - + The keyvault allows you to check token information. By default you do not have access. @@ -854,11 +854,11 @@ const SecuritySettings = () => { - + Static Web App (Role Management) - + The Static Web App role management allows you to invite other users to the application. @@ -876,11 +876,11 @@ const SecuritySettings = () => { - + Function App (Deployment Center) - + The Function App Deployment Center allows you to run updates on the API @@ -895,31 +895,31 @@ const SecuritySettings = () => { - + Function App (Configuration) - + At the Function App Configuration you can check the status of the API access to your keyvault + + Go to Function App Configuration + - - Go to Function App Configuration - - + Function App (Overview) - + At the function App Overview, you can stop and start the backend API @@ -1340,14 +1340,14 @@ const Maintenance = () => { {listScriptResult.isFetching && ( - + )} {!listScriptResult.isFetching && listScriptResult.isSuccess && ( - + Script Details From 0ead3929bb929a325e6aeb8fbd1a97997baaadad Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Wed, 3 May 2023 13:45:55 +0200 Subject: [PATCH 111/124] added outbound spamcontact --- src/data/standards.json | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/data/standards.json b/src/data/standards.json index cfefef351539..12d8991da6d4 100644 --- a/src/data/standards.json +++ b/src/data/standards.json @@ -226,6 +226,17 @@ "addedComponent": null, "label": "Enable FIDO2 capabilities" }, + { + "name": "standards.OutBoundSpamAlert.Enabled", + "cat": "Exchange", + "helpText": "This is the default helptext", + "addedComponent": { + "type": "input", + "name": "standards.OutBoundSpamAlert.OutboundSpamContact", + "label": "Outbound spam contact" + }, + "label": "Set Outbound Spam Alert e-mail" + }, { "name": "standards.DisableSharedMailbox", "cat": "Exchange", From 400f79f62ee398e2299253becb8ec72942167a71 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Wed, 3 May 2023 14:21:49 +0200 Subject: [PATCH 112/124] displayname --- src/views/identity/administration/Users.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/views/identity/administration/Users.js b/src/views/identity/administration/Users.js index d2e845b0641c..2b29432bc80b 100644 --- a/src/views/identity/administration/Users.js +++ b/src/views/identity/administration/Users.js @@ -349,7 +349,7 @@ const Users = (row) => { label: 'Reset Password (Must Change)', color: 'info', modal: true, - modalUrl: `/api/ExecResetPass?MustChange=true&TenantFilter=${tenant.defaultDomainName}&ID=!userPrincipalName`, + modalUrl: `/api/ExecResetPass?MustChange=true&TenantFilter=${tenant.defaultDomainName}&ID=!userPrincipalName&displayName=${tenant.displayName}`, modalMessage: 'Are you sure you want to reset the password for these users? The users must change their password at next logon.', }, @@ -357,7 +357,7 @@ const Users = (row) => { label: 'Reset Password', color: 'info', modal: true, - modalUrl: `/api/ExecResetPass?MustChange=false&TenantFilter=${tenant.defaultDomainName}&ID=!userPrincipalName`, + modalUrl: `/api/ExecResetPass?MustChange=false&TenantFilter=${tenant.defaultDomainName}&ID=!userPrincipalName&displayName=${tenant.displayName}`, modalMessage: 'Are you sure you want to reset the password for these users? The users must change their password at next logon.', }, From 6b9d3af0e7f4da8b9863281d33dd7af6799dfcd0 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Wed, 3 May 2023 14:36:40 +0200 Subject: [PATCH 113/124] fixed mistake --- src/views/identity/administration/Users.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/views/identity/administration/Users.js b/src/views/identity/administration/Users.js index 2b29432bc80b..9409f8230b35 100644 --- a/src/views/identity/administration/Users.js +++ b/src/views/identity/administration/Users.js @@ -349,7 +349,7 @@ const Users = (row) => { label: 'Reset Password (Must Change)', color: 'info', modal: true, - modalUrl: `/api/ExecResetPass?MustChange=true&TenantFilter=${tenant.defaultDomainName}&ID=!userPrincipalName&displayName=${tenant.displayName}`, + modalUrl: `/api/ExecResetPass?MustChange=true&TenantFilter=${tenant.defaultDomainName}&ID=!userPrincipalName&displayName=!displayName`, modalMessage: 'Are you sure you want to reset the password for these users? The users must change their password at next logon.', }, @@ -357,7 +357,7 @@ const Users = (row) => { label: 'Reset Password', color: 'info', modal: true, - modalUrl: `/api/ExecResetPass?MustChange=false&TenantFilter=${tenant.defaultDomainName}&ID=!userPrincipalName&displayName=${tenant.displayName}`, + modalUrl: `/api/ExecResetPass?MustChange=false&TenantFilter=${tenant.defaultDomainName}&ID=!userPrincipalName&displayName=!displayName`, modalMessage: 'Are you sure you want to reset the password for these users? The users must change their password at next logon.', }, From fe02112e952bc34c8b6ef1d7c39749a7d0ae7478 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Wed, 3 May 2023 19:20:53 +0200 Subject: [PATCH 114/124] ApplyStandard changes for duplicate items. --- src/views/tenant/standards/ApplyStandard.js | 28 ++++++++++++++++----- 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/src/views/tenant/standards/ApplyStandard.js b/src/views/tenant/standards/ApplyStandard.js index b62a8aea06d4..86a3f08786e4 100644 --- a/src/views/tenant/standards/ApplyStandard.js +++ b/src/views/tenant/standards/ApplyStandard.js @@ -28,7 +28,12 @@ const Error = ({ name }) => ( Error.propTypes = { name: PropTypes.string.isRequired, } - +function getDeepKeys(obj) { + return Object.keys(obj) + .filter((key) => obj[key] instanceof Object) + .map((key) => getDeepKeys(obj[key]).map((k) => `${key}.${k}`)) + .reduce((x, y) => x.concat(y), Object.keys(obj)) +} const ApplyStandard = () => { const [genericPostRequest, postResults] = useLazyGenericPostRequestQuery() @@ -296,11 +301,22 @@ const ApplyStandard = () => {
    Selected Standards
    - {Object.entries(props.values.standards).map(([key, value]) => - allStandardsList - .filter((obj) => obj.name.includes(key)) - .map((item, idx) =>
  • {item.label}
  • ), - )} + {getDeepKeys(props.values.standards) + .reduce((acc, key) => { + const existingItem = allStandardsList.find((obj) => + obj.name.includes(key), + ) + if ( + existingItem && + !acc.find((item) => item.name === existingItem.name) + ) { + acc.push(existingItem) + } + return acc + }, []) + .map((item, idx) => ( +
  • {item.label}
  • + ))}

    From c639a879e31d79032e66f90ef8f692228a508373 Mon Sep 17 00:00:00 2001 From: BNWEIN Date: Wed, 3 May 2023 20:33:20 +0100 Subject: [PATCH 115/124] Minor fixes Minor Fixes --- src/views/email-exchange/administration/MailboxesList.js | 2 +- src/views/email-exchange/administration/ViewMobileDevices.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/views/email-exchange/administration/MailboxesList.js b/src/views/email-exchange/administration/MailboxesList.js index 9126ba955d04..cc4015b9708e 100644 --- a/src/views/email-exchange/administration/MailboxesList.js +++ b/src/views/email-exchange/administration/MailboxesList.js @@ -52,7 +52,7 @@ const MailboxList = () => { value: row.UPN, }, { - label: 'Aditional Email Addresses', + label: 'Additional Email Addresses', value: row.AdditionalEmailAddresses ? `${row.AdditionalEmailAddresses}` : 'No additional email addresses', diff --git a/src/views/email-exchange/administration/ViewMobileDevices.js b/src/views/email-exchange/administration/ViewMobileDevices.js index c0a66d0e66be..78c835647e61 100644 --- a/src/views/email-exchange/administration/ViewMobileDevices.js +++ b/src/views/email-exchange/administration/ViewMobileDevices.js @@ -136,8 +136,8 @@ const MobileDeviceList = () => { selector: (row) => row['deviceID'], name: 'Device ID', sortable: true, + cell: (row) => CellTip(row['deviceID']), exportSelector: 'deviceID', - cell: cellDateFormatter(), }, { selector: (row) => row['firstSync'], From 193b1dd38172c8325eff189813d15cf0c0484c6a Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Thu, 4 May 2023 10:27:46 +0200 Subject: [PATCH 116/124] duplicate entry --- src/data/standards.json | 30 +----------------------------- 1 file changed, 1 insertion(+), 29 deletions(-) diff --git a/src/data/standards.json b/src/data/standards.json index 12d8991da6d4..1924f234bf7a 100644 --- a/src/data/standards.json +++ b/src/data/standards.json @@ -307,35 +307,7 @@ "addedComponent": null, "label": "Enable 1 hour Activity based Timeout" }, - { - "name": "standards.sharingCapability.Enabled", - "cat": "SharePoint", - "helpText": "This is the default helptext", - "addedComponent": { - "type": "Select", - "label": "Select Sharing Level", - "name": "standards.sharingCapability.Level", - "values": [ - { - "label": "Users can share only with people in the organization. No external sharing is allowed.", - "value": "disabled" - }, - { - "label": "Users can share with new and existing guests. Guests must sign in or provide a verification code.", - "value": "externalUserSharingOnly" - }, - { - "label": "Users can share with anyone by using links that do not require sign-in.", - "value": "externalUserAndGuestSharing" - }, - { - "label": "Users can share with existing guests (those already in the directory of the organization).", - "value": "existingExternalUserSharingOnly" - } - ] - }, - "label": "Set Sharing Level for OneDrive and Sharepoint" - }, + { "name": "standards.calDefault.Enabled", "cat": "Exchange", From 2fc6689ccd23fbb0ceecb25019c0a18852971652 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Thu, 4 May 2023 10:36:51 +0200 Subject: [PATCH 117/124] added guest standard --- src/data/standards.json | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/data/standards.json b/src/data/standards.json index 1924f234bf7a..9f08f6215c18 100644 --- a/src/data/standards.json +++ b/src/data/standards.json @@ -57,6 +57,13 @@ "addedComponent": null, "label": "Enable Usernames instead of pseudo anonymised names in reports" }, + { + "name": "standards.DisbaleGuestDirectory", + "cat": "Global", + "helpText": "This is the default helptext", + "addedComponent": null, + "label": "Restrict guest user access to directory objects" + }, { "name": "standards.ModernAuth", "cat": "Global", From 7c618eca42a7bbedddf830bdf167b523aca13849 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Thu, 4 May 2023 10:40:14 +0200 Subject: [PATCH 118/124] typo --- 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 9f08f6215c18..50e671286608 100644 --- a/src/data/standards.json +++ b/src/data/standards.json @@ -58,7 +58,7 @@ "label": "Enable Usernames instead of pseudo anonymised names in reports" }, { - "name": "standards.DisbaleGuestDirectory", + "name": "standards.DisableGuestDirectory", "cat": "Global", "helpText": "This is the default helptext", "addedComponent": null, From d7c6b9f09c7cc9b14da1b6a3d7bc89bfcdb3e827 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Fri, 5 May 2023 13:47:48 +0200 Subject: [PATCH 119/124] upped version --- 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 fbcbf7380658..e5b820341fb1 100644 --- a/public/version_latest.txt +++ b/public/version_latest.txt @@ -1 +1 @@ -3.4.0 \ No newline at end of file +3.5.0 \ No newline at end of file diff --git a/version_latest.txt b/version_latest.txt index fbcbf7380658..e5b820341fb1 100644 --- a/version_latest.txt +++ b/version_latest.txt @@ -1 +1 @@ -3.4.0 \ No newline at end of file +3.5.0 \ No newline at end of file From 2fa5820eea0446d6394d8cb1cbcd3637b201c0e7 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Fri, 5 May 2023 14:52:14 +0200 Subject: [PATCH 120/124] fix minor dash issue --- src/views/home/Home.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/views/home/Home.js b/src/views/home/Home.js index c2bbc28aaa0a..a6969fd9ea5b 100644 --- a/src/views/home/Home.js +++ b/src/views/home/Home.js @@ -218,14 +218,16 @@ const Home = () => {

    Domain(s)

    {(isLoadingOrg || isFetchingOrg) && } {!isFetchingOrg && - organization?.verifiedDomains.map((item) =>
  • {item.name}
  • )} + issuccessOrg && + organization?.verifiedDomains?.map((item) =>
  • {item.name}
  • )}

    Capabilities

    {(isLoadingOrg || isFetchingOrg) && } {!isFetchingOrg && + issuccessOrg && organization?.assignedPlans - .filter((p) => p.capabilityStatus == 'Enabled') + ?.filter((p) => p.capabilityStatus == 'Enabled') .reduce((plan, curr) => { if (!plan.includes(curr.service)) { plan.push(curr.service) From fa932e3eea5f77f0a688c73b73e99b9a9894dff7 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Fri, 5 May 2023 22:32:41 +0200 Subject: [PATCH 121/124] minor fix --- src/views/home/Home.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/views/home/Home.js b/src/views/home/Home.js index a6969fd9ea5b..15073bafeb8d 100644 --- a/src/views/home/Home.js +++ b/src/views/home/Home.js @@ -260,7 +260,7 @@ const Home = () => { ) return (
  • - {standardDisplayname[0].label} ({tenant.displayName}) + {standardDisplayname[0]?.label} ({tenant.displayName})
  • ) }) From 8ebbc5f9dd9c4f7198c06d24920cdb00312e2e7d Mon Sep 17 00:00:00 2001 From: Roel van der Wegen Date: Sat, 6 May 2023 13:51:00 +0200 Subject: [PATCH 122/124] Added Azure & Sharepoint portals to dashboard --- src/views/home/Home.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/views/home/Home.js b/src/views/home/Home.js index 15073bafeb8d..df7e05d94be5 100644 --- a/src/views/home/Home.js +++ b/src/views/home/Home.js @@ -15,6 +15,7 @@ import { faUserFriends, faUserPlus, faUsers, + faServer, } from '@fortawesome/free-solid-svg-icons' import { CCol, CRow } from '@coreui/react' import { useGenericGetRequestQuery } from 'src/store/api/app' @@ -88,6 +89,16 @@ const Home = () => { link: `https://security.microsoft.com/?tid=${currentTenant.customerId}`, icon: faShieldAlt, }, + { + label: 'Azure', + link: `https://portal.azure.com/?tid=${currentTenant.defaultDomainName}`, + icon: faServer, + }, + { + label: 'Sharepoint', + link: `https://admin.microsoft.com/Partner/beginclientsession.aspx?CTID=${currentTenant.customerId}&CSDEST=SharePoint`, + icon: faBook, + }, ] const actions2 = [ From 02c85e8f27b51e8e4a38e913d1215a49d51c7848 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Tue, 9 May 2023 10:45:26 +0200 Subject: [PATCH 123/124] version --- 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 e5b820341fb1..3c8ff8c36b50 100644 --- a/public/version_latest.txt +++ b/public/version_latest.txt @@ -1 +1 @@ -3.5.0 \ No newline at end of file +3.5.1 \ No newline at end of file diff --git a/version_latest.txt b/version_latest.txt index e5b820341fb1..3c8ff8c36b50 100644 --- a/version_latest.txt +++ b/version_latest.txt @@ -1 +1 @@ -3.5.0 \ No newline at end of file +3.5.1 \ No newline at end of file From a007b94d4939eace271d58a51567cf5e68303dcc Mon Sep 17 00:00:00 2001 From: Roel van der Wegen Date: Wed, 10 May 2023 17:33:02 +0200 Subject: [PATCH 124/124] Replaced old docs link --- .github/workflows/Comment_on_Issues.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/Comment_on_Issues.yml b/.github/workflows/Comment_on_Issues.yml index 6bd12f6a005b..80574ef5d235 100644 --- a/.github/workflows/Comment_on_Issues.yml +++ b/.github/workflows/Comment_on_Issues.yml @@ -16,7 +16,7 @@ jobs: with: issue-number: ${{ github.event.issue.number }} body: | - Thank you for creating a bug. Please make sure your bug is indeed a unique case by checking current and past issues, and reading the complete documentation at https://kelvintegelaar.github.io/CIPP + Thank you for creating a bug. Please make sure your bug is indeed a unique case by checking current and past issues, and reading the complete documentation at https://docs.cipp.app/ If your bug is a known documentation issue, it will be closed without notice by a contributor. To confirm that this is not a bug found in the documentation, please copy and paste the following comment: "I confirm that I have checked the documentation thoroughly and believe this to be an actual bug.". Without confirming, your report will be closed in 24 hours. If you'd like this bug to be assigned to you, please comment "I would like to work on this please!".