Skip to content

Commit

Permalink
New features (#1)
Browse files Browse the repository at this point in the history
- Dark/Light Mode
- Sample attack tests (simple, moderate, complex format)
- Upload a YAML test file to edit exist one.
  • Loading branch information
krdmnbrk authored Dec 12, 2024
2 parents 0071b25 + a14c51e commit 72f93cd
Show file tree
Hide file tree
Showing 17 changed files with 487 additions and 32 deletions.
1 change: 1 addition & 0 deletions .env
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
GENERATE_SOURCEMAP=false
3 changes: 1 addition & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 2 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "atomicgen.io",
"version": "0.1.0",
"version": "1.0.0",
"private": true,
"dependencies": {
"@emotion/react": "^11.13.3",
Expand All @@ -19,8 +19,7 @@
"react-ace": "^13.0.0",
"react-dom": "^18.3.1",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4",
"yaml": "^2.6.1"
"web-vitals": "^2.1.4"
},
"scripts": {
"start": "react-scripts start",
Expand Down
44 changes: 39 additions & 5 deletions src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,12 @@ const base = {
description: null,
supported_platforms: [],
input_arguments: [],
dependency_executor_name: null,
dependency_executor_name: "",
dependencies: [],
executor: {
command: null,
cleanup_command: null,
name: null,
name: "",
elevation_required: false,
},
};
Expand Down Expand Up @@ -126,8 +126,10 @@ const validateInputs = (data, rules) => {
function App() {
const [errors, setErrors] = useState([]);
const [validationErrors, setValidationErrors] = useState([]);
const [inputButtonErrors, setInputButtonErrors] = useState([]);
const [updated, setUpdated] = useState(false);
const [inputs, setInputs] = useState(base);
const [darkMode, setDarkMode] = useState(true);
const [isPortrait, setIsPortrait] = useState(window.innerHeight > window.innerWidth);
const [changed, setChanged] = useState(false);

Expand Down Expand Up @@ -156,6 +158,13 @@ function App() {
return () => window.removeEventListener('resize', handleResize);
}, []);

useEffect(() => {
const cachedTheme = localStorage.getItem('darkMode');
if (cachedTheme !== null) {
setDarkMode(cachedTheme === 'true');
}
}, []);

// Check if inputs are updated
useEffect(() => {
if (JSON.stringify(inputs) === JSON.stringify(base)) {
Expand All @@ -169,6 +178,7 @@ function App() {

// Validate inputs
useEffect(() => {
setInputButtonErrors([]);
if (updated) {

const errors = validateInputs(inputs, validationRules);
Expand All @@ -183,7 +193,7 @@ function App() {
palette: {
mode: 'dark',
primary: {
main: red[700],
main: red[500],
contrastText: '#fff',
},
background: {
Expand All @@ -196,24 +206,48 @@ function App() {
},
});

const lightTheme = createTheme({
palette: {
mode: 'light',
primary: {
main: red[900],
contrastText: '#fff',
},
background: {
paper: "#fff",
},
text: {
primary: "#000",
secondary: grey[600],
},
},
});

return (
<ThemeProvider theme={darkTheme}>
<ThemeProvider theme={darkMode ? darkTheme : lightTheme}>
<CssBaseline />
<Navbar/>
<Navbar darkMode={darkMode} setDarkMode={setDarkMode} />
<Box sx={{ p: 2 }}>
<Grid container spacing={2}>
<Grid size={isPortrait ? 12 : 6}>
<Inputs
base={base}
darkMode={darkMode}
changed={changed}
setChanged={setChanged}
executor_names={executor_names}
supported_platforms={supported_platforms}
inputs={inputs}
setInputs={setInputs}
errors={errors}
setErrors={setErrors}
inputButtonErrors={inputButtonErrors}
setInputButtonErrors={setInputButtonErrors}
/>
</Grid>
<Grid size={isPortrait ? 12 : 6}>
<YamlContent
darkMode={darkMode}
base={base}
errors={errors}
setErrors={setErrors}
Expand Down
6 changes: 4 additions & 2 deletions src/components/Editor.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import 'ace-builds/src-noconflict/mode-yaml';

// Importing the theme for the Ace Editor
import 'ace-builds/src-noconflict/theme-tomorrow_night_bright';
import 'ace-builds/src-noconflict/theme-github_light_default';

// Editor component definition
const Editor = ({
Expand All @@ -22,14 +23,15 @@ const Editor = ({
highlightGutterLine, // Highlight the line number in the gutter
maxLines, // Maximum number of lines before scrolling
placeholder, // Placeholder text when editor is empty
wrap // Text wrapping toggle
wrap, // Text wrapping toggle
darkMode // Dark mode toggle
}) => {
return (
<AceEditor
// Setting the programming language mode (e.g., YAML, PowerShell, Shell)
mode={mode}
// Applying the "Tomorrow Night Bright" theme for dark mode
theme="tomorrow_night_bright"
theme={darkMode ? "tomorrow_night_bright" : "github_light_default"}
// Callback function triggered when the editor content changes
onChange={onChange}
// Setting font size or defaulting to 14px
Expand Down
23 changes: 19 additions & 4 deletions src/components/Inputs.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import PropTypes from 'prop-types';
import Arguments from './Inputs/Arguments';
import Dependency from './Inputs/Dependency';
import Editor from './Editor';
import InputButtons from './Inputs/InputButtons';

// Constants for dropdown menu properties
const ITEM_HEIGHT = 48;
Expand All @@ -32,8 +33,8 @@ const MenuProps = {
};

// Functional component for managing inputs
function Inputs({ errors, setErrors, inputs, setInputs, executor_names, supported_platforms }) {
function Inputs({ inputButtonErrors, setInputButtonErrors, base, darkMode, changed, setChanged, errors, setErrors, inputs, setInputs, executor_names, supported_platforms }) {

// Handle changes to text fields (e.g., Atomic Name, Atomic Description)
const handleChangeText = (e) => {
const { name, value } = e.target;
Expand Down Expand Up @@ -100,6 +101,18 @@ function Inputs({ errors, setErrors, inputs, setInputs, executor_names, supporte

return (
<Box>
<Box sx={{ mb: 2 }}>
<InputButtons
inputButtonErrors={inputButtonErrors}
setInputButtonErrors={setInputButtonErrors}
base={base}
setInputs={setInputs}
setChanged={setChanged}
changed={changed}
darkMode={darkMode}

/>
</Box>
{/* Input for Atomic Name */}
<Box sx={{ mb: 2 }}>
<TextField
Expand Down Expand Up @@ -208,6 +221,7 @@ function Inputs({ errors, setErrors, inputs, setInputs, executor_names, supporte
Attack Command *
</Typography>
<Editor
darkMode={darkMode}
mode={inputs.executor.name === "powershell" ? "powershell" : "sh"}
name="attack-command-editor"
value={inputs.executor.command || ''}
Expand All @@ -223,6 +237,7 @@ function Inputs({ errors, setErrors, inputs, setInputs, executor_names, supporte
Cleanup Command (Optional)
</Typography>
<Editor
darkMode={darkMode}
mode={inputs.executor.name === "powershell" ? "powershell" : "sh"}
name="cleanup-command-editor"
value={inputs.executor.cleanup_command || ''}
Expand All @@ -236,10 +251,10 @@ function Inputs({ errors, setErrors, inputs, setInputs, executor_names, supporte
<Box sx={{ mb: 2 }}>
<Grid container spacing={2}>
<Grid size={6}>
<Dependency executor_names={executor_names} errors={errors} setErrors={setErrors} inputs={inputs} setInputs={setInputs} />
<Dependency darkMode={darkMode} executor_names={executor_names} errors={errors} setErrors={setErrors} inputs={inputs} setInputs={setInputs} />
</Grid>
<Grid size={6}>
<Arguments errors={errors} setErrors={setErrors} inputs={inputs} setInputs={setInputs} />
<Arguments darkMode={darkMode} errors={errors} setErrors={setErrors} inputs={inputs} setInputs={setInputs} />
</Grid>
</Grid>
</Box>
Expand Down
10 changes: 5 additions & 5 deletions src/components/Inputs/Arguments.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import Button from '@mui/material/Button';
import Typography from '@mui/material/Typography';

// Arguments component for managing input arguments
function Arguments({ errors, setErrors, inputs, setInputs }) {
function Arguments({ darkMode, errors, setErrors, inputs, setInputs }) {
// Check if there are duplicate names among the input arguments
function hasDuplicateNames(data) {
const names = data.map(obj => obj.name.trim());
Expand Down Expand Up @@ -90,7 +90,7 @@ function Arguments({ errors, setErrors, inputs, setInputs }) {
<Button
sx={{ mb: 1 }}
startIcon={<AddCircleOutlineIcon />}
variant="text"
variant={darkMode ? "outlined" : "contained"}
onClick={addInputArgument}
>
Add Input Argument {inputs.input_arguments.length > 0 ? `(${inputs.input_arguments.length})` : ''}
Expand All @@ -99,7 +99,7 @@ function Arguments({ errors, setErrors, inputs, setInputs }) {

{/* Display Validation Errors */}
{errors.length > 0 &&
<Alert sx={{ mb: 1 }} variant='outlined' severity="error">
<Alert sx={{ mb: 1 }} variant={darkMode ? "outlined" : "filled"} severity="error">
{errors.map((error, index) => (
<li key={index}>
{error}
Expand Down Expand Up @@ -177,8 +177,8 @@ function Arguments({ errors, setErrors, inputs, setInputs }) {
<IconButton
aria-label="delete"
size="large"
color="error"
variant="outlined"
color="primary"
variant={darkMode ? "outlined" : "contained"}
onClick={() => removeInputArgument(index)}
>
<DeleteIcon fontSize="inherit" />
Expand Down
17 changes: 12 additions & 5 deletions src/components/Inputs/Dependency.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import InfoIcon from '@mui/icons-material/Info';
import Editor from '../Editor';

// Dependency component for managing prerequisite commands and dependencies
function Dependency({ inputs, setInputs, executor_names }) {
function Dependency({ darkMode, inputs, setInputs, executor_names }) {
// State for managing tooltip visibility
const [tooltipOpen, setTooltipOpen] = useState(false);

Expand Down Expand Up @@ -85,8 +85,13 @@ function Dependency({ inputs, setInputs, executor_names }) {
</Typography>

{/* Button to add a new dependency */}
<Box sx={{ mt: 1 }}>
<Button startIcon={<AddCircleOutlineIcon />} sx={{ mr: 2, mb: 1 }} variant="text" onClick={addDependency}>
<Box sx={{ mt: 1, mb: 1 }}>
<Button
startIcon={<AddCircleOutlineIcon />}
sx={{ mr: 2, mb: 1 }}
variant={darkMode ? "outlined" : "contained"}
onClick={addDependency}
>
Add Dependency {inputs.dependencies.length > 0 ? `(${inputs.dependencies.length})` : ''}
</Button>
</Box>
Expand Down Expand Up @@ -151,6 +156,7 @@ function Dependency({ inputs, setInputs, executor_names }) {
Prerequisite Command
</Typography>
<Editor
darkMode={darkMode}
mode={inputs.executor.name === "powershell" ? "powershell" : "sh"}
name="prerequisite-command-editor"
value={dependency.prereq_command || ''}
Expand All @@ -164,6 +170,7 @@ function Dependency({ inputs, setInputs, executor_names }) {
Get Prerequisite Command
</Typography>
<Editor
darkMode={darkMode}
mode={inputs.executor.name === "powershell" ? "powershell" : "sh"}
name="prerequisite-command-editor"
value={dependency.get_prereq_command || ''}
Expand All @@ -176,8 +183,8 @@ function Dependency({ inputs, setInputs, executor_names }) {
<Box sx={{ display: 'flex', justifyContent: 'flex-end', mt: 2 }}>
<IconButton
size='large'
color="error"
variant="outlined"
color="primary"
variant={darkMode ? "outlined" : "contained"}
key={`remove-${index}`}
onClick={() => removeDependency(index)}
>
Expand Down
Loading

0 comments on commit 72f93cd

Please sign in to comment.