Skip to content

Commit

Permalink
Merge branch 'main' into global_setting_for_default_language
Browse files Browse the repository at this point in the history
  • Loading branch information
monsieurswag committed Oct 17, 2024
2 parents 2261e12 + 8cd02fd commit b9903f6
Show file tree
Hide file tree
Showing 60 changed files with 3,635 additions and 13,893 deletions.
108 changes: 108 additions & 0 deletions .github/workflows/backend-migrations-check.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
name: Backend migrations check

on:
pull_request:
branches: [main, develop]
types: [opened, synchronize]
workflow_dispatch:

env:
GITHUB_WORKFLOW: github_actions
backend-directory: ./backend
enterprise-backend-directory: ./enterprise/backend
enterprise-backend-settings-module: enterprise_core.settings

jobs:
migrations-check:
runs-on: ubuntu-20.04

strategy:
max-parallel: 4
matrix:
python-version: ["3.11"]

steps:
- uses: actions/checkout@v4
- name: Set up python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
cache: "pip"
- uses: actions/setup-node@v4
with:
node-version: latest
- name: Install requirements
working-directory: ${{ env.backend-directory }}
run: |
python -m pip install --upgrade pip
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
- name: Create backend environment variables file
working-directory: ${{ env.backend-directory }}
run: |
touch .env
echo DJANGO_DEBUG=True >> .env
echo [email protected] >> .env
echo DJANGO_SUPERUSER_PASSWORD=1234 >> .env
echo DB_HOST=localhost >> .env
echo CISO_ASSISTANT_SUPERUSER_EMAIL='' >> .env
echo CISO_ASSISTANT_URL=http://localhost:4173 >> .env
echo DEFAULT_FROM_EMAIL='[email protected]' >> .env
echo EMAIL_HOST=localhost >> .env
echo [email protected] >> .env
echo EMAIL_HOST_PASSWORD=password >> .env
echo EMAIL_PORT=1025 >> .env
- name: Check that migrations were made
working-directory: ${{ env.backend-directory }}
run: |
export $(grep -v '^#' .env | xargs)
python manage.py makemigrations --check --dry-run --verbosity=3
enterprise-migrations-check:
runs-on: ubuntu-20.04

strategy:
max-parallel: 4
matrix:
python-version: ["3.11"]

steps:
- uses: actions/checkout@v4
- name: Set up python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: "pip"
- name: Install Poetry
uses: snok/install-poetry@v1
with:
virtualenvs-create: false
installer-parallel: true
- name: Install backend requirements
working-directory: ${{ env.backend-directory }}
run: poetry install
- name: Install enterprise backend
working-directory: ${{ env.enterprise-backend-directory }}
run: poetry install
- name: Create backend environment variables file
working-directory: ${{ env.backend-directory }}
run: |
touch .env
echo DJANGO_DEBUG=True >> .env
echo [email protected] >> .env
echo DJANGO_SUPERUSER_PASSWORD=1234 >> .env
echo DB_HOST=localhost >> .env
echo CISO_ASSISTANT_SUPERUSER_EMAIL='' >> .env
echo CISO_ASSISTANT_URL=http://localhost:4173 >> .env
echo DEFAULT_FROM_EMAIL='[email protected]' >> .env
echo EMAIL_HOST=localhost >> .env
echo [email protected] >> .env
echo EMAIL_HOST_PASSWORD=password >> .env
echo EMAIL_PORT=1025 >> .env
echo DJANGO_SETTINGS_MODULE=enterprise_core.settings >> .env
echo LICENSE_SEATS=999 >> .env
- name: Check that migrations were made
working-directory: ${{ env.backend-directory }}
run: |
export $(grep -v '^#' .env | xargs)
poetry run python manage.py makemigrations --check --dry-run --verbosity=3 --settings=${{ env.enterprise-backend-settings-module }}
if [ $? -ne 0 ]; then echo "::error Migrations were not made, please run the makemigrations command." && exit 1; fi
6 changes: 3 additions & 3 deletions .github/workflows/frontend-linters.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@ jobs:
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- name: Install pnpm
- name: Install latest pnpm
working-directory: ${{env.working-directory}}
run: |
npm install -g pnpm &&
npm --version &&
npm list -g --depth 0
pnpm --version &&
pnpm list -g --depth 0
- name: Install prettier
working-directory: ${{env.working-directory}}
run: pnpm add --save-dev prettier
Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*.sqlite3
django_secret_key
temp/
db/
./db/
.dccache
/backend/profiles
./backend/ciso_assistant/.meta
Expand Down
2 changes: 1 addition & 1 deletion backend/core/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -2629,7 +2629,7 @@ def create_applied_controls_from_suggestions(self) -> list[AppliedControl]:
)
continue
if applied_controls:
self.applied_controls.add(applied_controls)
self.applied_controls.add(*applied_controls)
return applied_controls

class Meta:
Expand Down
4 changes: 3 additions & 1 deletion backend/core/startup.py
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,8 @@
"view_globalsettings",
"change_globalsettings",
"view_requirementmappingset",
"add_requirementmappingset",
"delete_requirementmappingset",
"view_requirementmapping",
"add_entity",
"change_entity",
Expand Down Expand Up @@ -367,7 +369,7 @@ def startup(sender: AppConfig, **kwargs):
name="Global", content_type=Folder.ContentType.ROOT, builtin=True
)
# if main entity does not exist, then create it
if not Entity.objects.filter(name="Main").exists():
if not Entity.get_main_entity():
main = Entity.objects.create(
name="Main", folder=Folder.get_root_folder(), builtin=True
)
Expand Down
4 changes: 4 additions & 0 deletions backend/core/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ def __str__(self) -> str:
str(UserGroupCodename.THIRD_PARTY_RESPONDENT): _("Third-party respondent"),
}

