Skip to content

Commit

Permalink
Merge pull request KelvinTegelaar#2490 from JohnDuprey/dev
Browse files Browse the repository at this point in the history
Custom Role Support and Bugfixes
  • Loading branch information
JohnDuprey committed May 29, 2024
2 parents 1da3471 + 17dcf39 commit ed01c11
Show file tree
Hide file tree
Showing 8 changed files with 814 additions and 67 deletions.
2 changes: 0 additions & 2 deletions src/components/forms/RFFComponents.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,6 @@ export const RFFCFormRadioList = ({
name,
options,
className = 'mb-3',
disabled = false,
onClick,
inline = false,
}) => {
Expand All @@ -312,7 +311,6 @@ export const RFFCFormRadioList = ({
onChange={input.onChange}
type="radio"
{...option}
disabled={disabled}
onClick={onClick}
inline={inline}
/>
Expand Down
9 changes: 7 additions & 2 deletions src/components/utilities/CippListOffcanvas.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ CippListOffcanvas.propTypes = {
hideFunction: PropTypes.func.isRequired,
}

export function OffcanvasListSection({ title, items }) {
export function OffcanvasListSection({ title, items, showCardTitle = true }) {
//console.log(items)
const mappedItems = items.map((item, key) => ({ value: item.content, label: item.heading }))
return (
Expand All @@ -48,7 +48,11 @@ export function OffcanvasListSection({ title, items }) {
<CCard className="content-card">
<CCardHeader className="d-flex justify-content-between align-items-center">
<CCardTitle>
<FontAwesomeIcon icon={faGlobe} className="mx-2" /> Extended Information
{showCardTitle && (
<>
<FontAwesomeIcon icon={faGlobe} className="mx-2" /> Extended Information
</>
)}
</CCardTitle>
</CCardHeader>
<CCardBody>
Expand All @@ -62,4 +66,5 @@ export function OffcanvasListSection({ title, items }) {
OffcanvasListSection.propTypes = {
title: PropTypes.string,
items: PropTypes.array,
showCardTitle: PropTypes.bool,
}
276 changes: 276 additions & 0 deletions src/components/utilities/CippScheduleOffcanvas.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,276 @@
import React, { useState } from 'react'
import PropTypes from 'prop-types'
import {
CButton,
CCallout,
CCard,
CCardBody,
CCardHeader,
CCol,
CForm,
CRow,
CSpinner,
CTooltip,
} from '@coreui/react'
import { CippOffcanvas, TenantSelector } from '.'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { Field, Form, FormSpy } from 'react-final-form'
import arrayMutators from 'final-form-arrays'
import {
RFFCFormInput,
RFFCFormInputArray,
RFFCFormSwitch,
RFFSelectSearch,
} from 'src/components/forms'
import { useSelector } from 'react-redux'
import { useGenericGetRequestQuery, useLazyGenericPostRequestQuery } from 'src/store/api/app'
import DatePicker from 'react-datepicker'
import 'react-datepicker/dist/react-datepicker.css'

export default function CippScheduleOffcanvas({
state: visible,
hideFunction,
title,
placement,
...props
}) {
const currentDate = new Date()
const [startDate, setStartDate] = useState(currentDate)
const tenantDomain = useSelector((state) => state.app.currentTenant.defaultDomainName)
const [refreshState, setRefreshState] = useState(false)
const taskName = `Scheduled Task ${currentDate.toLocaleString()}`
const { data: availableCommands = [], isLoading: isLoadingcmd } = useGenericGetRequestQuery({
path: 'api/ListFunctionParameters?Module=CIPPCore',
})

const recurrenceOptions = [
{ value: '0', name: 'Only once' },
{ value: '1', name: 'Every 1 day' },
{ value: '7', name: 'Every 7 days' },
{ value: '30', name: 'Every 30 days' },
{ value: '365', name: 'Every 365 days' },
]

const [genericPostRequest, postResults] = useLazyGenericPostRequestQuery()
const onSubmit = (values) => {
const unixTime = Math.floor(startDate.getTime() / 1000)
const shippedValues = {
TenantFilter: tenantDomain,
Name: values.taskName,
Command: values.command,
Parameters: values.parameters,
ScheduledTime: unixTime,
Recurrence: values.Recurrence,
AdditionalProperties: values.additional,
PostExecution: {
Webhook: values.webhook,
Email: values.email,
PSA: values.psa,
},
}
genericPostRequest({ path: '/api/AddScheduledItem', values: shippedValues }).then((res) => {
setRefreshState(res.requestId)
if (props.submitFunction) {
props.submitFunction()
}
})
}

return (
<CippOffcanvas
placement={placement}
title={title}
visible={visible}
hideFunction={hideFunction}
>
<CCard>
<CCardHeader></CCardHeader>
<CCardBody>
<Form
onSubmit={onSubmit}
mutators={{
...arrayMutators,
}}
initialValues={{ ...props.initialValues }}
render={({ handleSubmit, submitting, values }) => {
return (
<CForm onSubmit={handleSubmit}>
<CRow className="mb-3">
<CCol>
<label>Tenant</label>
<Field name="tenantFilter">{(props) => <TenantSelector />}</Field>
</CCol>
</CRow>
<CRow>
<CCol>
<RFFCFormInput
type="text"
name="taskName"
label="Task Name"
firstValue={`Task ${currentDate.toLocaleString()}`}
/>
</CCol>
</CRow>
<CRow>
<CCol>
<label>Scheduled Date</label>
<DatePicker
className="form-control mb-3"
selected={startDate}
showTimeSelect
timeFormat="HH:mm"
timeIntervals={15}
dateFormat="Pp"
onChange={(date) => setStartDate(date)}
/>
</CCol>
</CRow>
<CRow className="mb-3">
<CCol>
<RFFSelectSearch
values={recurrenceOptions}
name="Recurrence"
placeholder="Select a recurrence"
label="Recurrence"
/>
</CCol>
</CRow>
<CRow className="mb-3">
<CCol>
<RFFSelectSearch
values={availableCommands.map((cmd) => ({
value: cmd.Function,
name: cmd.Function,
}))}
name="command"
placeholder={
isLoadingcmd ? (
<CSpinner size="sm" />
) : (
'Select a command or report to execute.'
)
}
label="Command to execute"
/>
</CCol>
</CRow>
<FormSpy>
{/* eslint-disable react/prop-types */}
{(props) => {
const selectedCommand = availableCommands.find(
(cmd) => cmd.Function === props.values.command?.value,
)
return (
<CRow className="mb-3">
<CCol>{selectedCommand?.Synopsis}</CCol>
</CRow>
)
}}
</FormSpy>
<CRow>
<FormSpy>
{/* eslint-disable react/prop-types */}
{(props) => {
const selectedCommand = availableCommands.find(
(cmd) => cmd.Function === props.values.command?.value,
)
let paramblock = null
if (selectedCommand) {
//if the command parameter type is boolean we use <RFFCFormCheck /> else <RFFCFormInput />.
const parameters = selectedCommand.Parameters
if (parameters.length > 0) {
paramblock = parameters.map((param, idx) => (
<CRow key={idx} className="mb-3">
<CTooltip
content={
param?.Description !== null
? param.Description
: 'No Description'
}
placement="left"
>
<CCol>
{param.Type === 'System.Boolean' ||
param.Type ===
'System.Management.Automation.SwitchParameter' ? (
<>
<label>{param.Name}</label>
<RFFCFormSwitch
initialValue={false}
name={`parameters.${param.Name}`}
label={`True`}
/>
</>
) : (
<>
{param.Type === 'System.Collections.Hashtable' ? (
<RFFCFormInputArray
name={`parameters.${param.Name}`}
label={`${param.Name}`}
key={idx}
/>
) : (
<RFFCFormInput
type="text"
key={idx}
name={`parameters.${param.Name}`}
label={`${param.Name}`}
/>
)}
</>
)}
</CCol>
</CTooltip>
</CRow>
))
}
}
return paramblock
}}
</FormSpy>
</CRow>
<CRow className="mb-3">
<CCol>
<RFFCFormInputArray name={`additional`} label="Additional Properties" />
</CCol>
</CRow>
<CRow className="mb-3">
<CCol>
<label>Send results to</label>
<RFFCFormSwitch name="webhook" label="Webhook" />
<RFFCFormSwitch name="email" label="E-mail" />
<RFFCFormSwitch name="psa" label="PSA" />
</CCol>
</CRow>
<CRow className="mb-3">
<CCol md={6}>
<CButton type="submit" disabled={submitting}>
Add Schedule
{postResults.isFetching && (
<FontAwesomeIcon icon="circle-notch" spin className="ms-2" size="1x" />
)}
</CButton>
</CCol>
</CRow>
{postResults.isSuccess && (
<CCallout color="success">
<li>{postResults.data.Results}</li>
</CCallout>
)}
</CForm>
)
}}
/>
</CCardBody>
</CCard>
</CippOffcanvas>
)
}

CippScheduleOffcanvas.propTypes = {
groups: PropTypes.array,
placement: PropTypes.string.isRequired,
title: PropTypes.string.isRequired,
state: PropTypes.bool,
hideFunction: PropTypes.func.isRequired,
}
1 change: 0 additions & 1 deletion src/views/cipp/Scheduler.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,6 @@ const Scheduler = () => {
if (typeof row?.Parameters[key] === 'object') {
var nestedParamList = []
Object.keys(row?.Parameters[key]).forEach((nestedKey) => {
console.log(nestedKey)
nestedParamList.push({
Key: nestedKey,
Value: row?.Parameters[key][nestedKey],
Expand Down
2 changes: 2 additions & 0 deletions src/views/cipp/app-settings/SettingsExtensionMappings.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,7 @@ export function SettingsExtensionMappings() {
onClick={() => {
if (
mappingValue.value !== undefined &&
mappingValue.value !== '-1' &&
Object.values(haloMappingsArray)
.map((item) => item.haloId)
.includes(mappingValue.value) === false
Expand Down Expand Up @@ -481,6 +482,7 @@ export function SettingsExtensionMappings() {
//set the new mapping in the array
if (
mappingValue.value !== undefined &&
mappingValue.value !== '-1' &&
Object.values(ninjaMappingsArray)
.map((item) => item.ninjaId)
.includes(mappingValue.value) === false
Expand Down
Loading

0 comments on commit ed01c11

Please sign in to comment.