Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions backend/webserver/serializer/project_serializer.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from datetime import datetime

from rest_framework import serializers
from rest_framework.validators import MaxLengthValidator

from analyzer.models import Project
from utilities.constants import Status, Threshold
Expand All @@ -13,7 +12,7 @@ class Meta:
fields = ["projectId", "projectName", "updated", "deploymentThreshold"]

projectId = serializers.CharField(source="project_id", read_only=True)
projectName = serializers.CharField(source="project_name", allow_blank=True, validators=[MaxLengthValidator(255)])
projectName = serializers.CharField(source="project_name", allow_blank=True, max_length=255)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does this length relate to the maximum length of 25 characters declared in backend/analyzer/models.py?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, I haven't seen the constraint in models.py. I think that the check in project_serializer.py is then redundant and can be removed without losing validation. Is that correct? Or should we lave it, but reduce it to 25?

updated = serializers.DateTimeField(default=datetime.now(), read_only=True)
deploymentThreshold = serializers.ChoiceField(source="deployment_threshold", choices=Threshold.names)

Expand Down
54 changes: 32 additions & 22 deletions frontend/src/components/NavBar/ProjectCreationContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,15 @@ import {useNotification} from "../../context/NotificationContext";
const CreationContent: React.FunctionComponent<DialogContentProps> = (dialogContentProps: DialogContentProps) => {
const notification = useNotification();
const {data} = useQuery("allProjectsFlat", getAllProjectsFlat)
const [isInvalid, setInvalid] = useState(false);
const [isIdInvalid, setIdInvalid] = useState(true);
const [isNameInvalid, setNameInvalid] = useState(false);
const [isProjectIdTouched, setProjectIdTouched] = useState(false);
const [projectId, setProjectId] = useState("");
const [projectName, setProjectName] = useState("");
const [threshold, setThreshold] = useState("HIGH");
const queryClient = useQueryClient()
const [helperText, setHelperText] = useState("")
const [projectIdHelperText, setProjectIdHelperText] = useState("")
const [projectNameHelperText, setProjectNameHelperText] = useState("")
const handleSave = useMutation(() => createProject(projectId, {
projectName: projectName,
deploymentThreshold: threshold
Expand Down Expand Up @@ -52,52 +55,59 @@ const CreationContent: React.FunctionComponent<DialogContentProps> = (dialogCont
}

useEffect(() => {
if (!isProjectIdTouched) {
return;
}
if (projectId.length < 1){
setInvalid(true);
setHelperText(localization.dialog.projectIdHelperNotEmpty)
setIdInvalid(true);
setProjectIdHelperText(localization.dialog.projectIdHelperNotEmpty)
}else if (projectId.includes(" ")){
setInvalid(true);
setHelperText(localization.dialog.projectIdHelperNoSpaces)
setIdInvalid(true);
setProjectIdHelperText(localization.dialog.projectIdHelperNoSpaces)
}else if (projectId.length > 20){
setInvalid(true);
setHelperText(localization.dialog.projectIdHelperToLong)
setIdInvalid(true);
setProjectIdHelperText(localization.dialog.projectIdHelperToLong)
}else {
if (data?.data !== undefined) {
if (allProjectIds.includes(projectId.toLowerCase())) {
setInvalid(true);
setHelperText(localization.dialog.projectIdHelperIdAlreadyUsed)
setIdInvalid(true);
setProjectIdHelperText(localization.dialog.projectIdHelperIdAlreadyUsed)
} else {
setInvalid(false);
setHelperText("")
setIdInvalid(false);
setProjectIdHelperText("")
}
}
}
}, [projectId])
}, [projectId, isProjectIdTouched, allProjectIds])

useEffect(() => {
if (projectName.length > 255) {
setInvalid(true);
setHelperText(localization.dialog.projectNameHelperToLong);
setNameInvalid(true);
setProjectNameHelperText(localization.dialog.projectNameHelperToLong);
} else {
setInvalid(false);
setHelperText("");
setNameInvalid(false);
setProjectNameHelperText("Optional");
}
}, [projectName]);

return(
<Stack>
<Stack direction={"column"} sx={{width: "20rem", margin: "0px 25px 0px 25px"}}>
<TextField
helperText={helperText}
error={isInvalid}
helperText={projectIdHelperText}
error={isProjectIdTouched && isIdInvalid}
label={localization.dialog.projectId}
value={projectId}
variant="filled"
onChange={(e: ChangeEvent<HTMLTextAreaElement | HTMLInputElement>) => setProjectId(e.target.value)}
onChange={(e: ChangeEvent<HTMLTextAreaElement | HTMLInputElement>) => {
setProjectId(e.target.value)
setProjectIdTouched(true)
}}
/>
<TextField
style={{marginTop: "1rem"}}
helperText={"Optional"}
helperText={projectNameHelperText}
error={isNameInvalid}
label={localization.dialog.projectName}
value={projectName}
variant="filled"
Expand All @@ -115,7 +125,7 @@ const CreationContent: React.FunctionComponent<DialogContentProps> = (dialogCont
<Button color={"error"}
onClick={() => dialogContentProps.setOpen(false)}>{localization.misc.cancel}</Button>
<Button color={"success"}
disabled={isInvalid}
disabled={isIdInvalid || isNameInvalid}
onClick={() => handleSave.mutate()}>{localization.misc.save}</Button>
</Stack>
</Stack>
Expand Down
5 changes: 4 additions & 1 deletion frontend/src/queries/project-requests.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ export function updateProject(projectId: string, projectData: {}): AxiosPromise
return apiClient.put(urlAddress.api.project(projectId), projectData)
}

export function createProject(projectId: string, projectData: {}): AxiosPromise {
export function createProject(projectId: string, projectData: {
projectName: string,
deploymentThreshold: string
}): AxiosPromise {
if (projectData.projectName && projectData.projectName.length > 255) {
return Promise.reject(new Error("Project name exceeds the maximum length of 255 characters"));
}
Expand Down
2 changes: 1 addition & 1 deletion scripts/run-backend.bash
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ python manage.py createcachetable rate_limit
python manage.py migrate
python manage.py collectstatic --no-input

if [[ ${IS_DEV} == "true" ]] ; then
if [[ ${IS_DEV} == "True" ]] ; then
python manage.py runserver
else
gunicorn securecheckplus.wsgi:application --bind 0.0.0.0:8000 --workers=2 --threads=2 --log-level INFO
Expand Down