# NOTE: This is set to "Main" now, but will be changed to a unique identifier
# for internationalization.
MAIN_ENTITY_DEFAULT_NAME = "Main"

COUNTRY_FLAGS = {
"fr": "🇫🇷",
"en": "🇬🇧",
Expand Down
82 changes: 78 additions & 4 deletions backend/core/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -603,12 +603,57 @@ def treatment_plan_pdf(self, request, pk):
serializer_class=RiskAssessmentDuplicateSerializer,
)
def duplicate(self, request, pk):
def duplicate_related_objects(
scenario, duplicate_scenario, target_folder, field_name, model_class
):
"""
Duplicates related objects (e.g., controls, threats, assets) from a source scenario to a duplicate scenario,
ensuring that objects are not duplicated if they already exist in the/a target/parent domain (folder).
Parameters:
- scenario (object): The source scenario containing the related objects to be duplicated.
- duplicate_scenario (object): The duplicate scenario where the objects will be added.
- target_folder (object): The target folder where the duplicated objects will be stored.
- field_name (str): The field name representing the related objects to duplicate in the scenario.
- model_class (class): The model class of the related objects to be processed.
"""

# Get parent folders of the target folder
target_parent_folders = target_folder.get_parent_folders()

# Fetch all related objects for the given field name
related_objects = getattr(scenario, field_name).all()

for obj in related_objects:
# Check if an object with the same name already exists in the target folder
existing_obj = model_class.objects.filter(
name=obj.name, folder=target_folder
).first()

if existing_obj:
# If the object already exists in the targer folder, add the existing one to the duplicate scenario
getattr(duplicate_scenario, field_name).add(existing_obj)

elif obj.folder in target_parent_folders:
# If the object's folder is a parent of the targert folder, add the object to the duplicate scenario
getattr(duplicate_scenario, field_name).add(obj)

else:
# If the object doesn't exist, duplicate the object
duplicate_obj = obj
duplicate_obj.pk = None
duplicate_obj.folder = target_folder
duplicate_obj.save()
getattr(duplicate_scenario, field_name).add(duplicate_obj)

(object_ids_view, _, _) = RoleAssignment.get_accessible_object_ids(
Folder.get_root_folder(), request.user, RiskAssessment
)

if UUID(pk) in object_ids_view:
risk_assessment = self.get_object()
data = request.data

duplicate_risk_assessment = RiskAssessment.objects.create(
name=data["name"],
description=data["description"],
Expand All @@ -619,8 +664,10 @@ def duplicate(self, request, pk):
due_date=risk_assessment.due_date,
status=risk_assessment.status,
)

duplicate_risk_assessment.authors.set(risk_assessment.authors.all())
duplicate_risk_assessment.reviewers.set(risk_assessment.reviewers.all())

for scenario in risk_assessment.risk_scenarios.all():
duplicate_scenario = RiskScenario.objects.create(
risk_assessment=duplicate_risk_assessment,
Expand All @@ -636,11 +683,38 @@ def duplicate(self, request, pk):
strength_of_knowledge=scenario.strength_of_knowledge,
justification=scenario.justification,
)
duplicate_scenario.threats.set(scenario.threats.all())
duplicate_scenario.assets.set(scenario.assets.all())
duplicate_scenario.owner.set(scenario.owner.all())
duplicate_scenario.applied_controls.set(scenario.applied_controls.all())

duplicate_related_objects(
scenario,
duplicate_scenario,
duplicate_risk_assessment.project.folder,
"applied_controls",
AppliedControl,
)
duplicate_related_objects(
scenario,
duplicate_scenario,
duplicate_risk_assessment.project.folder,
"threats",
Threat,
)
duplicate_related_objects(
scenario,
duplicate_scenario,
duplicate_risk_assessment.project.folder,
"assets",
Asset,
)

if (
duplicate_risk_assessment.project.folder
in [risk_assessment.project.folder]
+ risk_assessment.project.folder.sub_folders()
):
duplicate_scenario.owner.set(scenario.owner.all())

duplicate_scenario.save()

duplicate_risk_assessment.save()
return Response({"results": "risk assessment duplicated"})

Expand Down
25 changes: 13 additions & 12 deletions backend/iam/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -721,18 +721,19 @@ def get_accessible_object_ids(

if hasattr(object_type, "is_published"):
for my_folder in folders_with_local_view:
target_folders = []
my_folder2 = my_folder
while my_folder2:
if my_folder2 != my_folder:
target_folders.append(my_folder2)
my_folder2 = my_folder2.parent_folder
for object in [
x
for x in all_objects
if folder_for_object[x] in target_folders and x.is_published
]:
permissions_per_object_id[object.id].add(permissions[0])
if my_folder.content_type != Folder.ContentType.ENCLAVE:
target_folders = []
my_folder2 = my_folder
while my_folder2:
if my_folder2 != my_folder:
target_folders.append(my_folder2)
my_folder2 = my_folder2.parent_folder
for object in [
x
for x in all_objects
if folder_for_object[x] in target_folders and x.is_published
]:
permissions_per_object_id[object.id].add(permissions[0])

return (
[
Expand Down
Loading

0 comments on commit b9903f6

Please sign in to comment.