Skip to content

Commit

Permalink
Merge branch 'main' into hotfix/risk-scenarios-table-sorting
Browse files Browse the repository at this point in the history
  • Loading branch information
ab-smith committed May 18, 2024
2 parents 030825f + fc5b407 commit 6b284db
Show file tree
Hide file tree
Showing 94 changed files with 3,997 additions and 1,289 deletions.
22 changes: 11 additions & 11 deletions .github/workflows/functional-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,13 @@ jobs:
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
mailhog:
image: mailhog/mailhog
ports: [
"1025:1025",
"8025:8025"
]
ports: ["1025:1025", "8025:8025"]

strategy:
max-parallel: 4
matrix:
python-version: ["3.11"]
playwright-browser: ["chromium", "firefox"]

steps:
- uses: actions/checkout@v4
Expand All @@ -54,10 +52,12 @@ jobs:
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
- name: Install dependencies
working-directory: ${{ env.working-directory }}
run: npm ci
- name: Install Playwright Browsers
run: |
npm install
npm ci
- name: Install Playwright browser ${{ matrix.playwright-browser }}
working-directory: ${{ env.working-directory }}
run: npx playwright install --with-deps
run: npx playwright install --with-deps ${{ matrix.playwright-browser }}
- name: Create frontend environment variables file
working-directory: ${{ env.working-directory }}
run: |
Expand Down Expand Up @@ -93,14 +93,14 @@ jobs:
export $(grep -v '^#' .env | xargs)
python manage.py createsuperuser --noinput
nohup python manage.py runserver &
- name: Run tests
- name: Run tests with browser ${{ matrix.playwright-browser }}
working-directory: ${{ env.working-directory }}
run: npx playwright test
run: npx playwright test --project=${{ matrix.playwright-browser }}
- uses: actions/upload-artifact@v4
if: always()
with:
name: functional-tests-report
path: |
${{ env.working-directory }}/tests/results/
${{ env.working-directory }}/tests/reports/
${{ env.working-directory }}/tests/${{ matrix.playwright-browser }}results/
${{ env.working-directory }}/tests/${{ matrix.playwright-browser }}reports/
retention-days: 5
5 changes: 3 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@ repos:
rev: v0.4.1
hooks:
# Run the linter.
- id: ruff
args: [--fix backend]
# - id: ruff
# args: [--fix, backend]
# Run the formatter.
- id: ruff-format
args: [backend]
exclude: (migrations)
- repo: local
hooks:
- id: format-frontend
Expand Down
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ Check out the online documentation on https://intuitem.gitbook.io/ciso-assistant

