@@ -513,79 +582,10 @@ export const RFFSelectSearch = ({
)}
- {!allowCreate && onChange && (
-
- )}
- {!allowCreate && !onChange && (
-
- )}
- {allowCreate && onChange && (
-
- )}
- {allowCreate && !onChange && (
-
+ {allowCreate ? (
+
+ ) : (
+
)}
{meta.error && meta.touched && (
diff --git a/src/components/forms/index.js b/src/components/forms/index.js
index 00a76ee4554a..aa36929d58da 100644
--- a/src/components/forms/index.js
+++ b/src/components/forms/index.js
@@ -10,6 +10,7 @@ import {
RFFCFormSelect,
RFFSelectSearch,
RFFCFormInputArray,
+ RFFCFormInputList,
} from 'src/components/forms/RFFComponents'
export {
@@ -24,4 +25,5 @@ export {
RFFCFormSelect,
RFFSelectSearch,
RFFCFormInputArray,
+ RFFCFormInputList,
}
diff --git a/src/components/utilities/CippFuzzySearch.jsx b/src/components/utilities/CippFuzzySearch.jsx
index e7efe8d0bc1a..ec176e77d340 100644
--- a/src/components/utilities/CippFuzzySearch.jsx
+++ b/src/components/utilities/CippFuzzySearch.jsx
@@ -4,7 +4,7 @@ import Fuse from 'fuse.js'
function CippfuzzySearch(options) {
const fuse = new Fuse(options, {
keys: ['name', 'groupName', 'items.name'],
- threshold: 0.5,
+ threshold: 0.3,
location: 0,
ignoreLocation: true,
useExtendedSearch: true,
@@ -15,8 +15,8 @@ function CippfuzzySearch(options) {
if (!value.length) {
return options
}
-
- return fuse.search(value).map((_ref) => {
+ const search = fuse.search(value)
+ return search.map((_ref) => {
let { item } = _ref
return item
})
diff --git a/src/components/utilities/TenantSelector.jsx b/src/components/utilities/TenantSelector.jsx
index df8eb7d00459..36a9bd8764e7 100644
--- a/src/components/utilities/TenantSelector.jsx
+++ b/src/components/utilities/TenantSelector.jsx
@@ -4,7 +4,7 @@ import { useDispatch, useSelector } from 'react-redux'
import PropTypes from 'prop-types'
import { useListTenantsQuery } from 'src/store/api/tenants'
import { setCurrentTenant } from 'src/store/features/app'
-import { CButton, CDropdown, CDropdownMenu, CDropdownToggle } from '@coreui/react'
+import { CButton } from '@coreui/react'
import { useNavigate, useSearchParams } from 'react-router-dom'
import { queryString } from 'src/helpers'
import { faBuilding } from '@fortawesome/free-solid-svg-icons'
diff --git a/src/data/Extensions.json b/src/data/Extensions.json
index 98a5c9a5a3f2..1ca3a87b94d7 100644
--- a/src/data/Extensions.json
+++ b/src/data/Extensions.json
@@ -160,5 +160,65 @@
}
],
"mappingRequired": true
+ },
+ {
+ "name": "PasswordPusher",
+ "type": "PWPush",
+ "cat": "Passwords",
+ "forceSyncButton": false,
+ "helpText": "This integration allows you to generate password links instead of plain text passwords. Visit https://pwpush.com/ or https://github.com/pglombardo/PasswordPusher for more information.",
+ "SettingOptions": [
+ {
+ "type": "checkbox",
+ "name": "PWPush.Enabled",
+ "label": "Replace generated passwords with PWPush links"
+ },
+ {
+ "type": "input",
+ "fieldtype": "text",
+ "name": "PWPush.BaseUrl",
+ "label": "PWPush URL",
+ "placeholder": "Enter your PWPush URL. (default: https://pwpush.com)"
+ },
+ {
+ "type": "input",
+ "fieldtype": "text",
+ "name": "PWPush.EmailAddress",
+ "label": "PWPush email address",
+ "placeholder": "Enter your email address for PWPush. (optional)"
+ },
+ {
+ "type": "input",
+ "fieldtype": "password",
+ "name": "PWPush.APIKey",
+ "label": "PWPush API Key",
+ "placeholder": "Enter your PWPush API Key. (optional)"
+ },
+ {
+ "type": "checkbox",
+ "name": "PWPush.RetrievalStep",
+ "label": "Click to retrieve password (recommended)"
+ },
+ {
+ "type": "input",
+ "fieldtype": "number",
+ "name": "PWPush.ExpireAfterDays",
+ "label": "Expiration in Days",
+ "placeholder": "Expiration time in days. (optional)"
+ },
+ {
+ "type": "input",
+ "fieldtype": "number",
+ "name": "PWPush.ExpireAfterViews",
+ "label": "Expiration after views",
+ "placeholder": "Expiration after views. (optional)"
+ },
+ {
+ "type": "checkbox",
+ "name": "PWPush.DeletableByViewer",
+ "label": "Allow deletion of passwords"
+ }
+ ],
+ "mappingRequired": false
}
]
diff --git a/src/data/standards.json b/src/data/standards.json
index d1b9e020ded7..28c9f0cdecab 100644
--- a/src/data/standards.json
+++ b/src/data/standards.json
@@ -121,6 +121,16 @@
"impact": "Low Impact",
"impactColour": "info"
},
+ {
+ "name": "standards.EnablePronouns",
+ "cat": "Global Standards",
+ "tag": ["lowimpact"],
+ "helpText": "Enables the Pronouns feature for the tenant. This allows users to set their pronouns in their profile.",
+ "addedComponent": [],
+ "label": "Enable Pronouns",
+ "impact": "Low Impact",
+ "impactColour": "info"
+ },
{
"name": "standards.AnonReportDisable",
"cat": "Global Standards",
@@ -1102,6 +1112,44 @@
"name": "standards.AntiPhishPolicy.EnableUnusualCharactersSafetyTips",
"default": true
},
+ {
+ "type": "Select",
+ "label": "If a message is detected as user impersonation",
+ "name": "standards.AntiPhishPolicy.TargetedUserProtectionAction",
+ "values": [
+ {
+ "label": "Move to Junk Folder",
+ "value": "MoveToJmf"
+ },
+ {
+ "label": "Delete the message before its delivered",
+ "value": "Delete"
+ },
+ {
+ "label": "Quarantine the message",
+ "value": "Quarantine"
+ }
+ ]
+ },
+ {
+ "type": "Select",
+ "label": "If a message is detected as domain impersonation",
+ "name": "standards.AntiPhishPolicy.TargetedDomainProtectionAction",
+ "values": [
+ {
+ "label": "Move to Junk Folder",
+ "value": "MoveToJmf"
+ },
+ {
+ "label": "Delete the message before its delivered",
+ "value": "Delete"
+ },
+ {
+ "label": "Quarantine the message",
+ "value": "Quarantine"
+ }
+ ]
+ },
{
"type": "Select",
"label": "If Mailbox Intelligence detects an impersonated user",
diff --git a/src/views/cipp/Extensions.jsx b/src/views/cipp/Extensions.jsx
index d42e79d9bb38..7bfe1d7feb86 100644
--- a/src/views/cipp/Extensions.jsx
+++ b/src/views/cipp/Extensions.jsx
@@ -10,7 +10,7 @@ import {
CTabContent,
CTabPane,
} from '@coreui/react'
-import { CippPage } from 'src/components/layout'
+import { CippCallout, CippPage } from 'src/components/layout'
import { CippLazy } from 'src/components/utilities'
import { useNavigate } from 'react-router-dom'
import useQuery from 'src/hooks/useQuery.jsx'
@@ -104,7 +104,7 @@ export default function CIPPExtensions() {
-
+
+ {extensionConfigResult?.data?.Results && (
+
+ {extensionConfigResult?.data?.Results}
+
+ )}
+ {listExtensionTestResult?.data?.Results && (
+
+ {listExtensionTestResult?.data?.Results}
+ {listExtensionTestResult?.data?.Link && (
+
+ Link
+
+ )}
+
+ )}
-
+
diff --git a/src/views/cipp/Scheduler.jsx b/src/views/cipp/Scheduler.jsx
index 7ffed5837fe0..e0fd1aea974a 100644
--- a/src/views/cipp/Scheduler.jsx
+++ b/src/views/cipp/Scheduler.jsx
@@ -5,6 +5,7 @@ import { Field, Form, FormSpy } from 'react-final-form'
import {
RFFCFormInput,
RFFCFormInputArray,
+ RFFCFormInputList,
RFFCFormSwitch,
RFFSelectSearch,
} from 'src/components/forms'
@@ -157,10 +158,14 @@ const Scheduler = () => {
if (typeof row?.Parameters[key] === 'object') {
var nestedParamList = []
Object.keys(row?.Parameters[key]).forEach((nestedKey) => {
- nestedParamList.push({
- Key: nestedKey,
- Value: row?.Parameters[key][nestedKey],
- })
+ if (nestedKey >= 0) {
+ nestedParamList.push(row?.Parameters[key][nestedKey])
+ } else {
+ nestedParamList.push({
+ Key: nestedKey,
+ Value: row?.Parameters[key][nestedKey],
+ })
+ }
})
parameters[key] = nestedParamList
} else {
@@ -179,6 +184,10 @@ const Scheduler = () => {
})
})
+ if (!recurrence) {
+ recurrence = { name: 'Only once', value: '0' }
+ }
+
// Set initial values
var formValues = {
taskName: row.Name,
@@ -413,12 +422,22 @@ const Scheduler = () => {
key={idx}
/>
) : (
-
+ <>
+ {param.Type === 'System.String[]' ? (
+
+ ) : (
+
+ )}
+ >
)}
>
)}
diff --git a/src/views/cipp/app-settings/CIPPSettings.jsx b/src/views/cipp/app-settings/CIPPSettings.jsx
index 14e5c3e0cb9e..5a610170e49b 100644
--- a/src/views/cipp/app-settings/CIPPSettings.jsx
+++ b/src/views/cipp/app-settings/CIPPSettings.jsx
@@ -8,9 +8,7 @@ import { SettingsTenants } from 'src/views/cipp/app-settings/SettingsTenants.jsx
import { SettingsBackend } from 'src/views/cipp/app-settings/SettingsBackend.jsx'
import { SettingsNotifications } from 'src/views/cipp/app-settings/SettingsNotifications.jsx'
import { SettingsLicenses } from 'src/views/cipp/app-settings/SettingsLicenses.jsx'
-import { SettingsExtensions } from 'src/views/cipp/app-settings/SettingsExtensions.jsx'
import { SettingsMaintenance } from 'src/views/cipp/app-settings/SettingsMaintenance.jsx'
-import { SettingsExtensionMappings } from 'src/views/cipp/app-settings/SettingsExtensionMappings.jsx'
import { SettingsPartner } from 'src/views/cipp/app-settings/SettingsPartner.jsx'
import useQuery from 'src/hooks/useQuery.jsx'
import { SettingsSuperAdmin } from './SettingsSuperAdmin.jsx'
diff --git a/src/views/cipp/app-settings/components/SettingsCustomRoles.jsx b/src/views/cipp/app-settings/components/SettingsCustomRoles.jsx
index 75c0a7504487..5799c900323f 100644
--- a/src/views/cipp/app-settings/components/SettingsCustomRoles.jsx
+++ b/src/views/cipp/app-settings/components/SettingsCustomRoles.jsx
@@ -13,20 +13,20 @@ import {
import { Field, Form, FormSpy } from 'react-final-form'
import { RFFCFormRadioList, RFFSelectSearch } from 'src/components/forms'
import { useGenericGetRequestQuery, useLazyGenericPostRequestQuery } from 'src/store/api/app'
-import { CippPage } from 'src/components/layout'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
-import Skeleton from 'react-loading-skeleton'
import { TenantSelectorMultiple, ModalService, CippOffcanvas } from 'src/components/utilities'
import PropTypes from 'prop-types'
import { OnChange } from 'react-final-form-listeners'
import { useListTenantsQuery } from 'src/store/api/tenants'
-import CippListOffcanvas, { OffcanvasListSection } from 'src/components/utilities/CippListOffcanvas'
+import { OffcanvasListSection } from 'src/components/utilities/CippListOffcanvas'
import CippButtonCard from 'src/components/contentcards/CippButtonCard'
const SettingsCustomRoles = () => {
const [genericPostRequest, postResults] = useLazyGenericPostRequestQuery()
const [selectedTenant, setSelectedTenant] = useState([])
+ const [blockedTenants, setBlockedTenants] = useState([])
const tenantSelectorRef = useRef()
+ const blockedTenantSelectorRef = useRef()
const { data: tenants = [], tenantsFetching } = useListTenantsQuery({
showAllTenantSelector: true,
})
@@ -57,13 +57,21 @@ const SettingsCustomRoles = () => {
alltenant = true
}
})
- if (alltenant) {
+ if (alltenant && blockedTenants.length === 0) {
setAllTenantSelected(true)
} else {
setAllTenantSelected(false)
}
setSelectedTenant(e)
}
+
+ const handleBlockedTenantChange = (e) => {
+ setBlockedTenants(e)
+ if (e.length > 0) {
+ setAllTenantSelected(false)
+ }
+ }
+
const handleSubmit = async (values) => {
//filter on only objects that are 'true'
genericPostRequest({
@@ -72,6 +80,7 @@ const SettingsCustomRoles = () => {
RoleName: values.RoleName.value,
Permissions: values.Permissions,
AllowedTenants: selectedTenant.map((tenant) => tenant.value),
+ BlockedTenants: blockedTenants.map((tenant) => tenant.value),
},
}).then(() => {
refetchCustomRoleList()
@@ -119,17 +128,30 @@ const SettingsCustomRoles = () => {
} else {
if (set === 'AllowedTenants') {
setSelectedTenant(customRole[0][set])
- var selectedTenants = []
+ var selectedTenantList = []
+ tenants.map((tenant) => {
+ if (customRole[0][set].includes(tenant.customerId)) {
+ selectedTenantList.push({
+ label: tenant.displayName,
+ value: tenant.customerId,
+ })
+ }
+ })
+
+ tenantSelectorRef.current.setValue(selectedTenantList)
+ } else if (set === 'BlockedTenants') {
+ setBlockedTenants(customRole[0][set])
+ var blockedTenantList = []
tenants.map((tenant) => {
if (customRole[0][set].includes(tenant.customerId)) {
- selectedTenants.push({
+ blockedTenantList.push({
label: tenant.displayName,
value: tenant.customerId,
})
}
})
- tenantSelectorRef.current.setValue(selectedTenants)
+ blockedTenantSelectorRef.current.setValue(blockedTenantList)
} else {
onChange(customRole[0][set])
}
@@ -277,6 +299,7 @@ const SettingsCustomRoles = () => {
/>
+
{cippApiRoleSelected && (
This role will limit access for the CIPP-API integration. It is not
@@ -299,6 +322,17 @@ const SettingsCustomRoles = () => {
)}
+