1. ISO 27001:2022, version Française 🇫🇷🌐
2. PGSSI-S (Politique Générale de Sécurité des Systèmes d'Information de Santé) 🇫🇷
3. ANSSI : Recommandations de configuration d'un système GNU/Linux 🇫🇷

<br/>

Expand Down Expand Up @@ -261,6 +262,10 @@ export DJANGO_SECRET_KEY=...
# Logging configuration
export LOG_LEVEL=INFO # optional, default value is INFO. Available options: DEBUG, INFO, WARNING, ERROR, CRITICAL
export LOG_FORMAT=plain # optional, default value is plain. Available options: json, plain

# Authentication options
export AUTH_TOKEN_TTL=900 # optional, default value is 900 seconds (15 minutes). It defines the time to live of the authentication token
export AUTH_TOKEN_AUTO_REFRESH=True # optional, default value is True. It defines if the token TTL should be refreshed automatically after each request authenticated with the token
```

3. Choose the tool of your choice, either python-venv or virtualenv. For example:
Expand Down Expand Up @@ -413,7 +418,7 @@ Set DJANGO_DEBUG=False for security reason.

- [Django](https://www.djangoproject.com/) - Python Web Development Framework
- [SvelteKit](https://kit.svelte.dev/) - Frontend Framework
- [eCharts](https://echarts.apache.org) - Charting library
- [eCharts](https://echarts.apache.org) - Charting library
- [Gunicorn](https://gunicorn.org/) - Python WSGI HTTP Server for UNIX
- [Caddy](https://caddyserver.com) - The coolest reverse Proxy
- [Gitbook](https://www.gitbook.com) - Documentation platform
Expand Down
48 changes: 31 additions & 17 deletions backend/app_tests/api/test_api_libraries.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import json
import pytest
from rest_framework.test import APIClient
from core.models import Framework
from app_tests.test_vars import TEST_FRAMEWORK_URN, TEST_RISK_MATRIX_URN
from core.models import Framework, StoredLibrary
from core.models import RiskMatrix
from iam.models import Folder
from rest_framework import status
Expand All @@ -17,7 +19,7 @@ class TestLibrariesUnauthenticated:
def test_get_libraries(self):
"""test to get libraries from the API without authentication"""

EndpointTestsQueries.get_object(self.client, "Libraries")
EndpointTestsQueries.get_object(self.client, "Stored libraries")

def test_import_frameworks(self):
"""test to import libraries with the API without authentication"""
Expand Down Expand Up @@ -50,21 +52,27 @@ def test_get_libraries(self, test):
"""test to get libraries from the API with authentication"""

EndpointTestsQueries.Auth.get_object(
test.client, "Libraries", base_count=-1, user_group=test.user_group
test.client, "Stored libraries", base_count=-1, user_group=test.user_group
)

def test_import_frameworks(self, test):
"""test to import frameworks with the API with authentication"""

# Uses the API endpoint to get library details with the admin client
lib_detail_response = test.admin_client.get(
EndpointTestsUtils.get_object_urn("Framework")
).json()["objects"]["framework"]
EndpointTestsUtils.get_stored_library_content(
test.client, TEST_FRAMEWORK_URN
)
)
lib_detail_response = lib_detail_response.content
lib_detail_response = json.loads(lib_detail_response)
lib_detail_response = json.loads(lib_detail_response)
lib_detail_response = lib_detail_response["framework"]

# Asserts that the library is not already imported
# Asserts that the library is not already loaded
assert (
Framework.objects.all().count() == 0
), "libraries are already imported in the database"
), "libraries are already loaded in the database"
EndpointTestsQueries.Auth.get_object(
test.client,
"Frameworks",
Expand All @@ -78,12 +86,12 @@ def test_import_frameworks(self, test):
assert Framework.objects.all().count() == (
1
if not EndpointTestsUtils.expected_request_response(
"add", "library", str(test.folder), test.user_group
"add", "loadedlibrary", str(test.folder), test.user_group
)[0]
else 0
), "Frameworks are not correctly imported in the database"

# Uses the API endpoint to assert that the library was properly imported
# Uses the API endpoint to assert that the library was properly loaded
EndpointTestsQueries.Auth.get_object(
test.client,
"Frameworks",
Expand All @@ -96,7 +104,7 @@ def test_import_frameworks(self, test):
base_count=1,
user_group=test.user_group,
fails=EndpointTestsUtils.expected_request_response(
"add", "library", str(test.folder), test.user_group
"add", "loadedlibrary", str(test.folder), test.user_group
)[0],
)

Expand All @@ -121,13 +129,19 @@ def test_import_risk_matrix(self, test):

# Uses the API endpoint to get library details with the admin client
lib_detail_response = test.admin_client.get(
EndpointTestsUtils.get_object_urn("Risk matrix")
).json()["objects"]["risk_matrix"][0]
EndpointTestsUtils.get_stored_library_content(
test.client, TEST_RISK_MATRIX_URN
)
)
lib_detail_response = lib_detail_response.content
lib_detail_response = json.loads(lib_detail_response)
lib_detail_response = json.loads(lib_detail_response)
lib_detail_response = lib_detail_response["risk_matrix"][0]

# Asserts that the library is not already imported
# Asserts that the library is not already loaded
assert (
RiskMatrix.objects.all().count() == 0
), "libraries are already imported in the database"
), "libraries are already loaded in the database"
EndpointTestsQueries.Auth.get_object(
test.client, "Risk matrices", user_group=test.user_group
)
Expand All @@ -139,12 +153,12 @@ def test_import_risk_matrix(self, test):
assert RiskMatrix.objects.all().count() == (
1
if not EndpointTestsUtils.expected_request_response(
"add", "library", str(test.folder), test.user_group
"add", "loadedlibrary", str(test.folder), test.user_group
)[0]
else 0
), "Risk matrices are not correctly imported in the database"

# Uses the API endpoint to assert that the library was properly imported
# Uses the API endpoint to assert that the library was properly loaded
EndpointTestsQueries.Auth.get_object(
test.client,
"Risk matrices",
Expand All @@ -158,7 +172,7 @@ def test_import_risk_matrix(self, test):
base_count=1,
user_group=test.user_group,
fails=EndpointTestsUtils.expected_request_response(
"add", "library", str(test.folder), test.user_group
"add", "loadedlibrary", str(test.folder), test.user_group
)[0],
)

Expand Down
7 changes: 5 additions & 2 deletions backend/app_tests/api/test_api_requirement_nodes.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import pytest
from rest_framework.test import APIClient
from core.models import RequirementNode, Framework
from app_tests.test_vars import TEST_FRAMEWORK_URN
from core.models import RequirementNode, Framework, StoredLibrary
from iam.models import Folder

from test_utils import EndpointTestsQueries, EndpointTestsUtils
Expand Down Expand Up @@ -76,7 +77,9 @@ def test_import_requirement_nodes(self, test):
test.client,
"Requirement nodes",
EndpointTestsUtils.get_endpoint_url("Requirement nodes"),
EndpointTestsUtils.get_object_urn("Framework"),
EndpointTestsUtils.get_stored_library_content(
test.client, TEST_FRAMEWORK_URN
),
[
"name",
"description",
Expand Down
25 changes: 20 additions & 5 deletions backend/app_tests/api/test_utils.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from django.db import models
from knox.auth import AuthToken
import pytest
import json
Expand All @@ -6,6 +7,7 @@
from django.urls import reverse
from rest_framework import status
from rest_framework.test import APIClient
from core.models import StoredLibrary

from test_vars import *

Expand All @@ -25,7 +27,17 @@ def get_object_urn(object_name: str, resolved: bool = True):

urn_varname = format_urn(object_name)
urn = get_var(urn_varname)
return f"{reverse(LIBRARIES_ENDPOINT)}{urn}/" if resolved else eval(urn)
return f"{reverse(STORED_LIBRARIES_ENDPOINT)}{urn}/" if resolved else eval(urn)

def get_referential_object_url_from_urn(
authenticated_client, urn: str, model: models.Model = StoredLibrary
):
"""Get the object URL from the URN"""
return f"{reverse(STORED_LIBRARIES_ENDPOINT)}{urn}/"

def get_stored_library_content(authenticated_client, urn: str) -> str:
"""Return an URL to fetch the content of a stored library"""
return f"{reverse(STORED_LIBRARIES_ENDPOINT)}{urn}/content/"

@pytest.mark.django_db
def get_test_client_and_folder(
Expand Down Expand Up @@ -958,7 +970,7 @@ def import_object(
user_perm_expected_status,
user_perm_reason,
) = EndpointTestsUtils.expected_request_response(
"add", "library", scope, user_group, expected_status
"add", "loadedlibrary", scope, user_group, expected_status
)

url = urn or EndpointTestsUtils.get_object_urn(verbose_name)
Expand Down Expand Up @@ -1014,9 +1026,12 @@ def compare_results(
reference.status_code == status.HTTP_200_OK
), "reference endpoint is not accessible"

for object in reference.json()["objects"]["framework"][
object_name.lower().replace(" ", "_")
][:count]:
content = json.loads(reference.content)
content = json.loads(content)

for object in content["framework"][object_name.lower().replace(" ", "_")][
:count
]:
comparelist = authenticated_client.get(compare_url)
compare = dict()
assert (
Expand Down
2 changes: 1 addition & 1 deletion backend/app_tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def __init__(self, *args, **kwargs):

@pytest.fixture
def app_config():
startup()
startup(sender=None, **{})


@pytest.fixture
Expand Down
4 changes: 2 additions & 2 deletions backend/app_tests/test_vars.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
EVIDENCES_ENDPOINT = "evidences-list"
FOLDERS_ENDPOINT = "folders-list"
FRAMEWORKS_ENDPOINT = "frameworks-list"
LIBRARIES_ENDPOINT = "libraries-list"
STORED_LIBRARIES_ENDPOINT = "stored-libraries-list"
RISK_MATRICES_ENDPOINT = "risk-matrices-list"
PROJECTS_ENDPOINT = "projects-list"
REQUIREMENT_ASSESSMENTS_ENDPOINT = "requirement-assessments-list"
Expand Down Expand Up @@ -95,7 +95,7 @@ def get_var(varname: str) -> Any:

def get_singular_name(plural_name: str) -> str:
exceptions = {
"Libraries": "Library",
"Stored libraries": "Stored library",
"Risk matrices": "Risk matrix",
"Policies": "Policy",
}
Expand Down
23 changes: 0 additions & 23 deletions backend/cal/forms.py

This file was deleted.

2 changes: 1 addition & 1 deletion backend/ciso_assistant/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ def set_ciso_assistant_url(_, __, event_dict):

# SQLIte file can be changed, useful for tests
SQLITE_FILE = os.environ.get("SQLITE_FILE", BASE_DIR / "db/ciso-assistant.sqlite3")

LIBRARIES_PATH = library_path = BASE_DIR / "library/libraries"

if "POSTGRES_NAME" in os.environ:
DATABASES = {
Expand Down
Loading

0 comments on commit 6b284db

Please sign in to comment.