From 2a771b924fd0baa583013bb4096dbbef5a73d5d7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 30 Oct 2024 15:31:04 +0100 Subject: [PATCH 01/34] chore(deps): update keycloak/keycloak docker tag to v26.0.4 (#2133) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- docker-compose-dev-keycloak.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose-dev-keycloak.yml b/docker-compose-dev-keycloak.yml index 148a8255a..6226f8169 100644 --- a/docker-compose-dev-keycloak.yml +++ b/docker-compose-dev-keycloak.yml @@ -84,7 +84,7 @@ services: - "8025:8025" keycloak: - image: keycloak/keycloak:26.0.2 + image: keycloak/keycloak:26.0.4 environment: - KEYCLOAK_ADMIN=admin - KEYCLOAK_ADMIN_PASSWORD=admin From ecbf5e208de0081473197c2000bad8da7da9df00 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 31 Oct 2024 06:28:08 +0000 Subject: [PATCH 02/34] fix(deps): update dependency mermaid to v11.4.0 (#2134) --- frontend/package-lock.json | 281 +++++++++++++++++++++++++++++++++++-- frontend/package.json | 2 +- 2 files changed, 271 insertions(+), 12 deletions(-) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index a7e6ca4ac..12802a271 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -21,7 +21,7 @@ "axios": "1.7.7", "chart.js": "4.4.6", "markdown-to-jsx": "7.5.0", - "mermaid": "11.3.0", + "mermaid": "11.4.0", "oidc-client-ts": "3.1.0", "prop-types": "15.8.1", "query-string": "9.1.1", @@ -2270,23 +2270,268 @@ "@babel/types": "^7.20.7" } }, + "node_modules/@types/d3": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@types/d3/-/d3-7.4.3.tgz", + "integrity": "sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww==", + "license": "MIT", + "dependencies": { + "@types/d3-array": "*", + "@types/d3-axis": "*", + "@types/d3-brush": "*", + "@types/d3-chord": "*", + "@types/d3-color": "*", + "@types/d3-contour": "*", + "@types/d3-delaunay": "*", + "@types/d3-dispatch": "*", + "@types/d3-drag": "*", + "@types/d3-dsv": "*", + "@types/d3-ease": "*", + "@types/d3-fetch": "*", + "@types/d3-force": "*", + "@types/d3-format": "*", + "@types/d3-geo": "*", + "@types/d3-hierarchy": "*", + "@types/d3-interpolate": "*", + "@types/d3-path": "*", + "@types/d3-polygon": "*", + "@types/d3-quadtree": "*", + "@types/d3-random": "*", + "@types/d3-scale": "*", + "@types/d3-scale-chromatic": "*", + "@types/d3-selection": "*", + "@types/d3-shape": "*", + "@types/d3-time": "*", + "@types/d3-time-format": "*", + "@types/d3-timer": "*", + "@types/d3-transition": "*", + "@types/d3-zoom": "*" + } + }, + "node_modules/@types/d3-array": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.1.tgz", + "integrity": "sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg==", + "license": "MIT" + }, + "node_modules/@types/d3-axis": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-axis/-/d3-axis-3.0.6.tgz", + "integrity": "sha512-pYeijfZuBd87T0hGn0FO1vQ/cgLk6E1ALJjfkC0oJ8cbwkZl3TpgS8bVBLZN+2jjGgg38epgxb2zmoGtSfvgMw==", + "license": "MIT", + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-brush": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-brush/-/d3-brush-3.0.6.tgz", + "integrity": "sha512-nH60IZNNxEcrh6L1ZSMNA28rj27ut/2ZmI3r96Zd+1jrZD++zD3LsMIjWlvg4AYrHn/Pqz4CF3veCxGjtbqt7A==", + "license": "MIT", + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-chord": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-chord/-/d3-chord-3.0.6.tgz", + "integrity": "sha512-LFYWWd8nwfwEmTZG9PfQxd17HbNPksHBiJHaKuY1XeqscXacsS2tyoo6OdRsjf+NQYeB6XrNL3a25E3gH69lcg==", + "license": "MIT" + }, + "node_modules/@types/d3-color": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz", + "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==", + "license": "MIT" + }, + "node_modules/@types/d3-contour": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-contour/-/d3-contour-3.0.6.tgz", + "integrity": "sha512-BjzLgXGnCWjUSYGfH1cpdo41/hgdWETu4YxpezoztawmqsvCeep+8QGfiY6YbDvfgHz/DkjeIkkZVJavB4a3rg==", + "license": "MIT", + "dependencies": { + "@types/d3-array": "*", + "@types/geojson": "*" + } + }, + "node_modules/@types/d3-delaunay": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-delaunay/-/d3-delaunay-6.0.4.tgz", + "integrity": "sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw==", + "license": "MIT" + }, + "node_modules/@types/d3-dispatch": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-dispatch/-/d3-dispatch-3.0.6.tgz", + "integrity": "sha512-4fvZhzMeeuBJYZXRXrRIQnvUYfyXwYmLsdiN7XXmVNQKKw1cM8a5WdID0g1hVFZDqT9ZqZEY5pD44p24VS7iZQ==", + "license": "MIT" + }, + "node_modules/@types/d3-drag": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-drag/-/d3-drag-3.0.7.tgz", + "integrity": "sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ==", + "license": "MIT", + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-dsv": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-dsv/-/d3-dsv-3.0.7.tgz", + "integrity": "sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g==", + "license": "MIT" + }, + "node_modules/@types/d3-ease": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz", + "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==", + "license": "MIT" + }, + "node_modules/@types/d3-fetch": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-fetch/-/d3-fetch-3.0.7.tgz", + "integrity": "sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA==", + "license": "MIT", + "dependencies": { + "@types/d3-dsv": "*" + } + }, + "node_modules/@types/d3-force": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@types/d3-force/-/d3-force-3.0.10.tgz", + "integrity": "sha512-ZYeSaCF3p73RdOKcjj+swRlZfnYpK1EbaDiYICEEp5Q6sUiqFaFQ9qgoshp5CzIyyb/yD09kD9o2zEltCexlgw==", + "license": "MIT" + }, + "node_modules/@types/d3-format": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-format/-/d3-format-3.0.4.tgz", + "integrity": "sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g==", + "license": "MIT" + }, + "node_modules/@types/d3-geo": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@types/d3-geo/-/d3-geo-3.1.0.tgz", + "integrity": "sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ==", + "license": "MIT", + "dependencies": { + "@types/geojson": "*" + } + }, + "node_modules/@types/d3-hierarchy": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@types/d3-hierarchy/-/d3-hierarchy-3.1.7.tgz", + "integrity": "sha512-tJFtNoYBtRtkNysX1Xq4sxtjK8YgoWUNpIiUee0/jHGRwqvzYxkq0hGVbbOGSz+JgFxxRu4K8nb3YpG3CMARtg==", + "license": "MIT" + }, + "node_modules/@types/d3-interpolate": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz", + "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==", + "license": "MIT", + "dependencies": { + "@types/d3-color": "*" + } + }, "node_modules/@types/d3-path": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-1.0.11.tgz", "integrity": "sha512-4pQMp8ldf7UaB/gR8Fvvy69psNHkTpD/pVw3vmEi8iZAB9EPMBruB1JvHO4BIq9QkUUd2lV1F5YXpMNj7JPBpw==", - "dev": true, + "license": "MIT" + }, + "node_modules/@types/d3-polygon": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-polygon/-/d3-polygon-3.0.2.tgz", + "integrity": "sha512-ZuWOtMaHCkN9xoeEMr1ubW2nGWsp4nIql+OPQRstu4ypeZ+zk3YKqQT0CXVe/PYqrKpZAi+J9mTs05TKwjXSRA==", + "license": "MIT" + }, + "node_modules/@types/d3-quadtree": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-quadtree/-/d3-quadtree-3.0.6.tgz", + "integrity": "sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg==", + "license": "MIT" + }, + "node_modules/@types/d3-random": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-random/-/d3-random-3.0.3.tgz", + "integrity": "sha512-Imagg1vJ3y76Y2ea0871wpabqp613+8/r0mCLEBfdtqC7xMSfj9idOnmBYyMoULfHePJyxMAw3nWhJxzc+LFwQ==", + "license": "MIT" + }, + "node_modules/@types/d3-scale": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.8.tgz", + "integrity": "sha512-gkK1VVTr5iNiYJ7vWDI+yUFFlszhNMtVeneJ6lUTKPjprsvLLI9/tgEGiXJOnlINJA8FyA88gfnQsHbybVZrYQ==", + "license": "MIT", + "dependencies": { + "@types/d3-time": "*" + } + }, + "node_modules/@types/d3-scale-chromatic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.0.3.tgz", + "integrity": "sha512-laXM4+1o5ImZv3RpFAsTRn3TEkzqkytiOY0Dz0sq5cnd1dtNlk6sHLon4OvqaiJb28T0S/TdsBI3Sjsy+keJrw==", + "license": "MIT" + }, + "node_modules/@types/d3-selection": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/@types/d3-selection/-/d3-selection-3.0.11.tgz", + "integrity": "sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w==", "license": "MIT" }, "node_modules/@types/d3-shape": { "version": "1.3.12", "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-1.3.12.tgz", "integrity": "sha512-8oMzcd4+poSLGgV0R1Q1rOlx/xdmozS4Xab7np0eamFFUYq71AU9pOCJEFnkXW2aI/oXdVYJzw6pssbSut7Z9Q==", - "dev": true, "license": "MIT", "dependencies": { "@types/d3-path": "^1" } }, + "node_modules/@types/d3-time": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.3.tgz", + "integrity": "sha512-2p6olUZ4w3s+07q3Tm2dbiMZy5pCDfYwtLXXHUnVzXgQlZ/OyPtUz6OL382BkOuGlLXqfT+wqv8Fw2v8/0geBw==", + "license": "MIT" + }, + "node_modules/@types/d3-time-format": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-time-format/-/d3-time-format-4.0.3.tgz", + "integrity": "sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg==", + "license": "MIT" + }, + "node_modules/@types/d3-timer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz", + "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==", + "license": "MIT" + }, + "node_modules/@types/d3-transition": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@types/d3-transition/-/d3-transition-3.0.9.tgz", + "integrity": "sha512-uZS5shfxzO3rGlu0cC3bjmMFKsXv+SmZZcgp0KD22ts4uGXp5EVYGzu/0YdwZeKmddhcAccYtREJKkPfXkZuCg==", + "license": "MIT", + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-zoom": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@types/d3-zoom/-/d3-zoom-3.0.8.tgz", + "integrity": "sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw==", + "license": "MIT", + "dependencies": { + "@types/d3-interpolate": "*", + "@types/d3-selection": "*" + } + }, + "node_modules/@types/dompurify": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/dompurify/-/dompurify-3.0.5.tgz", + "integrity": "sha512-1Wg0g3BtQF7sSb27fJQAKck1HECM6zV1EB66j8JH9i3LCjYabJa0FSdiSgsD5K/RbrsR0SiraKacLB+T8ZVYAg==", + "license": "MIT", + "dependencies": { + "@types/trusted-types": "*" + } + }, "node_modules/@types/estree": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", @@ -2294,6 +2539,12 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/geojson": { + "version": "7946.0.14", + "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.14.tgz", + "integrity": "sha512-WCfD5Ht3ZesJUsONdhvm84dmzWOiOzOAqOncN0++w0lBw1o8OuDNJF2McvvCef/yBqb/HYRahp1BYtODFQ8bRg==", + "license": "MIT" + }, "node_modules/@types/inflection": { "version": "1.13.2", "resolved": "https://registry.npmjs.org/@types/inflection/-/inflection-1.13.2.tgz", @@ -2392,6 +2643,12 @@ "@types/react": "*" } }, + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", + "license": "MIT" + }, "node_modules/@types/use-sync-external-store": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz", @@ -3719,12 +3976,12 @@ } }, "node_modules/dagre-d3-es": { - "version": "7.0.10", - "resolved": "https://registry.npmjs.org/dagre-d3-es/-/dagre-d3-es-7.0.10.tgz", - "integrity": "sha512-qTCQmEhcynucuaZgY5/+ti3X/rnszKZhEQH/ZdWdtP1tA/y3VoHJzcVrO9pjjJCNpigfscAtoUB5ONcd2wNn0A==", + "version": "7.0.11", + "resolved": "https://registry.npmjs.org/dagre-d3-es/-/dagre-d3-es-7.0.11.tgz", + "integrity": "sha512-tvlJLyQf834SylNKax8Wkzco/1ias1OPw8DcUMDE7oUIoSEW25riQVuiu/0OWEFqT0cxHT3Pa9/D82Jr47IONw==", "license": "MIT", "dependencies": { - "d3": "^7.8.2", + "d3": "^7.9.0", "lodash-es": "^4.17.21" } }, @@ -5810,20 +6067,22 @@ } }, "node_modules/mermaid": { - "version": "11.3.0", - "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-11.3.0.tgz", - "integrity": "sha512-fFmf2gRXLtlGzug4wpIGN+rQdZ30M8IZEB1D3eZkXNqC7puhqeURBcD/9tbwXsqBO+A6Nzzo3MSSepmnw5xSeg==", + "version": "11.4.0", + "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-11.4.0.tgz", + "integrity": "sha512-mxCfEYvADJqOiHfGpJXLs4/fAjHz448rH0pfY5fAoxiz70rQiDSzUUy4dNET2T08i46IVpjohPd6WWbzmRHiPA==", "license": "MIT", "dependencies": { "@braintree/sanitize-url": "^7.0.1", "@iconify/utils": "^2.1.32", "@mermaid-js/parser": "^0.3.0", + "@types/d3": "^7.4.3", + "@types/dompurify": "^3.0.5", "cytoscape": "^3.29.2", "cytoscape-cose-bilkent": "^4.1.0", "cytoscape-fcose": "^2.2.0", "d3": "^7.9.0", "d3-sankey": "^0.12.3", - "dagre-d3-es": "7.0.10", + "dagre-d3-es": "7.0.11", "dayjs": "^1.11.10", "dompurify": "^3.0.11 <3.1.7", "katex": "^0.16.9", diff --git a/frontend/package.json b/frontend/package.json index b18e9ac8c..c6a310a15 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -17,7 +17,7 @@ "axios": "1.7.7", "chart.js": "4.4.6", "markdown-to-jsx": "7.5.0", - "mermaid": "11.3.0", + "mermaid": "11.4.0", "oidc-client-ts": "3.1.0", "prop-types": "15.8.1", "query-string": "9.1.1", From 658ca5906c3d058709d91dfa2f46a2f2c02548ba Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 31 Oct 2024 08:08:28 +0100 Subject: [PATCH 03/34] chore(deps): update dependency @types/node to v22.8.5 (#2135) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- end_to_end_tests/package-lock.json | 8 ++++---- end_to_end_tests/package.json | 2 +- frontend/package-lock.json | 8 ++++---- frontend/package.json | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/end_to_end_tests/package-lock.json b/end_to_end_tests/package-lock.json index f7b26f15c..679c58d31 100644 --- a/end_to_end_tests/package-lock.json +++ b/end_to_end_tests/package-lock.json @@ -9,7 +9,7 @@ "version": "1.21.0", "devDependencies": { "@playwright/test": "1.48.2", - "@types/node": "22.8.4" + "@types/node": "22.8.5" } }, "node_modules/@playwright/test": { @@ -29,9 +29,9 @@ } }, "node_modules/@types/node": { - "version": "22.8.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.8.4.tgz", - "integrity": "sha512-SpNNxkftTJOPk0oN+y2bIqurEXHTA2AOZ3EJDDKeJ5VzkvvORSvmQXGQarcOzWV1ac7DCaPBEdMDxBsM+d8jWw==", + "version": "22.8.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.8.5.tgz", + "integrity": "sha512-5iYk6AMPtsMbkZqCO1UGF9W5L38twq11S2pYWkybGHH2ogPUvXWNlQqJBzuEZWKj/WRH+QTeiv6ySWqJtvIEgA==", "dev": true, "license": "MIT", "dependencies": { diff --git a/end_to_end_tests/package.json b/end_to_end_tests/package.json index b55b7e49b..d050f5514 100644 --- a/end_to_end_tests/package.json +++ b/end_to_end_tests/package.json @@ -9,6 +9,6 @@ "author": "", "devDependencies": { "@playwright/test": "1.48.2", - "@types/node": "22.8.4" + "@types/node": "22.8.5" } } diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 12802a271..49a0884f4 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -46,7 +46,7 @@ "@microsoft/eslint-formatter-sarif": "3.1.0", "@trivago/prettier-plugin-sort-imports": "4.3.0", "@types/inflection": "1.13.2", - "@types/node": "22.8.4", + "@types/node": "22.8.5", "@types/prop-types": "15.7.13", "@types/react": "18.3.12", "@types/react-dom": "18.3.1", @@ -2582,9 +2582,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.8.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.8.4.tgz", - "integrity": "sha512-SpNNxkftTJOPk0oN+y2bIqurEXHTA2AOZ3EJDDKeJ5VzkvvORSvmQXGQarcOzWV1ac7DCaPBEdMDxBsM+d8jWw==", + "version": "22.8.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.8.5.tgz", + "integrity": "sha512-5iYk6AMPtsMbkZqCO1UGF9W5L38twq11S2pYWkybGHH2ogPUvXWNlQqJBzuEZWKj/WRH+QTeiv6ySWqJtvIEgA==", "dev": true, "license": "MIT", "dependencies": { diff --git a/frontend/package.json b/frontend/package.json index c6a310a15..0dbbb42d2 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -55,7 +55,7 @@ "@microsoft/eslint-formatter-sarif": "3.1.0", "@trivago/prettier-plugin-sort-imports": "4.3.0", "@types/inflection": "1.13.2", - "@types/node": "22.8.4", + "@types/node": "22.8.5", "@types/prop-types": "15.7.13", "@types/react": "18.3.12", "@types/react-dom": "18.3.1", From 826048d18fbbfc7916bae80bfe031c225ff28ac8 Mon Sep 17 00:00:00 2001 From: Stefan Fleckenstein Date: Thu, 31 Oct 2024 07:37:20 +0000 Subject: [PATCH 04/34] fix: do not show empty license field in product header (#2136) --- frontend/src/core/products/ProductHeader.tsx | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/frontend/src/core/products/ProductHeader.tsx b/frontend/src/core/products/ProductHeader.tsx index b95d88cd8..2969907c5 100644 --- a/frontend/src/core/products/ProductHeader.tsx +++ b/frontend/src/core/products/ProductHeader.tsx @@ -50,11 +50,17 @@ const ProductHeader = () => { - {product && product.has_licenses && ( - - - - )} + {product && + product.forbidden_licenses_count + + product.review_required_licenses_count + + product.unknown_licenses_count + + product.allowed_licenses_count + + product.ignored_licenses_count > + 0 && ( + + + + )} From 97f2e3a4be3ff4c663a180034c58a40faca9edeb Mon Sep 17 00:00:00 2001 From: Stefan Fleckenstein Date: Thu, 31 Oct 2024 11:51:58 +0000 Subject: [PATCH 05/34] fix: correct dev_deps links per ecosystem (#2137) --- frontend/src/commons/functions.tsx | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/frontend/src/commons/functions.tsx b/frontend/src/commons/functions.tsx index d6a0a197d..f0c36fac8 100644 --- a/frontend/src/commons/functions.tsx +++ b/frontend/src/commons/functions.tsx @@ -119,21 +119,32 @@ export function get_component_purl_url( return null; } - const typeArray: string[] = ["cargo", "go", "maven", "npm", "nuget", "pypi"]; + const typeArray: string[] = ["cargo", "golang", "maven", "npm", "nuget", "pypi"]; if (!typeArray.includes(purl_type)) { return null; } - let component_purl_url = "https://deps.dev/" + purl_type + "/"; + let deps_dev_type = purl_type; + if (purl_type === "golang") { + deps_dev_type = "go"; + } + + let namespace_separator = "/"; + if (purl_type === "maven") { + namespace_separator = ":"; + } + + let component_purl_url = "https://deps.dev/" + deps_dev_type + "/"; if (!component_name.includes(":") && purl_namespace !== null) { - component_purl_url = component_purl_url + purl_namespace + "%2F"; + component_purl_url = + component_purl_url + encodeURIComponent(purl_namespace) + encodeURIComponent(namespace_separator); } - component_purl_url = component_purl_url + component_name; + component_purl_url = component_purl_url + encodeURIComponent(component_name); if (component_version !== null) { component_purl_url = component_purl_url + "/" + component_version; } - return encodeURI(component_purl_url); + return component_purl_url; } const rtf = new Intl.RelativeTimeFormat("en", { From 242cfa6a253303ec16b569294977d7979db48869 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 31 Oct 2024 20:10:19 +0100 Subject: [PATCH 06/34] chore(deps): update dependency mkdocs-material to v9.5.43 (#2138) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- mkdocs_requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mkdocs_requirements.txt b/mkdocs_requirements.txt index 4f80ee776..09ec947e1 100644 --- a/mkdocs_requirements.txt +++ b/mkdocs_requirements.txt @@ -1 +1 @@ -mkdocs-material==9.5.42 # https://github.com/squidfunk/mkdocs-material +mkdocs-material==9.5.43 # https://github.com/squidfunk/mkdocs-material From 6049140179e36e71ec6d9ef51809097d9ca4d445 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 31 Oct 2024 22:41:57 +0100 Subject: [PATCH 07/34] fix(deps): update react-admin monorepo to v5.3.2 (#2139) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- frontend/package-lock.json | 56 +++++++++++++++++++------------------- frontend/package.json | 8 +++--- 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 49a0884f4..f712f64f0 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -25,11 +25,11 @@ "oidc-client-ts": "3.1.0", "prop-types": "15.8.1", "query-string": "9.1.1", - "ra-i18n-polyglot": "5.3.1", - "ra-input-rich-text": "5.3.1", - "ra-language-english": "5.3.1", + "ra-i18n-polyglot": "5.3.2", + "ra-input-rich-text": "5.3.2", + "ra-language-english": "5.3.2", "react": "18.3.1", - "react-admin": "5.3.1", + "react-admin": "5.3.2", "react-chartjs-2": "5.2.0", "react-dom": "18.3.1", "react-hook-form": "7.53.1", @@ -6873,9 +6873,9 @@ "license": "MIT" }, "node_modules/ra-core": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/ra-core/-/ra-core-5.3.1.tgz", - "integrity": "sha512-1q/h71iOco6kA9kkGNEmChuw+JgUTr+Y6MLfb/N0VcF75xX+v5SjoNMgHee/Jtn6uObOVeWdhAhIJ/bFwHR5sg==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ra-core/-/ra-core-5.3.2.tgz", + "integrity": "sha512-JDZ44jMCTlAXWWdR8LLFXXjKIc6bNf4L/zjY9/iL9yP5Kcy4yNf4kTBzR46dNWpt5/3k4Z59cMKBf+A9fDjJAQ==", "license": "MIT", "dependencies": { "@tanstack/react-query": "^5.8.4", @@ -6943,19 +6943,19 @@ } }, "node_modules/ra-i18n-polyglot": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/ra-i18n-polyglot/-/ra-i18n-polyglot-5.3.1.tgz", - "integrity": "sha512-WcxTBWSYlLy20Hh72BhadyG/El5UHWaJQnglN7JK+M16EDR2Mp8R1kPGHFLtCAbjjMXUaKzZQ50AS51Ct1kVLQ==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ra-i18n-polyglot/-/ra-i18n-polyglot-5.3.2.tgz", + "integrity": "sha512-jyaDTPKyJOZlMnvLnrw7dqpD/ek01iVFg73FGoI3PAD/xYwKj4AfJBvwWlLVwlc6TOz9fcwd4hTWWVKbOMMFbA==", "license": "MIT", "dependencies": { "node-polyglot": "^2.2.2", - "ra-core": "^5.3.1" + "ra-core": "^5.3.2" } }, "node_modules/ra-input-rich-text": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/ra-input-rich-text/-/ra-input-rich-text-5.3.1.tgz", - "integrity": "sha512-+YDVg7fIYygU7hfiwX6lvhJkTcmC8Ox7nuCjPlzTz0R+lowto/naeb7vDCjH7WgL6P1R4HIqPW+2ZCxU/2+JvQ==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ra-input-rich-text/-/ra-input-rich-text-5.3.2.tgz", + "integrity": "sha512-J7SFLdyksRngNCr6KpIsX4mQ+43mHrqIfmiMWzy7V3vSU8CcpTuWZc2ueEHw4lu472+koLciytBI3f/QMPRKQA==", "license": "MIT", "dependencies": { "@tiptap/core": "^2.0.3", @@ -6982,18 +6982,18 @@ } }, "node_modules/ra-language-english": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/ra-language-english/-/ra-language-english-5.3.1.tgz", - "integrity": "sha512-ttEVhRI06VPA0MEFmCkxQNFa3C4ztGHG14vRnfRtpQ3qSF996genzoYCW/AdkI/JzskHU1zAw5o73qezSdqCuA==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ra-language-english/-/ra-language-english-5.3.2.tgz", + "integrity": "sha512-otfNWGAyRXuaEBYneYpNaNj96umOLQ+MVtWPJSHvHXq80nRL0y2tEy0RNDrdIayvF6Q9dRYs1Q7a+mV0tkNbAw==", "license": "MIT", "dependencies": { - "ra-core": "^5.3.1" + "ra-core": "^5.3.2" } }, "node_modules/ra-ui-materialui": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/ra-ui-materialui/-/ra-ui-materialui-5.3.1.tgz", - "integrity": "sha512-ViLAtCVsdAPrdT72K1W2a00UkZZI0FSw8YTsrPBPPjLfaH1MpjEAG2cwI9ODuPDe65/GkiM1W0husWV5JveLnw==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ra-ui-materialui/-/ra-ui-materialui-5.3.2.tgz", + "integrity": "sha512-jS+/7TFjbzyh4VMQk9f9nhFWs61IgTYejGvBAOckzDh/W6a8ZVE41z2ezVENG3KZzgJei8XkWsD7U9/2W0+Org==", "license": "MIT", "dependencies": { "@tanstack/react-query": "^5.8.4", @@ -7086,19 +7086,19 @@ } }, "node_modules/react-admin": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/react-admin/-/react-admin-5.3.1.tgz", - "integrity": "sha512-pxEccGTXwreI0EhPgssp0B8fWMk68fCmpHImjVZ8SJ//zXWncffwcbRwb7HbvkF56Zp3ivx9UIZ/vvuBCjN49g==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/react-admin/-/react-admin-5.3.2.tgz", + "integrity": "sha512-Wd9rAuMOx3shZOZwkqY0D/NXTOvVo7Qmw2vlz+wnDrvb5RDsLBos4yzE0MLozaRilizP6CCnvGtp+d0aXp4nVQ==", "license": "MIT", "dependencies": { "@emotion/react": "^11.4.1", "@emotion/styled": "^11.3.0", "@mui/icons-material": "^5.15.20", "@mui/material": "^5.15.20", - "ra-core": "^5.3.1", - "ra-i18n-polyglot": "^5.3.1", - "ra-language-english": "^5.3.1", - "ra-ui-materialui": "^5.3.1", + "ra-core": "^5.3.2", + "ra-i18n-polyglot": "^5.3.2", + "ra-language-english": "^5.3.2", + "ra-ui-materialui": "^5.3.2", "react-hook-form": "^7.53.0", "react-router": "^6.22.0", "react-router-dom": "^6.22.0" diff --git a/frontend/package.json b/frontend/package.json index 0dbbb42d2..e1406e007 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -21,11 +21,11 @@ "oidc-client-ts": "3.1.0", "prop-types": "15.8.1", "query-string": "9.1.1", - "ra-i18n-polyglot": "5.3.1", - "ra-input-rich-text": "5.3.1", - "ra-language-english": "5.3.1", + "ra-i18n-polyglot": "5.3.2", + "ra-input-rich-text": "5.3.2", + "ra-language-english": "5.3.2", "react": "18.3.1", - "react-admin": "5.3.1", + "react-admin": "5.3.2", "react-chartjs-2": "5.2.0", "react-dom": "18.3.1", "react-hook-form": "7.53.1", From 7bf2226b18659a1c7bf124566b73dc350d6d5071 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 1 Nov 2024 08:35:55 +0100 Subject: [PATCH 08/34] fix(deps): update dependency werkzeug to v3.1.0 (#2140) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- backend/poetry.lock | 10 +++++----- backend/pyproject.toml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/backend/poetry.lock b/backend/poetry.lock index 745e8dd68..5a396292b 100644 --- a/backend/poetry.lock +++ b/backend/poetry.lock @@ -2469,13 +2469,13 @@ files = [ [[package]] name = "werkzeug" -version = "3.0.6" +version = "3.1.0" description = "The comprehensive WSGI web application library." optional = true -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "werkzeug-3.0.6-py3-none-any.whl", hash = "sha256:1bc0c2310d2fbb07b1dd1105eba2f7af72f322e1e455f2f93c993bee8c8a5f17"}, - {file = "werkzeug-3.0.6.tar.gz", hash = "sha256:a8dd59d4de28ca70471a34cba79bed5f7ef2e036a76b3ab0835474246eb41f8d"}, + {file = "werkzeug-3.1.0-py3-none-any.whl", hash = "sha256:208a2e31a4a54c8b3d2244f2079ca1d3851629a7a7d546646059c64fb746023a"}, + {file = "werkzeug-3.1.0.tar.gz", hash = "sha256:6f2a0d38f25ba5a75c36c45b4ae350c7a23b57e3b974e9eb2d6851f2c648c00d"}, ] [package.dependencies] @@ -2506,4 +2506,4 @@ unittests = ["coverage", "django-coverage-plugin", "django-extensions"] [metadata] lock-version = "2.0" python-versions = ">= 3.10, < 3.13" -content-hash = "b72a7b820ebdc2d040ee1a40ef2c03275084ae5a689e27617d9b433af143ce13" +content-hash = "f2aeb1e48fff3a181bb317d0469499fa5b7b3fbfb0183c9010c3379efceb608d" diff --git a/backend/pyproject.toml b/backend/pyproject.toml index cbf2d4297..5412f144b 100644 --- a/backend/pyproject.toml +++ b/backend/pyproject.toml @@ -62,7 +62,7 @@ py-ocsf-models="0.1.1" # https://github.com/prowler-cloud/py-ocsf-models # Development dependencies # ------------------------------------------------------------------------------ # Werkzeug = { version = "3.0.4", extras = ["watchdog"], optional = true } # https://github.com/pallets/werkzeug -Werkzeug = { version = "3.0.6", optional = true } # https://github.com/pallets/werkzeug +Werkzeug = { version = "3.1.0", optional = true } # https://github.com/pallets/werkzeug ipdb = { version = "0.13.13", optional = true } # https://github.com/gotcha/ipdb # watchgod = { version = "0.8.2", optional = true } # https://github.com/samuelcolvin/watchgod django-extensions = { version = "3.2.3", optional = true } # https://github.com/django-extensions/django-extensions From c22d0b48297070058319fa695812974b449cdfc0 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 1 Nov 2024 08:40:28 +0100 Subject: [PATCH 09/34] chore(deps): update dependency @types/node to v22.8.6 (#2141) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- end_to_end_tests/package-lock.json | 8 ++++---- end_to_end_tests/package.json | 2 +- frontend/package-lock.json | 8 ++++---- frontend/package.json | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/end_to_end_tests/package-lock.json b/end_to_end_tests/package-lock.json index 679c58d31..95c1f12f0 100644 --- a/end_to_end_tests/package-lock.json +++ b/end_to_end_tests/package-lock.json @@ -9,7 +9,7 @@ "version": "1.21.0", "devDependencies": { "@playwright/test": "1.48.2", - "@types/node": "22.8.5" + "@types/node": "22.8.6" } }, "node_modules/@playwright/test": { @@ -29,9 +29,9 @@ } }, "node_modules/@types/node": { - "version": "22.8.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.8.5.tgz", - "integrity": "sha512-5iYk6AMPtsMbkZqCO1UGF9W5L38twq11S2pYWkybGHH2ogPUvXWNlQqJBzuEZWKj/WRH+QTeiv6ySWqJtvIEgA==", + "version": "22.8.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.8.6.tgz", + "integrity": "sha512-tosuJYKrIqjQIlVCM4PEGxOmyg3FCPa/fViuJChnGeEIhjA46oy8FMVoF9su1/v8PNs2a8Q0iFNyOx0uOF91nw==", "dev": true, "license": "MIT", "dependencies": { diff --git a/end_to_end_tests/package.json b/end_to_end_tests/package.json index d050f5514..b6f3cc75e 100644 --- a/end_to_end_tests/package.json +++ b/end_to_end_tests/package.json @@ -9,6 +9,6 @@ "author": "", "devDependencies": { "@playwright/test": "1.48.2", - "@types/node": "22.8.5" + "@types/node": "22.8.6" } } diff --git a/frontend/package-lock.json b/frontend/package-lock.json index f712f64f0..52c331081 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -46,7 +46,7 @@ "@microsoft/eslint-formatter-sarif": "3.1.0", "@trivago/prettier-plugin-sort-imports": "4.3.0", "@types/inflection": "1.13.2", - "@types/node": "22.8.5", + "@types/node": "22.8.6", "@types/prop-types": "15.7.13", "@types/react": "18.3.12", "@types/react-dom": "18.3.1", @@ -2582,9 +2582,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.8.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.8.5.tgz", - "integrity": "sha512-5iYk6AMPtsMbkZqCO1UGF9W5L38twq11S2pYWkybGHH2ogPUvXWNlQqJBzuEZWKj/WRH+QTeiv6ySWqJtvIEgA==", + "version": "22.8.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.8.6.tgz", + "integrity": "sha512-tosuJYKrIqjQIlVCM4PEGxOmyg3FCPa/fViuJChnGeEIhjA46oy8FMVoF9su1/v8PNs2a8Q0iFNyOx0uOF91nw==", "dev": true, "license": "MIT", "dependencies": { diff --git a/frontend/package.json b/frontend/package.json index e1406e007..a8345c5f1 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -55,7 +55,7 @@ "@microsoft/eslint-formatter-sarif": "3.1.0", "@trivago/prettier-plugin-sort-imports": "4.3.0", "@types/inflection": "1.13.2", - "@types/node": "22.8.5", + "@types/node": "22.8.6", "@types/prop-types": "15.7.13", "@types/react": "18.3.12", "@types/react-dom": "18.3.1", From 156cb2d698a7884747ca863ddc82d27218667f90 Mon Sep 17 00:00:00 2001 From: Stefan Fleckenstein Date: Fri, 1 Nov 2024 08:23:22 +0000 Subject: [PATCH 10/34] fix: encoded null value in description can cause SQL exception (#2142) * fix: encoded null value in description can cause SQL exception * chore: black --- backend/application/core/services/observation.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/backend/application/core/services/observation.py b/backend/application/core/services/observation.py index 98ee94e09..4696dc48b 100644 --- a/backend/application/core/services/observation.py +++ b/backend/application/core/services/observation.py @@ -175,6 +175,11 @@ def normalize_description(observation): while observation.description.endswith("\n"): observation.description = observation.description[:-1] + # \u0000 can lead to SQL exceptions + observation.description = observation.description.replace( + "\u0000", "REDACTED_NULL" + ) + def normalize_origin_component(observation): # pylint: disable=too-many-branches if not observation.origin_component_name_version: From a292d57fea07e665b7620cb91f81fa1b5bae2784 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 1 Nov 2024 18:19:59 +0100 Subject: [PATCH 11/34] chore(deps): update keycloak/keycloak docker tag to v26.0.5 (#2143) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- docker-compose-dev-keycloak.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose-dev-keycloak.yml b/docker-compose-dev-keycloak.yml index 6226f8169..d8095cadb 100644 --- a/docker-compose-dev-keycloak.yml +++ b/docker-compose-dev-keycloak.yml @@ -84,7 +84,7 @@ services: - "8025:8025" keycloak: - image: keycloak/keycloak:26.0.4 + image: keycloak/keycloak:26.0.5 environment: - KEYCLOAK_ADMIN=admin - KEYCLOAK_ADMIN_PASSWORD=admin From 5d8ff3dcaa582827dc65c30f92e15f96d634cd1b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 1 Nov 2024 19:13:45 +0100 Subject: [PATCH 12/34] fix(deps): update dependency cvss to v3.3 (#2144) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- backend/poetry.lock | 8 ++++---- backend/pyproject.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/backend/poetry.lock b/backend/poetry.lock index 5a396292b..b51e0ebca 100644 --- a/backend/poetry.lock +++ b/backend/poetry.lock @@ -536,13 +536,13 @@ test-randomorder = ["pytest-randomly"] [[package]] name = "cvss" -version = "3.2" +version = "3.3" description = "CVSS2/3/4 library with interactive calculator for Python 2 and Python 3" optional = false python-versions = "*" files = [ - {file = "cvss-3.2-py2.py3-none-any.whl", hash = "sha256:e2c2fbc8943c6df83d23c7ad74bb9c5e584c666a9455b013b598e292e5018469"}, - {file = "cvss-3.2.tar.gz", hash = "sha256:5e8e0f95e9e6c9dec0c2ef38f14153b2c019cfcd2fd6e75b5ad7da80a110fa8b"}, + {file = "cvss-3.3-py2.py3-none-any.whl", hash = "sha256:cc7326afc7585cc63d0a6ca74dab27d74aa2bc99f5f3d5d4bc4d94a3c22bc0a1"}, + {file = "cvss-3.3.tar.gz", hash = "sha256:ae097183ee58b02262ab2291d27857ca3d0a7c4242b9b076c6bf537e6239fbc0"}, ] [[package]] @@ -2506,4 +2506,4 @@ unittests = ["coverage", "django-coverage-plugin", "django-extensions"] [metadata] lock-version = "2.0" python-versions = ">= 3.10, < 3.13" -content-hash = "f2aeb1e48fff3a181bb317d0469499fa5b7b3fbfb0183c9010c3379efceb608d" +content-hash = "baed46becd0e77427916ee06cb55323bdb385726e198beaf90552de076834f2e" diff --git a/backend/pyproject.toml b/backend/pyproject.toml index 5412f144b..af38b1c22 100644 --- a/backend/pyproject.toml +++ b/backend/pyproject.toml @@ -55,7 +55,7 @@ jira = "3.8.0" # https://github.com/pycontribs/jira # ------------------------------------------------------------------------------ inflect = "7.4.0" # https://github.com/jaraco/inflect validators = "0.34.0" # https://github.com/python-validators/validators -cvss = "3.2" # https://github.com/RedHatProductSecurity/cvss +cvss = "3.3" # https://github.com/RedHatProductSecurity/cvss jsonpickle = "3.3.0" # https://github.com/jsonpickle/jsonpickle py-ocsf-models="0.1.1" # https://github.com/prowler-cloud/py-ocsf-models From f409b7743dedc05b10cab526c10dfc547973308d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 1 Nov 2024 19:21:57 +0100 Subject: [PATCH 13/34] fix(deps): update dependency werkzeug to v3.1.1 (#2146) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- backend/poetry.lock | 8 ++++---- backend/pyproject.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/backend/poetry.lock b/backend/poetry.lock index b51e0ebca..282dda24c 100644 --- a/backend/poetry.lock +++ b/backend/poetry.lock @@ -2469,13 +2469,13 @@ files = [ [[package]] name = "werkzeug" -version = "3.1.0" +version = "3.1.1" description = "The comprehensive WSGI web application library." optional = true python-versions = ">=3.9" files = [ - {file = "werkzeug-3.1.0-py3-none-any.whl", hash = "sha256:208a2e31a4a54c8b3d2244f2079ca1d3851629a7a7d546646059c64fb746023a"}, - {file = "werkzeug-3.1.0.tar.gz", hash = "sha256:6f2a0d38f25ba5a75c36c45b4ae350c7a23b57e3b974e9eb2d6851f2c648c00d"}, + {file = "werkzeug-3.1.1-py3-none-any.whl", hash = "sha256:a71124d1ef06008baafa3d266c02f56e1836a5984afd6dd6c9230669d60d9fb5"}, + {file = "werkzeug-3.1.1.tar.gz", hash = "sha256:8cd39dfbdfc1e051965f156163e2974e52c210f130810e9ad36858f0fd3edad4"}, ] [package.dependencies] @@ -2506,4 +2506,4 @@ unittests = ["coverage", "django-coverage-plugin", "django-extensions"] [metadata] lock-version = "2.0" python-versions = ">= 3.10, < 3.13" -content-hash = "baed46becd0e77427916ee06cb55323bdb385726e198beaf90552de076834f2e" +content-hash = "9ebc58eb7e5dd8974cd3144ed8d95ba4f952810292fc5d49e792ad991a8000f0" diff --git a/backend/pyproject.toml b/backend/pyproject.toml index af38b1c22..b7890a404 100644 --- a/backend/pyproject.toml +++ b/backend/pyproject.toml @@ -62,7 +62,7 @@ py-ocsf-models="0.1.1" # https://github.com/prowler-cloud/py-ocsf-models # Development dependencies # ------------------------------------------------------------------------------ # Werkzeug = { version = "3.0.4", extras = ["watchdog"], optional = true } # https://github.com/pallets/werkzeug -Werkzeug = { version = "3.1.0", optional = true } # https://github.com/pallets/werkzeug +Werkzeug = { version = "3.1.1", optional = true } # https://github.com/pallets/werkzeug ipdb = { version = "0.13.13", optional = true } # https://github.com/gotcha/ipdb # watchgod = { version = "0.8.2", optional = true } # https://github.com/samuelcolvin/watchgod django-extensions = { version = "3.2.3", optional = true } # https://github.com/django-extensions/django-extensions From 58838144d8ec468a24b6522f5145b772b0377151 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 1 Nov 2024 19:28:14 +0100 Subject: [PATCH 14/34] fix(deps): update dependency drf-spectacular-sidecar to v2024.11.1 (#2145) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- backend/poetry.lock | 8 ++++---- backend/pyproject.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/backend/poetry.lock b/backend/poetry.lock index 282dda24c..0eb0bfbe7 100644 --- a/backend/poetry.lock +++ b/backend/poetry.lock @@ -868,13 +868,13 @@ sidecar = ["drf-spectacular-sidecar"] [[package]] name = "drf-spectacular-sidecar" -version = "2024.7.1" +version = "2024.11.1" description = "Serve self-contained distribution builds of Swagger UI and Redoc with Django" optional = false python-versions = ">=3.6" files = [ - {file = "drf_spectacular_sidecar-2024.7.1-py3-none-any.whl", hash = "sha256:5dc8b38ad153e90b328152674c7959bf114bf86360a617a5a4516e135cb832bc"}, - {file = "drf_spectacular_sidecar-2024.7.1.tar.gz", hash = "sha256:beb992d6ece806a2d422ad626983e2472c0a5550de9647a7ed6764716a5abdfe"}, + {file = "drf_spectacular_sidecar-2024.11.1-py3-none-any.whl", hash = "sha256:e2efd49c5bd1a607fd5d120d9da58d78e587852db8220b8880282a849296ff83"}, + {file = "drf_spectacular_sidecar-2024.11.1.tar.gz", hash = "sha256:fcfccc72cbdbe41e93f8416fa0c712d14126b8d1629e65c09c07c8edea24aad0"}, ] [package.dependencies] @@ -2506,4 +2506,4 @@ unittests = ["coverage", "django-coverage-plugin", "django-extensions"] [metadata] lock-version = "2.0" python-versions = ">= 3.10, < 3.13" -content-hash = "9ebc58eb7e5dd8974cd3144ed8d95ba4f952810292fc5d49e792ad991a8000f0" +content-hash = "752a4bb0f9edf433315e2765ca4199976b7d8b79cf59cb707c58a39502266d36" diff --git a/backend/pyproject.toml b/backend/pyproject.toml index b7890a404..127a7ddc9 100644 --- a/backend/pyproject.toml +++ b/backend/pyproject.toml @@ -27,7 +27,7 @@ django-cors-headers = "4.6.0" # https://github.com/adamchainz/django-cors-header # OpenAPI 3 # ------------------------------------------------------------------------------ drf-spectacular = "0.27.2" # https://github.com/tfranzel/drf-spectacular -drf-spectacular-sidecar = "2024.7.1" # https://github.com/tfranzel/drf-spectacular-sidecar +drf-spectacular-sidecar = "2024.11.1" # https://github.com/tfranzel/drf-spectacular-sidecar # Token authentication # ------------------------------------------------------------------------------ PyJWT = "2.9.0" # https://github.com/jpadilla/pyjwt From be8fe1ca334b5467d5e19d3d58b6df9260c7bc09 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 2 Nov 2024 06:16:24 +0100 Subject: [PATCH 15/34] chore(deps): update eslint monorepo to v9.14.0 (#2147) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- frontend/package-lock.json | 86 ++++++++++++++++++++++---------------- frontend/package.json | 4 +- 2 files changed, 52 insertions(+), 38 deletions(-) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 52c331081..66ba7ecc3 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -42,7 +42,7 @@ "devDependencies": { "@eslint/compat": "1.2.2", "@eslint/eslintrc": "3.1.0", - "@eslint/js": "9.13.0", + "@eslint/js": "9.14.0", "@microsoft/eslint-formatter-sarif": "3.1.0", "@trivago/prettier-plugin-sort-imports": "4.3.0", "@types/inflection": "1.13.2", @@ -54,7 +54,7 @@ "@typescript-eslint/eslint-plugin": "8.12.2", "@typescript-eslint/parser": "8.12.2", "@vitejs/plugin-react": "4.3.3", - "eslint": "9.13.0", + "eslint": "9.14.0", "eslint-plugin-react": "7.37.2", "eslint-plugin-react-hooks": "rc", "eslint-plugin-security": "3.0.1", @@ -793,9 +793,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.13.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.13.0.tgz", - "integrity": "sha512-IFLyoY4d72Z5y/6o/BazFBezupzI/taV8sGumxTAVw3lXG9A6md1Dc34T9s1FoD/an9pJH8RHbAxsaEbBed9lA==", + "version": "9.14.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.14.0.tgz", + "integrity": "sha512-pFoEtFWCPyDOl+C6Ift+wC7Ro89otjigCf5vcuWqWgqNSQbRrpjSvdeE6ofLz4dHmyxD5f7gIdGT4+p36L6Twg==", "dev": true, "license": "MIT", "engines": { @@ -884,9 +884,9 @@ } }, "node_modules/@humanfs/core": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.0.tgz", - "integrity": "sha512-2cbWIHbZVEweE853g8jymffCA+NCMiuqeECeBBLm8dg2oFdjuGJhgN4UAbI+6v0CKbbhvtXA4qV8YR5Ji86nmw==", + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -894,13 +894,13 @@ } }, "node_modules/@humanfs/node": { - "version": "0.16.5", - "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.5.tgz", - "integrity": "sha512-KSPA4umqSG4LHYRodq31VDwKAvaTF4xmVlzM8Aeh4PlU1JQ3IG0wiA8C25d3RQ9nJyM3mBHyI53K06VVL/oFFg==", + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", + "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@humanfs/core": "^0.19.0", + "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.3.0" }, "engines": { @@ -4427,22 +4427,22 @@ } }, "node_modules/eslint": { - "version": "9.13.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.13.0.tgz", - "integrity": "sha512-EYZK6SX6zjFHST/HRytOdA/zE72Cq/bfw45LSyuwrdvcclb/gqV8RRQxywOBEWO2+WDpva6UZa4CcDeJKzUCFA==", + "version": "9.14.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.14.0.tgz", + "integrity": "sha512-c2FHsVBr87lnUtjP4Yhvk4yEhKrQavGafRA/Se1ouse8PfbfC/Qh9Mxa00yWsZRlqeUB9raXip0aiiUZkgnr9g==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.11.0", + "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.18.0", "@eslint/core": "^0.7.0", "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.13.0", + "@eslint/js": "9.14.0", "@eslint/plugin-kit": "^0.2.0", - "@humanfs/node": "^0.16.5", + "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.3.1", + "@humanwhocodes/retry": "^0.4.0", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", @@ -4450,9 +4450,9 @@ "cross-spawn": "^7.0.2", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.1.0", - "eslint-visitor-keys": "^4.1.0", - "espree": "^10.2.0", + "eslint-scope": "^8.2.0", + "eslint-visitor-keys": "^4.2.0", + "espree": "^10.3.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -4578,9 +4578,9 @@ } }, "node_modules/eslint-scope": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.1.0.tgz", - "integrity": "sha512-14dSvlhaVhKKsa9Fx1l8A17s7ah7Ef7wCakJ10LYk6+GYmP9yDti2oq2SEwcyndt6knfcZyhyxwY3i9yL78EQw==", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz", + "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -4607,10 +4607,24 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint/node_modules/@humanwhocodes/retry": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.0.tgz", + "integrity": "sha512-xnRgu9DxZbkWak/te3fcytNyp8MTbuiZIaueg2rgEvBuN55n04nwLYLU9TX/VVlusc9L2ZNXi99nUFNkHXtr5g==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, "node_modules/eslint/node_modules/eslint-visitor-keys": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.1.0.tgz", - "integrity": "sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", "dev": true, "license": "Apache-2.0", "engines": { @@ -4621,15 +4635,15 @@ } }, "node_modules/espree": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.2.0.tgz", - "integrity": "sha512-upbkBJbckcCNBDBDXEbuhjbP68n+scUd3k/U2EkyM9nw+I/jPiL4cLF/Al06CF96wRltFda16sxDFrxsI1v0/g==", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", + "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "acorn": "^8.12.0", + "acorn": "^8.14.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.1.0" + "eslint-visitor-keys": "^4.2.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4639,9 +4653,9 @@ } }, "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.1.0.tgz", - "integrity": "sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", "dev": true, "license": "Apache-2.0", "engines": { diff --git a/frontend/package.json b/frontend/package.json index a8345c5f1..d781a7e27 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -51,7 +51,7 @@ "devDependencies": { "@eslint/compat": "1.2.2", "@eslint/eslintrc": "3.1.0", - "@eslint/js": "9.13.0", + "@eslint/js": "9.14.0", "@microsoft/eslint-formatter-sarif": "3.1.0", "@trivago/prettier-plugin-sort-imports": "4.3.0", "@types/inflection": "1.13.2", @@ -63,7 +63,7 @@ "@typescript-eslint/eslint-plugin": "8.12.2", "@typescript-eslint/parser": "8.12.2", "@vitejs/plugin-react": "4.3.3", - "eslint": "9.13.0", + "eslint": "9.14.0", "eslint-plugin-react": "7.37.2", "eslint-plugin-react-hooks": "rc", "eslint-plugin-security": "3.0.1", From f09c62ba5d4a5b53a84cac98b73a7089eb29e7fc Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 3 Nov 2024 08:59:48 +0100 Subject: [PATCH 16/34] fix(deps): update dependency types-pymysql to v1.1.0.20241103 (#2148) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- backend/poetry.lock | 8 ++++---- backend/pyproject.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/backend/poetry.lock b/backend/poetry.lock index 0eb0bfbe7..db5d26cc3 100644 --- a/backend/poetry.lock +++ b/backend/poetry.lock @@ -2338,13 +2338,13 @@ test = ["coverage[toml] (>=7)", "mypy (>=1.2.0)", "pytest (>=7)"] [[package]] name = "types-pymysql" -version = "1.1.0.20240524" +version = "1.1.0.20241103" description = "Typing stubs for PyMySQL" optional = true python-versions = ">=3.8" files = [ - {file = "types-PyMySQL-1.1.0.20240524.tar.gz", hash = "sha256:93058fef2077c407e29bdcd1a7dfbbf06a59324a5440df30dd002f572199ac17"}, - {file = "types_PyMySQL-1.1.0.20240524-py3-none-any.whl", hash = "sha256:8be5be228bf6376f9055ec03bec0dfa6f1a84163f9a89305db446f0b31f87be3"}, + {file = "types-PyMySQL-1.1.0.20241103.tar.gz", hash = "sha256:a7628542919a0ba87625fb79eefb2a2de45fb4ad32afe6e561e8f2f27fb58b8c"}, + {file = "types_PyMySQL-1.1.0.20241103-py3-none-any.whl", hash = "sha256:1a32efd8a74b5bf74c4de92a86c1cc6edaf3802dcfd5546635ab501eb5e3c096"}, ] [[package]] @@ -2506,4 +2506,4 @@ unittests = ["coverage", "django-coverage-plugin", "django-extensions"] [metadata] lock-version = "2.0" python-versions = ">= 3.10, < 3.13" -content-hash = "752a4bb0f9edf433315e2765ca4199976b7d8b79cf59cb707c58a39502266d36" +content-hash = "e7fa620c397e4b09c334238e8543f9a1eb903dd067297ec4b3351f9cc41d9226" diff --git a/backend/pyproject.toml b/backend/pyproject.toml index 127a7ddc9..245e6c26f 100644 --- a/backend/pyproject.toml +++ b/backend/pyproject.toml @@ -83,7 +83,7 @@ pre-commit = { version = "4.0.1", optional = true } # https://github.com/pre-co mypy = { version = "1.13.0", optional = true } # https://github.com/python/mypy django-stubs = { version = "5.1.1", optional = true } # https://github.com/typeddjango/django-stubs djangorestframework-stubs = { version = "3.15.1", optional = true } # https://github.com/typeddjango/djangorestframework-stubs -types-PyMySQL = { version = "1.1.0.20240524", optional = true } # https://github.com/python/typeshed +types-PyMySQL = { version = "1.1.0.20241103", optional = true } # https://github.com/python/typeshed # import-linter = "2.0" # https://github.com/seddonym/import-linter --> Cannot be build with Docker [tool.poetry.extras] From 928b0a16e206c9af285dc42b5a0ef7255d01faf6 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 3 Nov 2024 09:18:34 +0100 Subject: [PATCH 17/34] chore(deps): update dependency @types/node to v22.8.7 (#2149) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- end_to_end_tests/package-lock.json | 8 ++++---- end_to_end_tests/package.json | 2 +- frontend/package-lock.json | 8 ++++---- frontend/package.json | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/end_to_end_tests/package-lock.json b/end_to_end_tests/package-lock.json index 95c1f12f0..7ab54e743 100644 --- a/end_to_end_tests/package-lock.json +++ b/end_to_end_tests/package-lock.json @@ -9,7 +9,7 @@ "version": "1.21.0", "devDependencies": { "@playwright/test": "1.48.2", - "@types/node": "22.8.6" + "@types/node": "22.8.7" } }, "node_modules/@playwright/test": { @@ -29,9 +29,9 @@ } }, "node_modules/@types/node": { - "version": "22.8.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.8.6.tgz", - "integrity": "sha512-tosuJYKrIqjQIlVCM4PEGxOmyg3FCPa/fViuJChnGeEIhjA46oy8FMVoF9su1/v8PNs2a8Q0iFNyOx0uOF91nw==", + "version": "22.8.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.8.7.tgz", + "integrity": "sha512-LidcG+2UeYIWcMuMUpBKOnryBWG/rnmOHQR5apjn8myTQcx3rinFRn7DcIFhMnS0PPFSC6OafdIKEad0lj6U0Q==", "dev": true, "license": "MIT", "dependencies": { diff --git a/end_to_end_tests/package.json b/end_to_end_tests/package.json index b6f3cc75e..5fe6b4bd3 100644 --- a/end_to_end_tests/package.json +++ b/end_to_end_tests/package.json @@ -9,6 +9,6 @@ "author": "", "devDependencies": { "@playwright/test": "1.48.2", - "@types/node": "22.8.6" + "@types/node": "22.8.7" } } diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 66ba7ecc3..1efbe4f70 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -46,7 +46,7 @@ "@microsoft/eslint-formatter-sarif": "3.1.0", "@trivago/prettier-plugin-sort-imports": "4.3.0", "@types/inflection": "1.13.2", - "@types/node": "22.8.6", + "@types/node": "22.8.7", "@types/prop-types": "15.7.13", "@types/react": "18.3.12", "@types/react-dom": "18.3.1", @@ -2582,9 +2582,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.8.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.8.6.tgz", - "integrity": "sha512-tosuJYKrIqjQIlVCM4PEGxOmyg3FCPa/fViuJChnGeEIhjA46oy8FMVoF9su1/v8PNs2a8Q0iFNyOx0uOF91nw==", + "version": "22.8.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.8.7.tgz", + "integrity": "sha512-LidcG+2UeYIWcMuMUpBKOnryBWG/rnmOHQR5apjn8myTQcx3rinFRn7DcIFhMnS0PPFSC6OafdIKEad0lj6U0Q==", "dev": true, "license": "MIT", "dependencies": { diff --git a/frontend/package.json b/frontend/package.json index d781a7e27..c17aead59 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -55,7 +55,7 @@ "@microsoft/eslint-formatter-sarif": "3.1.0", "@trivago/prettier-plugin-sort-imports": "4.3.0", "@types/inflection": "1.13.2", - "@types/node": "22.8.6", + "@types/node": "22.8.7", "@types/prop-types": "15.7.13", "@types/react": "18.3.12", "@types/react-dom": "18.3.1", From 13c040e5123a8f0f94363333ec81f4c2078ce7eb Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 4 Nov 2024 18:46:51 +0000 Subject: [PATCH 18/34] chore(deps): update dependency globals to v15.12.0 (#2151) --- frontend/package-lock.json | 8 ++++---- frontend/package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 1efbe4f70..6bac94d99 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -58,7 +58,7 @@ "eslint-plugin-react": "7.37.2", "eslint-plugin-react-hooks": "rc", "eslint-plugin-security": "3.0.1", - "globals": "15.11.0", + "globals": "15.12.0", "prettier": "3.3.3", "rewire": "7.0.0", "typescript": "5.6.3", @@ -5052,9 +5052,9 @@ } }, "node_modules/globals": { - "version": "15.11.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-15.11.0.tgz", - "integrity": "sha512-yeyNSjdbyVaWurlwCpcA6XNBrHTMIeDdj0/hnvX/OLJ9ekOXYbLsLinH/MucQyGvNnXhidTdNhTtJaffL2sMfw==", + "version": "15.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.12.0.tgz", + "integrity": "sha512-1+gLErljJFhbOVyaetcwJiJ4+eLe45S2E7P5UiZ9xGfeq3ATQf5DOv9G7MH3gGbKQLkzmNh2DxfZwLdw+j6oTQ==", "dev": true, "license": "MIT", "engines": { diff --git a/frontend/package.json b/frontend/package.json index c17aead59..5c0d1541a 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -67,7 +67,7 @@ "eslint-plugin-react": "7.37.2", "eslint-plugin-react-hooks": "rc", "eslint-plugin-security": "3.0.1", - "globals": "15.11.0", + "globals": "15.12.0", "prettier": "3.3.3", "rewire": "7.0.0", "typescript": "5.6.3", From 13994a2f90d90e20fccb636ab9076d08d802ef92 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 4 Nov 2024 19:05:56 +0000 Subject: [PATCH 19/34] fix(deps): update dependency werkzeug to v3.1.2 (#2152) --- backend/poetry.lock | 8 ++++---- backend/pyproject.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/backend/poetry.lock b/backend/poetry.lock index db5d26cc3..1c472cd66 100644 --- a/backend/poetry.lock +++ b/backend/poetry.lock @@ -2469,13 +2469,13 @@ files = [ [[package]] name = "werkzeug" -version = "3.1.1" +version = "3.1.2" description = "The comprehensive WSGI web application library." optional = true python-versions = ">=3.9" files = [ - {file = "werkzeug-3.1.1-py3-none-any.whl", hash = "sha256:a71124d1ef06008baafa3d266c02f56e1836a5984afd6dd6c9230669d60d9fb5"}, - {file = "werkzeug-3.1.1.tar.gz", hash = "sha256:8cd39dfbdfc1e051965f156163e2974e52c210f130810e9ad36858f0fd3edad4"}, + {file = "werkzeug-3.1.2-py3-none-any.whl", hash = "sha256:4f7d1a5de312c810a8a2c6f0b47e9f6a7cffb7c8322def35e4d4d9841ff85597"}, + {file = "werkzeug-3.1.2.tar.gz", hash = "sha256:f471a4cd167233077e9d2a8190c3471c5bc520c636a9e3c1e9300c33bced03bc"}, ] [package.dependencies] @@ -2506,4 +2506,4 @@ unittests = ["coverage", "django-coverage-plugin", "django-extensions"] [metadata] lock-version = "2.0" python-versions = ">= 3.10, < 3.13" -content-hash = "e7fa620c397e4b09c334238e8543f9a1eb903dd067297ec4b3351f9cc41d9226" +content-hash = "9f70241f31f537423de62b8ac1b80009aad008c04e6afc150e0b877994122d85" diff --git a/backend/pyproject.toml b/backend/pyproject.toml index 245e6c26f..6009389d0 100644 --- a/backend/pyproject.toml +++ b/backend/pyproject.toml @@ -62,7 +62,7 @@ py-ocsf-models="0.1.1" # https://github.com/prowler-cloud/py-ocsf-models # Development dependencies # ------------------------------------------------------------------------------ # Werkzeug = { version = "3.0.4", extras = ["watchdog"], optional = true } # https://github.com/pallets/werkzeug -Werkzeug = { version = "3.1.1", optional = true } # https://github.com/pallets/werkzeug +Werkzeug = { version = "3.1.2", optional = true } # https://github.com/pallets/werkzeug ipdb = { version = "0.13.13", optional = true } # https://github.com/gotcha/ipdb # watchgod = { version = "0.8.2", optional = true } # https://github.com/samuelcolvin/watchgod django-extensions = { version = "3.2.3", optional = true } # https://github.com/django-extensions/django-extensions From cae4ac1a36cdf7e093c8b350bd9a823db6646eb3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 5 Nov 2024 05:30:39 +0000 Subject: [PATCH 20/34] chore(deps): update typescript-eslint monorepo to v8.13.0 (#2153) --- frontend/package-lock.json | 88 +++++++++++++++++++------------------- frontend/package.json | 4 +- 2 files changed, 46 insertions(+), 46 deletions(-) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 6bac94d99..5cabffab2 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -51,8 +51,8 @@ "@types/react": "18.3.12", "@types/react-dom": "18.3.1", "@types/recharts": "1.8.29", - "@typescript-eslint/eslint-plugin": "8.12.2", - "@typescript-eslint/parser": "8.12.2", + "@typescript-eslint/eslint-plugin": "8.13.0", + "@typescript-eslint/parser": "8.13.0", "@vitejs/plugin-react": "4.3.3", "eslint": "9.14.0", "eslint-plugin-react": "7.37.2", @@ -2656,17 +2656,17 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.12.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.12.2.tgz", - "integrity": "sha512-gQxbxM8mcxBwaEmWdtLCIGLfixBMHhQjBqR8sVWNTPpcj45WlYL2IObS/DNMLH1DBP0n8qz+aiiLTGfopPEebw==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.13.0.tgz", + "integrity": "sha512-nQtBLiZYMUPkclSeC3id+x4uVd1SGtHuElTxL++SfP47jR0zfkZBJHc+gL4qPsgTuypz0k8Y2GheaDYn6Gy3rg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.12.2", - "@typescript-eslint/type-utils": "8.12.2", - "@typescript-eslint/utils": "8.12.2", - "@typescript-eslint/visitor-keys": "8.12.2", + "@typescript-eslint/scope-manager": "8.13.0", + "@typescript-eslint/type-utils": "8.13.0", + "@typescript-eslint/utils": "8.13.0", + "@typescript-eslint/visitor-keys": "8.13.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -2690,16 +2690,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.12.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.12.2.tgz", - "integrity": "sha512-MrvlXNfGPLH3Z+r7Tk+Z5moZAc0dzdVjTgUgwsdGweH7lydysQsnSww3nAmsq8blFuRD5VRlAr9YdEFw3e6PBw==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.13.0.tgz", + "integrity": "sha512-w0xp+xGg8u/nONcGw1UXAr6cjCPU1w0XVyBs6Zqaj5eLmxkKQAByTdV/uGgNN5tVvN/kKpoQlP2cL7R+ajZZIQ==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/scope-manager": "8.12.2", - "@typescript-eslint/types": "8.12.2", - "@typescript-eslint/typescript-estree": "8.12.2", - "@typescript-eslint/visitor-keys": "8.12.2", + "@typescript-eslint/scope-manager": "8.13.0", + "@typescript-eslint/types": "8.13.0", + "@typescript-eslint/typescript-estree": "8.13.0", + "@typescript-eslint/visitor-keys": "8.13.0", "debug": "^4.3.4" }, "engines": { @@ -2719,14 +2719,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.12.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.12.2.tgz", - "integrity": "sha512-gPLpLtrj9aMHOvxJkSbDBmbRuYdtiEbnvO25bCMza3DhMjTQw0u7Y1M+YR5JPbMsXXnSPuCf5hfq0nEkQDL/JQ==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.13.0.tgz", + "integrity": "sha512-XsGWww0odcUT0gJoBZ1DeulY1+jkaHUciUq4jKNv4cpInbvvrtDoyBH9rE/n2V29wQJPk8iCH1wipra9BhmiMA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.12.2", - "@typescript-eslint/visitor-keys": "8.12.2" + "@typescript-eslint/types": "8.13.0", + "@typescript-eslint/visitor-keys": "8.13.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2737,14 +2737,14 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.12.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.12.2.tgz", - "integrity": "sha512-bwuU4TAogPI+1q/IJSKuD4shBLc/d2vGcRT588q+jzayQyjVK2X6v/fbR4InY2U2sgf8MEvVCqEWUzYzgBNcGQ==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.13.0.tgz", + "integrity": "sha512-Rqnn6xXTR316fP4D2pohZenJnp+NwQ1mo7/JM+J1LWZENSLkJI8ID8QNtlvFeb0HnFSK94D6q0cnMX6SbE5/vA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.12.2", - "@typescript-eslint/utils": "8.12.2", + "@typescript-eslint/typescript-estree": "8.13.0", + "@typescript-eslint/utils": "8.13.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -2762,9 +2762,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.12.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.12.2.tgz", - "integrity": "sha512-VwDwMF1SZ7wPBUZwmMdnDJ6sIFk4K4s+ALKLP6aIQsISkPv8jhiw65sAK6SuWODN/ix+m+HgbYDkH+zLjrzvOA==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.13.0.tgz", + "integrity": "sha512-4cyFErJetFLckcThRUFdReWJjVsPCqyBlJTi6IDEpc1GWCIIZRFxVppjWLIMcQhNGhdWJJRYFHpHoDWvMlDzng==", "dev": true, "license": "MIT", "engines": { @@ -2776,14 +2776,14 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.12.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.12.2.tgz", - "integrity": "sha512-mME5MDwGe30Pq9zKPvyduyU86PH7aixwqYR2grTglAdB+AN8xXQ1vFGpYaUSJ5o5P/5znsSBeNcs5g5/2aQwow==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.13.0.tgz", + "integrity": "sha512-v7SCIGmVsRK2Cy/LTLGN22uea6SaUIlpBcO/gnMGT/7zPtxp90bphcGf4fyrCQl3ZtiBKqVTG32hb668oIYy1g==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/types": "8.12.2", - "@typescript-eslint/visitor-keys": "8.12.2", + "@typescript-eslint/types": "8.13.0", + "@typescript-eslint/visitor-keys": "8.13.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -2831,16 +2831,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.12.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.12.2.tgz", - "integrity": "sha512-UTTuDIX3fkfAz6iSVa5rTuSfWIYZ6ATtEocQ/umkRSyC9O919lbZ8dcH7mysshrCdrAM03skJOEYaBugxN+M6A==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.13.0.tgz", + "integrity": "sha512-A1EeYOND6Uv250nybnLZapeXpYMl8tkzYUxqmoKAWnI4sei3ihf2XdZVd+vVOmHGcp3t+P7yRrNsyyiXTvShFQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.12.2", - "@typescript-eslint/types": "8.12.2", - "@typescript-eslint/typescript-estree": "8.12.2" + "@typescript-eslint/scope-manager": "8.13.0", + "@typescript-eslint/types": "8.13.0", + "@typescript-eslint/typescript-estree": "8.13.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2854,13 +2854,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.12.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.12.2.tgz", - "integrity": "sha512-PChz8UaKQAVNHghsHcPyx1OMHoFRUEA7rJSK/mDhdq85bk+PLsUHUBqTQTFt18VJZbmxBovM65fezlheQRsSDA==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.13.0.tgz", + "integrity": "sha512-7N/+lztJqH4Mrf0lb10R/CbI1EaAMMGyF5y0oJvFoAhafwgiRA7TXyd8TFn8FC8k5y2dTsYogg238qavRGNnlw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.12.2", + "@typescript-eslint/types": "8.13.0", "eslint-visitor-keys": "^3.4.3" }, "engines": { diff --git a/frontend/package.json b/frontend/package.json index 5c0d1541a..360b82bff 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -60,8 +60,8 @@ "@types/react": "18.3.12", "@types/react-dom": "18.3.1", "@types/recharts": "1.8.29", - "@typescript-eslint/eslint-plugin": "8.12.2", - "@typescript-eslint/parser": "8.12.2", + "@typescript-eslint/eslint-plugin": "8.13.0", + "@typescript-eslint/parser": "8.13.0", "@vitejs/plugin-react": "4.3.3", "eslint": "9.14.0", "eslint-plugin-react": "7.37.2", From c7342d8b2773415839c96b1f0cc394bf2eed1c6f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 5 Nov 2024 05:36:11 +0000 Subject: [PATCH 21/34] chore(deps): update dependency @types/node to v22.9.0 (#2154) --- end_to_end_tests/package-lock.json | 8 ++++---- end_to_end_tests/package.json | 2 +- frontend/package-lock.json | 8 ++++---- frontend/package.json | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/end_to_end_tests/package-lock.json b/end_to_end_tests/package-lock.json index 7ab54e743..8319a6531 100644 --- a/end_to_end_tests/package-lock.json +++ b/end_to_end_tests/package-lock.json @@ -9,7 +9,7 @@ "version": "1.21.0", "devDependencies": { "@playwright/test": "1.48.2", - "@types/node": "22.8.7" + "@types/node": "22.9.0" } }, "node_modules/@playwright/test": { @@ -29,9 +29,9 @@ } }, "node_modules/@types/node": { - "version": "22.8.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.8.7.tgz", - "integrity": "sha512-LidcG+2UeYIWcMuMUpBKOnryBWG/rnmOHQR5apjn8myTQcx3rinFRn7DcIFhMnS0PPFSC6OafdIKEad0lj6U0Q==", + "version": "22.9.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.9.0.tgz", + "integrity": "sha512-vuyHg81vvWA1Z1ELfvLko2c8f34gyA0zaic0+Rllc5lbCnbSyuvb2Oxpm6TAUAC/2xZN3QGqxBNggD1nNR2AfQ==", "dev": true, "license": "MIT", "dependencies": { diff --git a/end_to_end_tests/package.json b/end_to_end_tests/package.json index 5fe6b4bd3..70cb04196 100644 --- a/end_to_end_tests/package.json +++ b/end_to_end_tests/package.json @@ -9,6 +9,6 @@ "author": "", "devDependencies": { "@playwright/test": "1.48.2", - "@types/node": "22.8.7" + "@types/node": "22.9.0" } } diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 5cabffab2..961d8aeda 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -46,7 +46,7 @@ "@microsoft/eslint-formatter-sarif": "3.1.0", "@trivago/prettier-plugin-sort-imports": "4.3.0", "@types/inflection": "1.13.2", - "@types/node": "22.8.7", + "@types/node": "22.9.0", "@types/prop-types": "15.7.13", "@types/react": "18.3.12", "@types/react-dom": "18.3.1", @@ -2582,9 +2582,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.8.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.8.7.tgz", - "integrity": "sha512-LidcG+2UeYIWcMuMUpBKOnryBWG/rnmOHQR5apjn8myTQcx3rinFRn7DcIFhMnS0PPFSC6OafdIKEad0lj6U0Q==", + "version": "22.9.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.9.0.tgz", + "integrity": "sha512-vuyHg81vvWA1Z1ELfvLko2c8f34gyA0zaic0+Rllc5lbCnbSyuvb2Oxpm6TAUAC/2xZN3QGqxBNggD1nNR2AfQ==", "dev": true, "license": "MIT", "dependencies": { diff --git a/frontend/package.json b/frontend/package.json index 360b82bff..f662f9515 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -55,7 +55,7 @@ "@microsoft/eslint-formatter-sarif": "3.1.0", "@trivago/prettier-plugin-sort-imports": "4.3.0", "@types/inflection": "1.13.2", - "@types/node": "22.8.7", + "@types/node": "22.9.0", "@types/prop-types": "15.7.13", "@types/react": "18.3.12", "@types/react-dom": "18.3.1", From de930565e186e559d45ea1b36ffe97382ae47dee Mon Sep 17 00:00:00 2001 From: Stefan Fleckenstein Date: Tue, 5 Nov 2024 06:31:01 +0000 Subject: [PATCH 22/34] feat: authorization groups for license groups and policies (#2155) * feat: authorization groups for license groups and policies * more unittests --- backend/application/licenses/api/filters.py | 44 ++++- .../application/licenses/api/permissions.py | 90 +++++++-- .../application/licenses/api/serializers.py | 178 ++++++++++++++++- backend/application/licenses/api/views.py | 42 ++++ ...oup_authorization_group_member_and_more.py | 103 ++++++++++ backend/application/licenses/models.py | 60 +++++- .../licenses/queries/license_group.py | 4 +- ...icense_group_authorization_group_member.py | 47 +++++ .../licenses/queries/license_policy.py | 4 +- ...cense_policy_authorization_group_member.py | 48 +++++ backend/config/api_router.py | 12 ++ .../access_control/api/test_authentication.py | 16 ++ ...thorization_authorization_group_members.py | 16 +- ...cense_group_authorization_group_members.py | 186 ++++++++++++++++++ ...est_authorization_license_group_members.py | 10 +- .../api/test_authorization_license_groups.py | 77 +++++++- .../test_authorization_license_policies.py | 77 +++++++- ...ense_policy_authorization_group_members.py | 186 ++++++++++++++++++ ...test_authorization_license_policy_items.py | 118 ++++++++++- ...st_authorization_license_policy_members.py | 10 +- .../fixtures/unittests_fixtures.json | 18 ++ .../fixtures/unittests_license_fixtures.json | 110 +++++++++++ ...icenseGroupAuthorizationGroupMemberAdd.tsx | 96 +++++++++ ...censeGroupAuthorizationGroupMemberEdit.tsx | 96 +++++++++ ...upAuthorizationGroupMemberEmbeddedList.tsx | 108 ++++++++++ ...nseGroupAuthorizationGroupMemberRemove.tsx | 58 ++++++ .../LicenseGroupLicenseEmbeddedList.tsx | 55 ++++-- .../LicenseGroupMemberAdd.tsx | 35 ++-- .../LicenseGroupMemberEmbeddedList.tsx | 74 ++++--- .../license_groups/LicenseGroupShow.tsx | 7 + .../license_policies/LicensePolicyShow.tsx | 7 + ...censePolicyAuthorizationGroupMemberAdd.tsx | 96 +++++++++ ...ensePolicyAuthorizationGroupMemberEdit.tsx | 96 +++++++++ ...cyAuthorizationGroupMemberEmbeddedList.tsx | 108 ++++++++++ ...sePolicyAuthorizationGroupMemberRemove.tsx | 58 ++++++ .../LicensePolicyItemEmbeddedList.tsx | 81 ++++---- .../LicensePolicyMemberEmbeddedList.tsx | 76 ++++--- 37 files changed, 2300 insertions(+), 207 deletions(-) create mode 100644 backend/application/licenses/migrations/0006_license_group_authorization_group_member_and_more.py create mode 100644 backend/application/licenses/queries/license_group_authorization_group_member.py create mode 100644 backend/application/licenses/queries/license_policy_authorization_group_member.py create mode 100644 backend/unittests/access_control/api/test_authorization_license_group_authorization_group_members.py create mode 100644 backend/unittests/access_control/api/test_authorization_license_policy_authorization_group_members.py create mode 100644 frontend/src/licenses/license_group_authorization_group_members/LicenseGroupAuthorizationGroupMemberAdd.tsx create mode 100644 frontend/src/licenses/license_group_authorization_group_members/LicenseGroupAuthorizationGroupMemberEdit.tsx create mode 100644 frontend/src/licenses/license_group_authorization_group_members/LicenseGroupAuthorizationGroupMemberEmbeddedList.tsx create mode 100644 frontend/src/licenses/license_group_authorization_group_members/LicenseGroupAuthorizationGroupMemberRemove.tsx create mode 100644 frontend/src/licenses/license_policy_authorization_group_members/LicensePolicyAuthorizationGroupMemberAdd.tsx create mode 100644 frontend/src/licenses/license_policy_authorization_group_members/LicensePolicyAuthorizationGroupMemberEdit.tsx create mode 100644 frontend/src/licenses/license_policy_authorization_group_members/LicensePolicyAuthorizationGroupMemberEmbeddedList.tsx create mode 100644 frontend/src/licenses/license_policy_authorization_group_members/LicensePolicyAuthorizationGroupMemberRemove.tsx diff --git a/backend/application/licenses/api/filters.py b/backend/application/licenses/api/filters.py index dd536463c..429802141 100644 --- a/backend/application/licenses/api/filters.py +++ b/backend/application/licenses/api/filters.py @@ -15,8 +15,10 @@ License, License_Component, License_Group, + License_Group_Authorization_Group_Member, License_Group_Member, License_Policy, + License_Policy_Authorization_Group_Member, License_Policy_Item, License_Policy_Member, ) @@ -133,12 +135,31 @@ class LicenseGroupMemberFilter(FilterSet): ("user__full_name", "user_data.full_name"), ("license_group", "license_group"), ("user", "user"), + ("is_manager", "is_manager"), ), ) class Meta: model = License_Group_Member - fields = ["license_group", "user", "username", "full_name"] + fields = ["license_group", "user", "username", "full_name", "is_manager"] + + +class LicenseGroupAuthorizationGroupFilter(FilterSet): + name = CharFilter(field_name="authorization_group__name", lookup_expr="icontains") + + ordering = OrderingFilter( + # tuple-mapping retains order + fields=( + ("authorization_group__name", "authorization_group_data.name"), + ("license_group", "license_group"), + ("authorization_group", "authorization_group"), + ("is_manager", "is_manager"), + ), + ) + + class Meta: + model = License_Group_Authorization_Group_Member + fields = ["license_group", "authorization_group", "name", "is_manager"] class LicensePolicyFilter(FilterSet): @@ -233,9 +254,28 @@ class LicensePolicyMemberFilter(FilterSet): ("user__full_name", "user_data.full_name"), ("license_policy", "license_policy"), ("user", "user"), + ("is_manager", "is_manager"), ), ) class Meta: model = License_Policy_Member - fields = ["license_policy", "user", "username", "full_name"] + fields = ["license_policy", "user", "username", "full_name", "is_manager"] + + +class LicensePolicyAuthorizationGroupFilter(FilterSet): + name = CharFilter(field_name="authorization_group__name", lookup_expr="icontains") + + ordering = OrderingFilter( + # tuple-mapping retains order + fields=( + ("authorization_group__name", "authorization_group_data.name"), + ("license_policy", "license_policy"), + ("authorization_group", "authorization_group"), + ("is_manager", "is_manager"), + ), + ) + + class Meta: + model = License_Policy_Authorization_Group_Member + fields = ["license_policy", "authorization_group", "name", "is_manager"] diff --git a/backend/application/licenses/api/permissions.py b/backend/application/licenses/api/permissions.py index b2b6dc2b5..521fc82a2 100644 --- a/backend/application/licenses/api/permissions.py +++ b/backend/application/licenses/api/permissions.py @@ -1,10 +1,16 @@ from django.shortcuts import get_object_or_404 +from rest_framework.exceptions import NotFound from rest_framework.permissions import BasePermission +from application.access_control.queries.authorization_group import ( + get_authorization_groups, +) from application.licenses.models import ( License_Group, + License_Group_Authorization_Group_Member, License_Group_Member, License_Policy, + License_Policy_Authorization_Group_Member, License_Policy_Member, ) @@ -40,6 +46,30 @@ def has_object_permission(self, request, view, obj: License_Group_Member): return True +class UserHasLicenseGroupAuthenticationGroupMemberPermission(BasePermission): + def has_permission(self, request, view): + if request.method == "POST": + license_group = get_object_or_404( + License_Group, pk=request.data.get("license_group") + ) + + authorization_groups = get_authorization_groups().values_list( + "id", flat=True + ) + if request.data.get("authorization_group") not in authorization_groups: + raise NotFound("Authorization_Group not found.") + + return _has_license_group_manage_permission(request, license_group) + + return True + + def has_object_permission(self, request, view, obj: License_Group_Member): + if request.method != "GET": + return _has_license_group_manage_permission(request, obj.license_group) + + return True + + class UserHasLicensePolicyPermission(BasePermission): def has_permission(self, request, view): if request.method == "POST": @@ -71,18 +101,46 @@ def has_object_permission(self, request, view, obj: License_Policy_Member): return True +class UserHasLicensePolicyAuthorizationGroupMemberPermission(BasePermission): + def has_permission(self, request, view): + if request.method == "POST": + license_policy = get_object_or_404( + License_Policy, pk=request.data.get("license_policy") + ) + + authorization_groups = get_authorization_groups().values_list( + "id", flat=True + ) + if request.data.get("authorization_group") not in authorization_groups: + raise NotFound("Authorization_Group not found.") + + return _has_license_policy_manage_permission(request, license_policy) + + return True + + def has_object_permission(self, request, view, obj: License_Policy_Member): + if request.method != "GET": + return _has_license_policy_manage_permission(request, obj.license_policy) + + return True + + def _has_license_group_manage_permission(request, license_group: License_Group) -> bool: user = request.user if user and user.is_superuser: return True - try: - license_group_member = License_Group_Member.objects.get( - license_group=license_group, user=user - ) - return license_group_member.is_manager - except License_Group_Member.DoesNotExist: - return False + if License_Group_Member.objects.filter( + license_group=license_group, user=user, is_manager=True + ).exists(): + return True + + if License_Group_Authorization_Group_Member.objects.filter( + license_group=license_group, authorization_group__users=user, is_manager=True + ).exists(): + return True + + return False def _has_license_policy_manage_permission( @@ -92,10 +150,14 @@ def _has_license_policy_manage_permission( if user and user.is_superuser: return True - try: - license_policy_member = License_Policy_Member.objects.get( - license_policy=license_policy, user=user - ) - return license_policy_member.is_manager - except License_Policy_Member.DoesNotExist: - return False + if License_Policy_Member.objects.filter( + license_policy=license_policy, user=user, is_manager=True + ).exists(): + return True + + if License_Policy_Authorization_Group_Member.objects.filter( + license_policy=license_policy, authorization_group__users=user, is_manager=True + ).exists(): + return True + + return False diff --git a/backend/application/licenses/api/serializers.py b/backend/application/licenses/api/serializers.py index fbf364688..754d65d54 100644 --- a/backend/application/licenses/api/serializers.py +++ b/backend/application/licenses/api/serializers.py @@ -11,19 +11,34 @@ ValidationError, ) -from application.access_control.api.serializers import UserListSerializer +from application.access_control.api.serializers import ( + AuthorizationGroupListSerializer, + UserListSerializer, +) from application.commons.services.global_request import get_current_user +from application.core.queries.product import get_products from application.core.types import PURL_Type from application.licenses.models import ( License, License_Component, License_Group, + License_Group_Authorization_Group_Member, License_Group_Member, License_Policy, + License_Policy_Authorization_Group_Member, License_Policy_Item, License_Policy_Member, ) +from application.licenses.queries.license_group_authorization_group_member import ( + get_license_group_authorization_group_member, + get_license_group_authorization_group_members, +) from application.licenses.queries.license_group_member import get_license_group_member +from application.licenses.queries.license_policy_authorization_group_member import ( + get_license_policy_authorization_group_member, + get_license_policy_authorization_group_members, +) +from application.licenses.queries.license_policy_item import get_license_policy_items from application.licenses.queries.license_policy_member import get_license_policy_member from application.licenses.services.license_policy import get_ignore_component_type_list @@ -98,25 +113,96 @@ class LicenseComponentBulkDeleteSerializer(Serializer): class LicenseGroupSerializer(ModelSerializer): is_manager = SerializerMethodField() is_in_license_policy = SerializerMethodField() + has_licenses = SerializerMethodField() + has_users = SerializerMethodField() + has_authorization_groups = SerializerMethodField() class Meta: model = License_Group - exclude = ["licenses"] + exclude = ["licenses", "users", "authorization_groups"] def get_is_manager(self, obj: License_Group) -> bool: user = get_current_user() - return License_Group_Member.objects.filter( + + if License_Group_Member.objects.filter( license_group=obj, user=user, is_manager=True - ).exists() + ).exists(): + return True + + if License_Group_Authorization_Group_Member.objects.filter( + license_group=obj, + authorization_group__users=user, + is_manager=True, + ).exists(): + return True + + return False def get_is_in_license_policy(self, obj: License_Group) -> bool: - return License_Policy_Item.objects.filter(license_group=obj).exists() + return get_license_policy_items().filter(license_group=obj).exists() + + def get_has_licenses(self, obj: License_Group) -> bool: + return obj.licenses.exists() + + def get_has_users(self, obj: License_Group) -> bool: + return obj.users.exists() + + def get_has_authorization_groups(self, obj: License_Group) -> bool: + return ( + get_license_group_authorization_group_members() + .filter(license_group=obj) + .exists() + ) class LicenseGroupLicenseAddRemoveSerializer(Serializer): license = IntegerField(min_value=1, required=True) +class LicenseGroupAuthorizationGroupMemberSerializer(ModelSerializer): + license_group_data = LicenseGroupSerializer( + source="license_group", + read_only=True, + ) + authorization_group_data = AuthorizationGroupListSerializer( + source="authorization_group", read_only=True + ) + + class Meta: + model = License_Group_Authorization_Group_Member + fields = "__all__" + + def validate(self, attrs: dict): + self.instance: License_Group_Authorization_Group_Member + data_license_group: Optional[License_Group] = attrs.get("license_group") + data_authorization_group = attrs.get("authorization_group") + + if self.instance is not None and ( + (data_license_group and data_license_group != self.instance.license_group) + or ( + data_authorization_group + and data_authorization_group != self.instance.authorization_group + ) + ): + raise ValidationError( + "License group and authorization group cannot be changed" + ) + + if self.instance is None: + license_group_authorization_group_member = ( + get_license_group_authorization_group_member( + data_license_group, data_authorization_group + ) + ) + if license_group_authorization_group_member: + raise ValidationError( + "License group authorization group member " + + f"{data_license_group} / {data_authorization_group} already exists" + ) + + return attrs + + class LicenseGroupMemberSerializer(ModelSerializer): license_group_data = LicenseGroupSerializer( source="license_group", @@ -158,10 +244,13 @@ class LicenseGroupCopySerializer(Serializer): class LicensePolicySerializer(ModelSerializer): is_manager = SerializerMethodField() has_products = SerializerMethodField() + has_items = SerializerMethodField() + has_users = SerializerMethodField() + has_authorization_groups = SerializerMethodField() class Meta: model = License_Policy - fields = "__all__" + exclude = ["users", "authorization_groups"] def validate_ignore_component_types(self, value: str) -> str: ignore_component_types = get_ignore_component_type_list(value) @@ -174,12 +263,36 @@ def validate_ignore_component_types(self, value: str) -> str: def get_is_manager(self, obj: License_Policy) -> bool: user = get_current_user() - return License_Policy_Member.objects.filter( + + if License_Policy_Member.objects.filter( license_policy=obj, user=user, is_manager=True - ).exists() + ).exists(): + return True + + if License_Policy_Authorization_Group_Member.objects.filter( + license_policy=obj, + authorization_group__users=user, + is_manager=True, + ).exists(): + return True + + return False def get_has_products(self, obj: License_Policy) -> bool: - return obj.product.exists() + return get_products().filter(license_policy=obj).exists() + + def get_has_items(self, obj: License_Policy) -> bool: + return obj.license_policy_items.exists() + + def get_has_users(self, obj: License_Policy) -> bool: + return obj.users.exists() + + def get_has_authorization_groups(self, obj: License_Policy) -> bool: + return ( + get_license_policy_authorization_group_members() + .filter(license_policy=obj) + .exists() + ) class LicensePolicyItemSerializer(ModelSerializer): @@ -297,5 +410,52 @@ def validate(self, attrs: dict): return attrs +class LicensePolicyAuthorizationGroupMemberSerializer(ModelSerializer): + license_policy_data = LicensePolicySerializer( + source="license_policy", + read_only=True, + ) + authorization_group_data = AuthorizationGroupListSerializer( + source="authorization_group", read_only=True + ) + + class Meta: + model = License_Policy_Authorization_Group_Member + fields = "__all__" + + def validate(self, attrs: dict): + self.instance: License_Policy_Authorization_Group_Member + data_license_policy: Optional[License_Policy] = attrs.get("license_policy") + data_authorization_group = attrs.get("authorization_group") + + if self.instance is not None and ( + ( + data_license_policy + and data_license_policy != self.instance.license_policy + ) + or ( + data_authorization_group + and data_authorization_group != self.instance.authorization_group + ) + ): + raise ValidationError( + "License policy and authorization group cannot be changed" + ) + + if self.instance is None: + license_policy_authorization_group_member = ( + get_license_policy_authorization_group_member( + data_license_policy, data_authorization_group + ) + ) + if license_policy_authorization_group_member: + raise ValidationError( + "License policy authorization group member " + + f"{data_license_policy} / {data_authorization_group} already exists" + ) + + return attrs + + class LicensePolicyCopySerializer(Serializer): name = CharField(max_length=255, required=True) diff --git a/backend/application/licenses/api/views.py b/backend/application/licenses/api/views.py index f6dd92d8e..57dc32942 100644 --- a/backend/application/licenses/api/views.py +++ b/backend/application/licenses/api/views.py @@ -12,24 +12,30 @@ from application.licenses.api.filters import ( LicenseComponentFilter, LicenseFilter, + LicenseGroupAuthorizationGroupFilter, LicenseGroupFilter, LicenseGroupMemberFilter, + LicensePolicyAuthorizationGroupFilter, LicensePolicyFilter, LicensePolicyItemFilter, LicensePolicyMemberFilter, ) from application.licenses.api.permissions import ( + UserHasLicenseGroupAuthenticationGroupMemberPermission, UserHasLicenseGroupMemberPermission, UserHasLicenseGroupPermission, + UserHasLicensePolicyAuthorizationGroupMemberPermission, UserHasLicensePolicyItemMemberPermission, UserHasLicensePolicyPermission, ) from application.licenses.api.serializers import ( LicenseComponentSerializer, + LicenseGroupAuthorizationGroupMemberSerializer, LicenseGroupCopySerializer, LicenseGroupLicenseAddRemoveSerializer, LicenseGroupMemberSerializer, LicenseGroupSerializer, + LicensePolicyAuthorizationGroupMemberSerializer, LicensePolicyCopySerializer, LicensePolicyItemSerializer, LicensePolicyMemberSerializer, @@ -40,8 +46,10 @@ License, License_Component, License_Group, + License_Group_Authorization_Group_Member, License_Group_Member, License_Policy, + License_Policy_Authorization_Group_Member, License_Policy_Item, License_Policy_Member, ) @@ -51,6 +59,9 @@ get_license_group, get_license_groups, ) +from application.licenses.queries.license_group_authorization_group_member import ( + get_license_group_authorization_group_members, +) from application.licenses.queries.license_group_member import ( get_license_group_member, get_license_group_members, @@ -59,6 +70,9 @@ get_license_policies, get_license_policy, ) +from application.licenses.queries.license_policy_authorization_group_member import ( + get_license_policy_authorization_group_members, +) from application.licenses.queries.license_policy_item import get_license_policy_items from application.licenses.queries.license_policy_member import ( get_license_policy_member, @@ -214,6 +228,20 @@ def get_queryset(self): return get_license_group_members() +class LicenseGroupAuthorizationGroupMemberViewSet(ModelViewSet): + serializer_class = LicenseGroupAuthorizationGroupMemberSerializer + filterset_class = LicenseGroupAuthorizationGroupFilter + queryset = License_Group_Authorization_Group_Member.objects.none() + filter_backends = [SearchFilter, DjangoFilterBackend] + permission_classes = [ + IsAuthenticated, + UserHasLicenseGroupAuthenticationGroupMemberPermission, + ] + + def get_queryset(self): + return get_license_group_authorization_group_members() + + class LicensePolicyViewSet(ModelViewSet): serializer_class = LicensePolicySerializer filterset_class = LicensePolicyFilter @@ -309,3 +337,17 @@ class LicensePolicyMemberViewSet(ModelViewSet): def get_queryset(self): return get_license_policy_members() + + +class LicensePolicyAuthorizationGroupMemberViewSet(ModelViewSet): + serializer_class = LicensePolicyAuthorizationGroupMemberSerializer + filterset_class = LicensePolicyAuthorizationGroupFilter + queryset = License_Policy_Authorization_Group_Member.objects.none() + filter_backends = [SearchFilter, DjangoFilterBackend] + permission_classes = [ + IsAuthenticated, + UserHasLicensePolicyAuthorizationGroupMemberPermission, + ] + + def get_queryset(self): + return get_license_policy_authorization_group_members() diff --git a/backend/application/licenses/migrations/0006_license_group_authorization_group_member_and_more.py b/backend/application/licenses/migrations/0006_license_group_authorization_group_member_and_more.py new file mode 100644 index 000000000..2e84dc4c3 --- /dev/null +++ b/backend/application/licenses/migrations/0006_license_group_authorization_group_member_and_more.py @@ -0,0 +1,103 @@ +# Generated by Django 5.1.2 on 2024-11-02 09:46 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("access_control", "0010_authorization_group_member_and_more"), + ("licenses", "0005_license_component_created_and_more"), + ] + + operations = [ + migrations.CreateModel( + name="License_Group_Authorization_Group_Member", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("is_manager", models.BooleanField(default=False)), + ( + "authorization_group", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="license_group_authorization_group_members", + to="access_control.authorization_group", + ), + ), + ( + "license_group", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="license_group_authorization_group_members", + to="licenses.license_group", + ), + ), + ], + options={ + "unique_together": {("license_group", "authorization_group")}, + }, + ), + migrations.AddField( + model_name="license_group", + name="authorization_groups", + field=models.ManyToManyField( + blank=True, + related_name="license_groups", + through="licenses.License_Group_Authorization_Group_Member", + to="access_control.authorization_group", + ), + ), + migrations.CreateModel( + name="License_Policy_Authorization_Group_Member", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("is_manager", models.BooleanField(default=False)), + ( + "authorization_group", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="license_policy_authorization_group_members", + to="access_control.authorization_group", + ), + ), + ( + "license_policy", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="license_policy_authorization_group_members", + to="licenses.license_policy", + ), + ), + ], + options={ + "unique_together": {("license_policy", "authorization_group")}, + }, + ), + migrations.AddField( + model_name="license_policy", + name="authorization_groups", + field=models.ManyToManyField( + blank=True, + related_name="license_policies", + through="licenses.License_Policy_Authorization_Group_Member", + to="access_control.authorization_group", + ), + ), + ] diff --git a/backend/application/licenses/models.py b/backend/application/licenses/models.py index ad514ee97..16f036c97 100644 --- a/backend/application/licenses/models.py +++ b/backend/application/licenses/models.py @@ -13,7 +13,7 @@ ) from django.utils import timezone -from application.access_control.models import User +from application.access_control.models import Authorization_Group, User from application.core.models import Branch, Product from application.licenses.types import License_Policy_Evaluation_Result @@ -40,6 +40,12 @@ class License_Group(Model): related_name="license_groups", blank=True, ) + authorization_groups: ManyToManyField = ManyToManyField( + Authorization_Group, + through="License_Group_Authorization_Group_Member", + related_name="license_groups", + blank=True, + ) def __str__(self): return self.name @@ -62,6 +68,29 @@ def __str__(self): return f"{self.license_group} / {self.user}" +class License_Group_Authorization_Group_Member(Model): + license_group = ForeignKey( + License_Group, + related_name="license_group_authorization_group_members", + on_delete=CASCADE, + ) + authorization_group = ForeignKey( + Authorization_Group, + related_name="license_group_authorization_group_members", + on_delete=CASCADE, + ) + is_manager = BooleanField(default=False) + + class Meta: + unique_together = ( + "license_group", + "authorization_group", + ) + + def __str__(self): + return f"{self.license_group} / {self.authorization_group}" + + class License_Component(Model): identity_hash = CharField(max_length=64) @@ -128,6 +157,12 @@ class License_Policy(Model): related_name="license_policies", blank=True, ) + authorization_groups: ManyToManyField = ManyToManyField( + Authorization_Group, + through="License_Policy_Authorization_Group_Member", + related_name="license_policies", + blank=True, + ) def __str__(self): return self.name @@ -184,3 +219,26 @@ class Meta: def __str__(self): return f"{self.license_policy} / {self.user}" + + +class License_Policy_Authorization_Group_Member(Model): + license_policy = ForeignKey( + License_Policy, + related_name="license_policy_authorization_group_members", + on_delete=CASCADE, + ) + authorization_group = ForeignKey( + Authorization_Group, + related_name="license_policy_authorization_group_members", + on_delete=CASCADE, + ) + is_manager = BooleanField(default=False) + + class Meta: + unique_together = ( + "license_policy", + "authorization_group", + ) + + def __str__(self): + return f"{self.license_policy} / {self.authorization_group}" diff --git a/backend/application/licenses/queries/license_group.py b/backend/application/licenses/queries/license_group.py index 2872d9aef..6b2c3e75b 100644 --- a/backend/application/licenses/queries/license_group.py +++ b/backend/application/licenses/queries/license_group.py @@ -25,4 +25,6 @@ def get_license_groups() -> QuerySet[License_Group]: if user.is_superuser: return license_groups - return license_groups.filter(Q(users=user) | Q(is_public=True)) + return license_groups.filter( + Q(users=user) | Q(authorization_groups__users=user) | Q(is_public=True) + ) diff --git a/backend/application/licenses/queries/license_group_authorization_group_member.py b/backend/application/licenses/queries/license_group_authorization_group_member.py new file mode 100644 index 000000000..9c4f7f0aa --- /dev/null +++ b/backend/application/licenses/queries/license_group_authorization_group_member.py @@ -0,0 +1,47 @@ +from typing import Optional + +from django.db.models.query import QuerySet + +from application.access_control.models import Authorization_Group +from application.access_control.queries.authorization_group import ( + get_authorization_groups, +) +from application.commons.services.global_request import get_current_user +from application.licenses.models import ( + License_Group, + License_Group_Authorization_Group_Member, +) +from application.licenses.queries.license_group import get_license_groups + + +def get_license_group_authorization_group_member( + license_group: License_Group, authorization_group: Authorization_Group +) -> Optional[License_Group_Authorization_Group_Member]: + try: + return License_Group_Authorization_Group_Member.objects.get( + license_group=license_group, authorization_group=authorization_group + ) + except License_Group_Authorization_Group_Member.DoesNotExist: + return None + + +def get_license_group_authorization_group_members() -> ( + QuerySet[License_Group_Authorization_Group_Member] +): + user = get_current_user() + + if user is None: + return License_Group_Authorization_Group_Member.objects.none() + + license_group_authorization_group_members = ( + License_Group_Authorization_Group_Member.objects.all().order_by("id") + ) + + if user.is_superuser: + return license_group_authorization_group_members + + authorization_groups = get_authorization_groups() + license_groups = get_license_groups() + return license_group_authorization_group_members.filter( + authorization_group__in=authorization_groups, license_group__in=license_groups + ) diff --git a/backend/application/licenses/queries/license_policy.py b/backend/application/licenses/queries/license_policy.py index 7f349046f..63b51defe 100644 --- a/backend/application/licenses/queries/license_policy.py +++ b/backend/application/licenses/queries/license_policy.py @@ -25,4 +25,6 @@ def get_license_policies() -> QuerySet[License_Policy]: if user.is_superuser: return license_policies - return license_policies.filter(Q(users=user) | Q(is_public=True)) + return license_policies.filter( + Q(users=user) | Q(authorization_groups__users=user) | Q(is_public=True) + ) diff --git a/backend/application/licenses/queries/license_policy_authorization_group_member.py b/backend/application/licenses/queries/license_policy_authorization_group_member.py new file mode 100644 index 000000000..dfdbc62d1 --- /dev/null +++ b/backend/application/licenses/queries/license_policy_authorization_group_member.py @@ -0,0 +1,48 @@ +from typing import Optional + +from django.db.models.query import QuerySet + +from application.access_control.models import Authorization_Group +from application.access_control.queries.authorization_group import ( + get_authorization_groups, +) +from application.commons.services.global_request import get_current_user +from application.licenses.models import ( + License_Policy, + License_Policy_Authorization_Group_Member, +) +from application.licenses.queries.license_policy import get_license_policies + + +def get_license_policy_authorization_group_member( + license_policy: License_Policy, authorization_group: Authorization_Group +) -> Optional[License_Policy_Authorization_Group_Member]: + try: + return License_Policy_Authorization_Group_Member.objects.get( + license_policy=license_policy, authorization_group=authorization_group + ) + except License_Policy_Authorization_Group_Member.DoesNotExist: + return None + + +def get_license_policy_authorization_group_members() -> ( + QuerySet[License_Policy_Authorization_Group_Member] +): + user = get_current_user() + + if user is None: + return License_Policy_Authorization_Group_Member.objects.none() + + license_policy_authorization_group_members = ( + License_Policy_Authorization_Group_Member.objects.all().order_by("id") + ) + + if user.is_superuser: + return license_policy_authorization_group_members + + authorization_groups = get_authorization_groups() + license_policies = get_license_policies() + return license_policy_authorization_group_members.filter( + authorization_group__in=authorization_groups, + license_policy__in=license_policies, + ) diff --git a/backend/config/api_router.py b/backend/config/api_router.py index 25238ca20..95fb0eefa 100644 --- a/backend/config/api_router.py +++ b/backend/config/api_router.py @@ -27,8 +27,10 @@ ) from application.licenses.api.views import ( LicenseComponentViewSet, + LicenseGroupAuthorizationGroupMemberViewSet, LicenseGroupMemberViewSet, LicenseGroupViewSet, + LicensePolicyAuthorizationGroupMemberViewSet, LicensePolicyItemViewSet, LicensePolicyMemberViewSet, LicensePolicyViewSet, @@ -116,6 +118,11 @@ router.register( "license_group_members", LicenseGroupMemberViewSet, basename="license_group_members" ) +router.register( + "license_group_authorization_group_members", + LicenseGroupAuthorizationGroupMemberViewSet, + basename="license_group_authorization_group_members", +) router.register("license_policies", LicensePolicyViewSet, basename="license_policies") router.register( "license_policy_items", LicensePolicyItemViewSet, basename="license_policy_items" @@ -125,6 +132,11 @@ LicensePolicyMemberViewSet, basename="license_policy_members", ) +router.register( + "license_policy_authorization_group_members", + LicensePolicyAuthorizationGroupMemberViewSet, + basename="license_policy_authorization_group_members", +) app_name = "api" urlpatterns = router.urls diff --git a/backend/unittests/access_control/api/test_authentication.py b/backend/unittests/access_control/api/test_authentication.py index 0253eaa80..466053e99 100644 --- a/backend/unittests/access_control/api/test_authentication.py +++ b/backend/unittests/access_control/api/test_authentication.py @@ -331,6 +331,14 @@ def test_authentication(self, mock_user): ["delete", "get", "put", "patch"], "/api/license_group_members/1001/" ) + self._check_authentication( + ["get", "post"], "/api/license_group_authorization_group_members/" + ) + self._check_authentication( + ["delete", "get", "put", "patch"], + "/api/license_group_authorization_group_members/1001/", + ) + self._check_authentication(["get", "post"], "/api/license_policies/") self._check_authentication( ["delete", "get", "put", "patch"], "/api/license_policies/1/" @@ -348,6 +356,14 @@ def test_authentication(self, mock_user): ["delete", "get", "put", "patch"], "/api/license_policy_members/1001/" ) + self._check_authentication( + ["get", "post"], "/api/license_policy_authorization_group_members/" + ) + self._check_authentication( + ["delete", "get", "put", "patch"], + "/api/license_policy_authorization_group_members/1001/", + ) + def test_authentication_users(self): self._check_authentication(["get"], "/api/users/me/") self._check_authentication(["get"], "/api/users/") diff --git a/backend/unittests/access_control/api/test_authorization_authorization_group_members.py b/backend/unittests/access_control/api/test_authorization_authorization_group_members.py index f3b41d4c3..a0b036da1 100644 --- a/backend/unittests/access_control/api/test_authorization_authorization_group_members.py +++ b/backend/unittests/access_control/api/test_authorization_authorization_group_members.py @@ -6,7 +6,7 @@ class TestAuthorizationAuthorizationGroupMembers(TestAuthorizationBase): def test_authorization_authorization_group_members(self): - expected_data = "{'count': 2, 'next': None, 'previous': None, 'results': [{'id': 1, 'authorization_group_data': {'id': 3, 'name': 'non_oidc_group', 'oidc_group': ''}, 'user_data': {'id': 2, 'username': 'db_internal_write', 'first_name': '', 'last_name': '', 'full_name': 'db_internal_write', 'email': '', 'is_active': True, 'is_superuser': False, 'is_external': False, 'setting_theme': 'light', 'setting_list_size': 'medium', 'permissions': [, ], 'setting_list_properties': '', 'oidc_groups_hash': '', 'is_oidc_user': False, 'date_joined': '2022-12-07T20:24:53+01:00', 'has_password': False}, 'is_manager': True, 'authorization_group': 3, 'user': 2}, {'id': 2, 'authorization_group_data': {'id': 3, 'name': 'non_oidc_group', 'oidc_group': ''}, 'user_data': {'id': 3, 'username': 'db_internal_read', 'first_name': '', 'last_name': '', 'full_name': 'db_internal_read', 'email': '', 'is_active': True, 'is_superuser': False, 'is_external': False, 'setting_theme': 'light', 'setting_list_size': 'medium', 'permissions': [, ], 'setting_list_properties': '', 'oidc_groups_hash': '', 'is_oidc_user': False, 'date_joined': '2022-12-07T20:25:06+01:00', 'has_password': False}, 'is_manager': False, 'authorization_group': 3, 'user': 3}]}" + expected_data = "{'count': 4, 'next': None, 'previous': None, 'results': [{'id': 1, 'authorization_group_data': {'id': 3, 'name': 'non_oidc_group', 'oidc_group': ''}, 'user_data': {'id': 2, 'username': 'db_internal_write', 'first_name': '', 'last_name': '', 'full_name': 'db_internal_write', 'email': '', 'is_active': True, 'is_superuser': False, 'is_external': False, 'setting_theme': 'light', 'setting_list_size': 'medium', 'permissions': [, ], 'setting_list_properties': '', 'oidc_groups_hash': '', 'is_oidc_user': False, 'date_joined': '2022-12-07T20:24:53+01:00', 'has_password': False}, 'is_manager': True, 'authorization_group': 3, 'user': 2}, {'id': 2, 'authorization_group_data': {'id': 3, 'name': 'non_oidc_group', 'oidc_group': ''}, 'user_data': {'id': 3, 'username': 'db_internal_read', 'first_name': '', 'last_name': '', 'full_name': 'db_internal_read', 'email': '', 'is_active': True, 'is_superuser': False, 'is_external': False, 'setting_theme': 'light', 'setting_list_size': 'medium', 'permissions': [, ], 'setting_list_properties': '', 'oidc_groups_hash': '', 'is_oidc_user': False, 'date_joined': '2022-12-07T20:25:06+01:00', 'has_password': False}, 'is_manager': False, 'authorization_group': 3, 'user': 3}, {'id': 3, 'authorization_group_data': {'id': 1, 'name': 'oidc_group_1', 'oidc_group': 'oidc_1'}, 'user_data': {'id': 6, 'username': 'db_product_group_user', 'first_name': '', 'last_name': '', 'full_name': 'db_product_group_user', 'email': '', 'is_active': True, 'is_superuser': False, 'is_external': False, 'setting_theme': 'light', 'setting_list_size': 'medium', 'permissions': [, ], 'setting_list_properties': '', 'oidc_groups_hash': '', 'is_oidc_user': False, 'date_joined': '2022-12-04T11:09:18.495000+01:00', 'has_password': True}, 'is_manager': False, 'authorization_group': 1, 'user': 6}, {'id': 4, 'authorization_group_data': {'id': 2, 'name': 'oidc_group_2', 'oidc_group': 'oidc_2'}, 'user_data': {'id': 6, 'username': 'db_product_group_user', 'first_name': '', 'last_name': '', 'full_name': 'db_product_group_user', 'email': '', 'is_active': True, 'is_superuser': False, 'is_external': False, 'setting_theme': 'light', 'setting_list_size': 'medium', 'permissions': [, ], 'setting_list_properties': '', 'oidc_groups_hash': '', 'is_oidc_user': False, 'date_joined': '2022-12-04T11:09:18.495000+01:00', 'has_password': True}, 'is_manager': False, 'authorization_group': 2, 'user': 6}]}" self._test_api( APITest( "db_admin", @@ -34,7 +34,7 @@ def test_authorization_authorization_group_members(self): expected_data = "{'count': 0, 'next': None, 'previous': None, 'results': []}" self._test_api( APITest( - "db_product_group_user", + "db_external", "get", "/api/authorization_group_members/", None, @@ -98,7 +98,7 @@ def test_authorization_authorization_group_members(self): no_second_user=True, ) ) - expected_data = "{'id': 3, 'authorization_group_data': {'id': 3, 'name': 'non_oidc_group', 'oidc_group': ''}, 'user_data': {'id': 1, 'username': 'db_admin', 'full_name': 'db_admin'}, 'is_manager': False, 'authorization_group': 3, 'user': 1}" + expected_data = "{'id': 5, 'authorization_group_data': {'id': 3, 'name': 'non_oidc_group', 'oidc_group': ''}, 'user_data': {'id': 1, 'username': 'db_admin', 'full_name': 'db_admin'}, 'is_manager': False, 'authorization_group': 3, 'user': 1}" self._test_api( APITest( "db_internal_write", @@ -119,7 +119,7 @@ def test_authorization_authorization_group_members(self): APITest( "db_internal_read", "patch", - "/api/authorization_group_members/3/", + "/api/authorization_group_members/5/", post_data, 403, expected_data, @@ -127,12 +127,12 @@ def test_authorization_authorization_group_members(self): ) ) - expected_data = "{'id': 3, 'authorization_group_data': {'id': 3, 'name': 'non_oidc_group', 'oidc_group': ''}, 'user_data': {'id': 1, 'username': 'db_admin', 'full_name': 'db_admin'}, 'is_manager': True, 'authorization_group': 3, 'user': 1}" + expected_data = "{'id': 5, 'authorization_group_data': {'id': 3, 'name': 'non_oidc_group', 'oidc_group': ''}, 'user_data': {'id': 1, 'username': 'db_admin', 'full_name': 'db_admin'}, 'is_manager': True, 'authorization_group': 3, 'user': 1}" self._test_api( APITest( "db_internal_write", "patch", - "/api/authorization_group_members/3/", + "/api/authorization_group_members/5/", post_data, 200, expected_data, @@ -147,7 +147,7 @@ def test_authorization_authorization_group_members(self): APITest( "db_internal_read", "delete", - "/api/authorization_group_members/3/", + "/api/authorization_group_members/5/", None, 403, expected_data, @@ -159,7 +159,7 @@ def test_authorization_authorization_group_members(self): APITest( "db_internal_write", "delete", - "/api/authorization_group_members/3/", + "/api/authorization_group_members/5/", None, 204, expected_data, diff --git a/backend/unittests/access_control/api/test_authorization_license_group_authorization_group_members.py b/backend/unittests/access_control/api/test_authorization_license_group_authorization_group_members.py new file mode 100644 index 000000000..4e5a2c070 --- /dev/null +++ b/backend/unittests/access_control/api/test_authorization_license_group_authorization_group_members.py @@ -0,0 +1,186 @@ +from application.licenses.models import License_Group +from unittests.access_control.api.test_authorization import ( + APITest, + TestAuthorizationBase, +) + + +class TestAuthorizationLicenseGroupAuthorizationGroupMembers(TestAuthorizationBase): + def test_authorization_license_group_authorization_group_members(self): + License_Group.objects.filter(pk__lt=1000).delete() + + expected_data = "{'count': 3, 'next': None, 'previous': None, 'results': [{'id': 1000, 'license_group_data': {'id': 1003, 'is_manager': False, 'is_in_license_policy': False, 'has_licenses': False, 'has_users': False, 'has_authorization_groups': True, 'name': 'authorization_group_not_manager', 'description': '', 'is_public': False}, 'authorization_group_data': {'id': 2, 'name': 'oidc_group_2', 'oidc_group': 'oidc_2'}, 'is_manager': False, 'license_group': 1003, 'authorization_group': 2}, {'id': 1001, 'license_group_data': {'id': 1004, 'is_manager': False, 'is_in_license_policy': False, 'has_licenses': False, 'has_users': False, 'has_authorization_groups': True, 'name': 'authorization_group_manager', 'description': '', 'is_public': False}, 'authorization_group_data': {'id': 2, 'name': 'oidc_group_2', 'oidc_group': 'oidc_2'}, 'is_manager': True, 'license_group': 1004, 'authorization_group': 2}, {'id': 1002, 'license_group_data': {'id': 1003, 'is_manager': False, 'is_in_license_policy': False, 'has_licenses': False, 'has_users': False, 'has_authorization_groups': True, 'name': 'authorization_group_not_manager', 'description': '', 'is_public': False}, 'authorization_group_data': {'id': 3, 'name': 'non_oidc_group', 'oidc_group': ''}, 'is_manager': True, 'license_group': 1003, 'authorization_group': 3}]}" + self._test_api( + APITest( + "db_admin", + "get", + "/api/license_group_authorization_group_members/", + None, + 200, + expected_data, + ) + ) + + expected_data = "{'count': 2, 'next': None, 'previous': None, 'results': [{'id': 1000, 'license_group_data': {'id': 1003, 'is_manager': False, 'is_in_license_policy': False, 'has_licenses': False, 'has_users': False, 'has_authorization_groups': True, 'name': 'authorization_group_not_manager', 'description': '', 'is_public': False}, 'authorization_group_data': {'id': 2, 'name': 'oidc_group_2', 'oidc_group': 'oidc_2'}, 'is_manager': False, 'license_group': 1003, 'authorization_group': 2}, {'id': 1001, 'license_group_data': {'id': 1004, 'is_manager': True, 'is_in_license_policy': False, 'has_licenses': False, 'has_users': False, 'has_authorization_groups': True, 'name': 'authorization_group_manager', 'description': '', 'is_public': False}, 'authorization_group_data': {'id': 2, 'name': 'oidc_group_2', 'oidc_group': 'oidc_2'}, 'is_manager': True, 'license_group': 1004, 'authorization_group': 2}]}" + self._test_api( + APITest( + "db_product_group_user", + "get", + "/api/license_group_authorization_group_members/", + None, + 200, + expected_data, + no_second_user=True, + ) + ) + + expected_data = "{'id': 1000, 'license_group_data': {'id': 1003, 'is_manager': False, 'is_in_license_policy': False, 'has_licenses': False, 'has_users': False, 'has_authorization_groups': True, 'name': 'authorization_group_not_manager', 'description': '', 'is_public': False}, 'authorization_group_data': {'id': 2, 'name': 'oidc_group_2', 'oidc_group': 'oidc_2'}, 'is_manager': False, 'license_group': 1003, 'authorization_group': 2}" + self._test_api( + APITest( + "db_product_group_user", + "get", + "/api/license_group_authorization_group_members/1000/", + None, + 200, + expected_data, + no_second_user=True, + ) + ) + + expected_data = "{'message': 'No License_Group_Authorization_Group_Member matches the given query.'}" + self._test_api( + APITest( + "db_product_group_user", + "get", + "/api/license_group_authorization_group_members/99999/", + None, + 404, + expected_data, + no_second_user=True, + ) + ) + + post_data = { + "license_group": 1004, + "authorization_group": 1, + "is_manager": False, + } + expected_data = "{'id': 1003, 'license_group_data': {'id': 1004, 'is_manager': True, 'is_in_license_policy': False, 'has_licenses': False, 'has_users': False, 'has_authorization_groups': True, 'name': 'authorization_group_manager', 'description': '', 'is_public': False}, 'authorization_group_data': {'id': 1, 'name': 'oidc_group_1', 'oidc_group': 'oidc_1'}, 'is_manager': False, 'license_group': 1004, 'authorization_group': 1}" + self._test_api( + APITest( + "db_product_group_user", + "post", + "/api/license_group_authorization_group_members/", + post_data, + 201, + expected_data, + no_second_user=True, + ) + ) + + post_data = { + "license_group": 1004, + "authorization_group": 3, + "is_manager": False, + } + expected_data = "{'message': 'Authorization_Group not found.'}" + self._test_api( + APITest( + "db_product_group_user", + "post", + "/api/license_group_authorization_group_members/", + post_data, + 404, + expected_data, + no_second_user=True, + ) + ) + + post_data = { + "license_group": 1001, + "authorization_group": 2, + "is_manager": False, + } + expected_data = ( + "{'message': 'You do not have permission to perform this action.'}" + ) + self._test_api( + APITest( + "db_product_group_user", + "post", + "/api/license_group_authorization_group_members/", + post_data, + 403, + expected_data, + no_second_user=True, + ) + ) + + post_data = { + "license_group": 1003, + "authorization_group": 1, + "is_manager": False, + } + self._test_api( + APITest( + "db_product_group_user", + "post", + "/api/license_group_authorization_group_members/", + post_data, + 403, + expected_data, + no_second_user=True, + ) + ) + + expected_data = "{'id': 1003, 'license_group_data': {'id': 1004, 'is_manager': True, 'is_in_license_policy': False, 'has_licenses': False, 'has_users': False, 'has_authorization_groups': True, 'name': 'authorization_group_manager', 'description': '', 'is_public': False}, 'authorization_group_data': {'id': 1, 'name': 'oidc_group_1', 'oidc_group': 'oidc_1'}, 'is_manager': True, 'license_group': 1004, 'authorization_group': 1}" + self._test_api( + APITest( + "db_product_group_user", + "patch", + "/api/license_group_authorization_group_members/1003/", + {"is_manager": "True"}, + 200, + expected_data, + no_second_user=True, + ) + ) + + expected_data = ( + "{'message': 'You do not have permission to perform this action.'}" + ) + self._test_api( + APITest( + "db_product_group_user", + "patch", + "/api/license_group_authorization_group_members/1000/", + {"is_manager": "True"}, + 403, + expected_data, + no_second_user=True, + ) + ) + + self._test_api( + APITest( + "db_product_group_user", + "delete", + "/api/license_group_authorization_group_members/1003/", + None, + 204, + None, + no_second_user=True, + ) + ) + + self._test_api( + APITest( + "db_product_group_user", + "delete", + "/api/license_group_authorization_group_members/1000/", + None, + 403, + None, + no_second_user=True, + ) + ) diff --git a/backend/unittests/access_control/api/test_authorization_license_group_members.py b/backend/unittests/access_control/api/test_authorization_license_group_members.py index a6b4ca0ed..a62a8df9b 100644 --- a/backend/unittests/access_control/api/test_authorization_license_group_members.py +++ b/backend/unittests/access_control/api/test_authorization_license_group_members.py @@ -9,7 +9,7 @@ class TestAuthorizationLicenseGroupMembers(TestAuthorizationBase): def test_authorization_license_group_members(self): License_Group.objects.filter(pk__lt=1000).delete() - expected_data = "{'count': 3, 'next': None, 'previous': None, 'results': [{'id': 1001, 'license_group_data': {'id': 1001, 'is_manager': False, 'is_in_license_policy': False, 'name': 'internal_read_not_manager', 'description': '', 'is_public': False, 'users': [3, 4]}, 'user_data': {'id': 3, 'username': 'db_internal_read', 'first_name': '', 'last_name': '', 'full_name': 'db_internal_read', 'email': '', 'is_active': True, 'is_superuser': False, 'is_external': False, 'setting_theme': 'light', 'setting_list_size': 'medium', 'permissions': [, ], 'setting_list_properties': '', 'oidc_groups_hash': '', 'is_oidc_user': False, 'date_joined': '2022-12-07T20:25:06+01:00', 'has_password': False}, 'is_manager': False, 'license_group': 1001, 'user': 3}, {'id': 1002, 'license_group_data': {'id': 1002, 'is_manager': False, 'is_in_license_policy': False, 'name': 'internal_write_manager', 'description': '', 'is_public': False, 'users': [2]}, 'user_data': {'id': 2, 'username': 'db_internal_write', 'first_name': '', 'last_name': '', 'full_name': 'db_internal_write', 'email': '', 'is_active': True, 'is_superuser': False, 'is_external': False, 'setting_theme': 'light', 'setting_list_size': 'medium', 'permissions': [, ], 'setting_list_properties': '', 'oidc_groups_hash': '', 'is_oidc_user': False, 'date_joined': '2022-12-07T20:24:53+01:00', 'has_password': False}, 'is_manager': True, 'license_group': 1002, 'user': 2}, {'id': 1003, 'license_group_data': {'id': 1001, 'is_manager': False, 'is_in_license_policy': False, 'name': 'internal_read_not_manager', 'description': '', 'is_public': False, 'users': [3, 4]}, 'user_data': {'id': 4, 'username': 'db_external', 'first_name': '', 'last_name': '', 'full_name': 'db_external', 'email': '', 'is_active': True, 'is_superuser': False, 'is_external': True, 'setting_theme': 'light', 'setting_list_size': 'medium', 'permissions': [], 'setting_list_properties': '', 'oidc_groups_hash': '', 'is_oidc_user': False, 'date_joined': '2022-12-12T19:48:08.514000+01:00', 'has_password': False}, 'is_manager': False, 'license_group': 1001, 'user': 4}]}" + expected_data = "{'count': 3, 'next': None, 'previous': None, 'results': [{'id': 1001, 'license_group_data': {'id': 1001, 'is_manager': False, 'is_in_license_policy': False, 'has_licenses': True, 'has_users': True, 'has_authorization_groups': False, 'name': 'internal_read_not_manager', 'description': '', 'is_public': False}, 'user_data': {'id': 3, 'username': 'db_internal_read', 'first_name': '', 'last_name': '', 'full_name': 'db_internal_read', 'email': '', 'is_active': True, 'is_superuser': False, 'is_external': False, 'setting_theme': 'light', 'setting_list_size': 'medium', 'permissions': [, ], 'setting_list_properties': '', 'oidc_groups_hash': '', 'is_oidc_user': False, 'date_joined': '2022-12-07T20:25:06+01:00', 'has_password': False}, 'is_manager': False, 'license_group': 1001, 'user': 3}, {'id': 1002, 'license_group_data': {'id': 1002, 'is_manager': False, 'is_in_license_policy': False, 'has_licenses': True, 'has_users': True, 'has_authorization_groups': False, 'name': 'internal_write_manager', 'description': '', 'is_public': False}, 'user_data': {'id': 2, 'username': 'db_internal_write', 'first_name': '', 'last_name': '', 'full_name': 'db_internal_write', 'email': '', 'is_active': True, 'is_superuser': False, 'is_external': False, 'setting_theme': 'light', 'setting_list_size': 'medium', 'permissions': [, ], 'setting_list_properties': '', 'oidc_groups_hash': '', 'is_oidc_user': False, 'date_joined': '2022-12-07T20:24:53+01:00', 'has_password': False}, 'is_manager': True, 'license_group': 1002, 'user': 2}, {'id': 1003, 'license_group_data': {'id': 1001, 'is_manager': False, 'is_in_license_policy': False, 'has_licenses': True, 'has_users': True, 'has_authorization_groups': False, 'name': 'internal_read_not_manager', 'description': '', 'is_public': False}, 'user_data': {'id': 4, 'username': 'db_external', 'first_name': '', 'last_name': '', 'full_name': 'db_external', 'email': '', 'is_active': True, 'is_superuser': False, 'is_external': True, 'setting_theme': 'light', 'setting_list_size': 'medium', 'permissions': [], 'setting_list_properties': '', 'oidc_groups_hash': '', 'is_oidc_user': False, 'date_joined': '2022-12-12T19:48:08.514000+01:00', 'has_password': False}, 'is_manager': False, 'license_group': 1001, 'user': 4}]}" self._test_api( APITest( "db_admin", @@ -21,7 +21,7 @@ def test_authorization_license_group_members(self): ) ) - expected_data = "{'count': 1, 'next': None, 'previous': None, 'results': [{'id': 1002, 'license_group_data': {'id': 1002, 'is_manager': True, 'is_in_license_policy': False, 'name': 'internal_write_manager', 'description': '', 'is_public': False, 'users': [2]}, 'user_data': {'id': 2, 'username': 'db_internal_write', 'first_name': '', 'last_name': '', 'full_name': 'db_internal_write', 'email': '', 'is_active': True, 'is_superuser': False, 'is_external': False, 'setting_theme': 'light', 'setting_list_size': 'medium', 'permissions': [, ], 'setting_list_properties': '', 'oidc_groups_hash': '', 'is_oidc_user': False, 'date_joined': '2022-12-07T20:24:53+01:00', 'has_password': False}, 'is_manager': True, 'license_group': 1002, 'user': 2}]}" + expected_data = "{'count': 1, 'next': None, 'previous': None, 'results': [{'id': 1002, 'license_group_data': {'id': 1002, 'is_manager': True, 'is_in_license_policy': False, 'has_licenses': True, 'has_users': True, 'has_authorization_groups': False, 'name': 'internal_write_manager', 'description': '', 'is_public': False}, 'user_data': {'id': 2, 'username': 'db_internal_write', 'first_name': '', 'last_name': '', 'full_name': 'db_internal_write', 'email': '', 'is_active': True, 'is_superuser': False, 'is_external': False, 'setting_theme': 'light', 'setting_list_size': 'medium', 'permissions': [, ], 'setting_list_properties': '', 'oidc_groups_hash': '', 'is_oidc_user': False, 'date_joined': '2022-12-07T20:24:53+01:00', 'has_password': False}, 'is_manager': True, 'license_group': 1002, 'user': 2}]}" self._test_api( APITest( "db_internal_write", @@ -34,7 +34,7 @@ def test_authorization_license_group_members(self): ) ) - expected_data = "{'id': 1002, 'license_group_data': {'id': 1002, 'is_manager': True, 'is_in_license_policy': False, 'name': 'internal_write_manager', 'description': '', 'is_public': False, 'users': [2]}, 'user_data': {'id': 2, 'username': 'db_internal_write', 'first_name': '', 'last_name': '', 'full_name': 'db_internal_write', 'email': '', 'is_active': True, 'is_superuser': False, 'is_external': False, 'setting_theme': 'light', 'setting_list_size': 'medium', 'permissions': [, ], 'setting_list_properties': '', 'oidc_groups_hash': '', 'is_oidc_user': False, 'date_joined': '2022-12-07T20:24:53+01:00', 'has_password': False}, 'is_manager': True, 'license_group': 1002, 'user': 2}" + expected_data = "{'id': 1002, 'license_group_data': {'id': 1002, 'is_manager': True, 'is_in_license_policy': False, 'has_licenses': True, 'has_users': True, 'has_authorization_groups': False, 'name': 'internal_write_manager', 'description': '', 'is_public': False}, 'user_data': {'id': 2, 'username': 'db_internal_write', 'first_name': '', 'last_name': '', 'full_name': 'db_internal_write', 'email': '', 'is_active': True, 'is_superuser': False, 'is_external': False, 'setting_theme': 'light', 'setting_list_size': 'medium', 'permissions': [, ], 'setting_list_properties': '', 'oidc_groups_hash': '', 'is_oidc_user': False, 'date_joined': '2022-12-07T20:24:53+01:00', 'has_password': False}, 'is_manager': True, 'license_group': 1002, 'user': 2}" self._test_api( APITest( "db_internal_write", @@ -73,7 +73,7 @@ def test_authorization_license_group_members(self): ) post_data = {"license_group": 1002, "user": 6, "is_manager": False} - expected_data = "{'id': 1004, 'license_group_data': {'id': 1002, 'is_manager': True, 'is_in_license_policy': False, 'name': 'internal_write_manager', 'description': '', 'is_public': False, 'users': [2, 6]}, 'user_data': {'id': 6, 'username': 'db_product_group_user', 'full_name': 'db_product_group_user'}, 'is_manager': False, 'license_group': 1002, 'user': 6}" + expected_data = "{'id': 1004, 'license_group_data': {'id': 1002, 'is_manager': True, 'is_in_license_policy': False, 'has_licenses': True, 'has_users': True, 'has_authorization_groups': False, 'name': 'internal_write_manager', 'description': '', 'is_public': False}, 'user_data': {'id': 6, 'username': 'db_product_group_user', 'full_name': 'db_product_group_user'}, 'is_manager': False, 'license_group': 1002, 'user': 6}" self._test_api( APITest( "db_internal_write", @@ -115,7 +115,7 @@ def test_authorization_license_group_members(self): ) ) - expected_data = "{'id': 1004, 'license_group_data': {'id': 1002, 'is_manager': True, 'is_in_license_policy': False, 'name': 'internal_write_manager', 'description': '', 'is_public': False, 'users': [2, 6]}, 'user_data': {'id': 6, 'username': 'db_product_group_user', 'full_name': 'db_product_group_user'}, 'is_manager': True, 'license_group': 1002, 'user': 6}" + expected_data = "{'id': 1004, 'license_group_data': {'id': 1002, 'is_manager': True, 'is_in_license_policy': False, 'has_licenses': True, 'has_users': True, 'has_authorization_groups': False, 'name': 'internal_write_manager', 'description': '', 'is_public': False}, 'user_data': {'id': 6, 'username': 'db_product_group_user', 'full_name': 'db_product_group_user'}, 'is_manager': True, 'license_group': 1002, 'user': 6}" self._test_api( APITest( "db_internal_write", diff --git a/backend/unittests/access_control/api/test_authorization_license_groups.py b/backend/unittests/access_control/api/test_authorization_license_groups.py index 33a6be9a7..5280fd721 100644 --- a/backend/unittests/access_control/api/test_authorization_license_groups.py +++ b/backend/unittests/access_control/api/test_authorization_license_groups.py @@ -9,12 +9,12 @@ class TestAuthorizationLicenseGroups(TestAuthorizationBase): def test_authorization_license_groups(self): License_Group.objects.filter(pk__lt=1000).delete() - expected_data = "{'count': 3, 'next': None, 'previous': None, 'results': [{'id': 1000, 'is_manager': False, 'is_in_license_policy': False, 'name': 'public', 'description': '', 'is_public': True, 'users': []}, {'id': 1001, 'is_manager': False, 'is_in_license_policy': False, 'name': 'internal_read_not_manager', 'description': '', 'is_public': False, 'users': [3, 4]}, {'id': 1002, 'is_manager': False, 'is_in_license_policy': False, 'name': 'internal_write_manager', 'description': '', 'is_public': False, 'users': [2]}]}" + expected_data = "{'count': 5, 'next': None, 'previous': None, 'results': [{'id': 1000, 'is_manager': False, 'is_in_license_policy': False, 'has_licenses': True, 'has_users': False, 'has_authorization_groups': False, 'name': 'public', 'description': '', 'is_public': True}, {'id': 1001, 'is_manager': False, 'is_in_license_policy': False, 'has_licenses': True, 'has_users': True, 'has_authorization_groups': False, 'name': 'internal_read_not_manager', 'description': '', 'is_public': False}, {'id': 1002, 'is_manager': False, 'is_in_license_policy': False, 'has_licenses': True, 'has_users': True, 'has_authorization_groups': False, 'name': 'internal_write_manager', 'description': '', 'is_public': False}, {'id': 1003, 'is_manager': False, 'is_in_license_policy': False, 'has_licenses': False, 'has_users': False, 'has_authorization_groups': True, 'name': 'authorization_group_not_manager', 'description': '', 'is_public': False}, {'id': 1004, 'is_manager': False, 'is_in_license_policy': False, 'has_licenses': False, 'has_users': False, 'has_authorization_groups': True, 'name': 'authorization_group_manager', 'description': '', 'is_public': False}]}" self._test_api( APITest("db_admin", "get", "/api/license_groups/", None, 200, expected_data) ) - expected_data = "{'count': 2, 'next': None, 'previous': None, 'results': [{'id': 1000, 'is_manager': False, 'is_in_license_policy': False, 'name': 'public', 'description': '', 'is_public': True, 'users': []}, {'id': 1002, 'is_manager': True, 'is_in_license_policy': False, 'name': 'internal_write_manager', 'description': '', 'is_public': False, 'users': [2]}]}" + expected_data = "{'count': 3, 'next': None, 'previous': None, 'results': [{'id': 1000, 'is_manager': False, 'is_in_license_policy': False, 'has_licenses': True, 'has_users': False, 'has_authorization_groups': False, 'name': 'public', 'description': '', 'is_public': True}, {'id': 1002, 'is_manager': True, 'is_in_license_policy': False, 'has_licenses': True, 'has_users': True, 'has_authorization_groups': False, 'name': 'internal_write_manager', 'description': '', 'is_public': False}, {'id': 1003, 'is_manager': True, 'is_in_license_policy': False, 'has_licenses': False, 'has_users': False, 'has_authorization_groups': True, 'name': 'authorization_group_not_manager', 'description': '', 'is_public': False}]}" self._test_api( APITest( "db_internal_write", @@ -27,7 +27,20 @@ def test_authorization_license_groups(self): ) ) - expected_data = "{'id': 1002, 'is_manager': True, 'is_in_license_policy': False, 'name': 'internal_write_manager', 'description': '', 'is_public': False, 'users': [2]}" + expected_data = "{'count': 3, 'next': None, 'previous': None, 'results': [{'id': 1000, 'is_manager': False, 'is_in_license_policy': False, 'has_licenses': True, 'has_users': False, 'has_authorization_groups': False, 'name': 'public', 'description': '', 'is_public': True}, {'id': 1003, 'is_manager': False, 'is_in_license_policy': False, 'has_licenses': False, 'has_users': False, 'has_authorization_groups': True, 'name': 'authorization_group_not_manager', 'description': '', 'is_public': False}, {'id': 1004, 'is_manager': True, 'is_in_license_policy': False, 'has_licenses': False, 'has_users': False, 'has_authorization_groups': True, 'name': 'authorization_group_manager', 'description': '', 'is_public': False}]}" + self._test_api( + APITest( + "db_product_group_user", + "get", + "/api/license_groups/", + None, + 200, + expected_data, + no_second_user=True, + ) + ) + + expected_data = "{'id': 1002, 'is_manager': True, 'is_in_license_policy': False, 'has_licenses': True, 'has_users': True, 'has_authorization_groups': False, 'name': 'internal_write_manager', 'description': '', 'is_public': False}" self._test_api( APITest( "db_internal_write", @@ -64,7 +77,7 @@ def test_authorization_license_groups(self): ) post_data = {"name": "new_license_group"} - expected_data = "{'id': 1003, 'is_manager': True, 'is_in_license_policy': False, 'name': 'new_license_group', 'description': '', 'is_public': False, 'users': [2]}" + expected_data = "{'id': 1005, 'is_manager': True, 'is_in_license_policy': False, 'has_licenses': False, 'has_users': True, 'has_authorization_groups': False, 'name': 'new_license_group', 'description': '', 'is_public': False}" self._test_api( APITest( "db_internal_write", @@ -93,7 +106,7 @@ def test_authorization_license_groups(self): ) ) - expected_data = "{'id': 1002, 'is_manager': True, 'is_in_license_policy': False, 'name': 'internal_write_manager', 'description': 'changed', 'is_public': False, 'users': [2]}" + expected_data = "{'id': 1002, 'is_manager': True, 'is_in_license_policy': False, 'has_licenses': True, 'has_users': True, 'has_authorization_groups': False, 'name': 'internal_write_manager', 'description': 'changed', 'is_public': False}" self._test_api( APITest( "db_internal_write", @@ -121,6 +134,34 @@ def test_authorization_license_groups(self): ) ) + expected_data = "{'id': 1004, 'is_manager': True, 'is_in_license_policy': False, 'has_licenses': False, 'has_users': False, 'has_authorization_groups': True, 'name': 'authorization_group_manager', 'description': 'changed', 'is_public': False}" + self._test_api( + APITest( + "db_product_group_user", + "patch", + "/api/license_groups/1004/", + {"description": "changed"}, + 200, + expected_data, + no_second_user=True, + ) + ) + + expected_data = ( + "{'message': 'You do not have permission to perform this action.'}" + ) + self._test_api( + APITest( + "db_product_group_user", + "patch", + "/api/license_groups/1003/", + {"description": "changed"}, + 403, + expected_data, + no_second_user=True, + ) + ) + self._test_api( APITest( "db_internal_read", @@ -134,7 +175,7 @@ def test_authorization_license_groups(self): ) post_data = {"name": "copied_license_group"} - expected_data = "{'id': 1004, 'is_manager': True, 'is_in_license_policy': False, 'name': 'copied_license_group', 'description': 'changed', 'is_public': False, 'users': [2]}" + expected_data = "{'id': 1006, 'is_manager': True, 'is_in_license_policy': False, 'has_licenses': True, 'has_users': True, 'has_authorization_groups': False, 'name': 'copied_license_group', 'description': 'changed', 'is_public': False}" self._test_api( APITest( "db_internal_write", @@ -288,3 +329,27 @@ def test_authorization_license_groups(self): no_second_user=True, ) ) + + self._test_api( + APITest( + "db_product_group_user", + "delete", + "/api/license_groups/1004/", + None, + 204, + None, + no_second_user=True, + ) + ) + + self._test_api( + APITest( + "db_product_group_user", + "delete", + "/api/license_groups/1003/", + None, + 403, + None, + no_second_user=True, + ) + ) diff --git a/backend/unittests/access_control/api/test_authorization_license_policies.py b/backend/unittests/access_control/api/test_authorization_license_policies.py index 28c974fa9..0c5dfc3f0 100644 --- a/backend/unittests/access_control/api/test_authorization_license_policies.py +++ b/backend/unittests/access_control/api/test_authorization_license_policies.py @@ -9,14 +9,14 @@ class TestAuthorizationLicensePolicies(TestAuthorizationBase): def test_authorization_license_policies(self): License_Policy.objects.filter(pk__lt=1000).delete() - expected_data = "{'count': 3, 'next': None, 'previous': None, 'results': [{'id': 1000, 'is_manager': False, 'has_products': False, 'name': 'public', 'description': '', 'is_public': True, 'ignore_component_types': '', 'users': []}, {'id': 1001, 'is_manager': False, 'has_products': False, 'name': 'internal_read_not_manager', 'description': '', 'is_public': False, 'ignore_component_types': '', 'users': [3, 4]}, {'id': 1002, 'is_manager': False, 'has_products': False, 'name': 'internal_write_manager', 'description': '', 'is_public': False, 'ignore_component_types': '', 'users': [2]}]}" + expected_data = "{'count': 5, 'next': None, 'previous': None, 'results': [{'id': 1000, 'is_manager': False, 'has_products': False, 'has_items': True, 'has_users': False, 'has_authorization_groups': False, 'name': 'public', 'description': '', 'is_public': True, 'ignore_component_types': ''}, {'id': 1001, 'is_manager': False, 'has_products': False, 'has_items': True, 'has_users': True, 'has_authorization_groups': False, 'name': 'internal_read_not_manager', 'description': '', 'is_public': False, 'ignore_component_types': ''}, {'id': 1002, 'is_manager': False, 'has_products': False, 'has_items': True, 'has_users': True, 'has_authorization_groups': False, 'name': 'internal_write_manager', 'description': '', 'is_public': False, 'ignore_component_types': ''}, {'id': 1003, 'is_manager': False, 'has_products': False, 'has_items': True, 'has_users': False, 'has_authorization_groups': True, 'name': 'authorization_group_not_manager', 'description': '', 'is_public': False, 'ignore_component_types': ''}, {'id': 1004, 'is_manager': False, 'has_products': False, 'has_items': True, 'has_users': False, 'has_authorization_groups': True, 'name': 'authorization_group_manager', 'description': '', 'is_public': False, 'ignore_component_types': ''}]}" self._test_api( APITest( "db_admin", "get", "/api/license_policies/", None, 200, expected_data ) ) - expected_data = "{'count': 2, 'next': None, 'previous': None, 'results': [{'id': 1000, 'is_manager': False, 'has_products': False, 'name': 'public', 'description': '', 'is_public': True, 'ignore_component_types': '', 'users': []}, {'id': 1002, 'is_manager': True, 'has_products': False, 'name': 'internal_write_manager', 'description': '', 'is_public': False, 'ignore_component_types': '', 'users': [2]}]}" + expected_data = "{'count': 3, 'next': None, 'previous': None, 'results': [{'id': 1000, 'is_manager': False, 'has_products': False, 'has_items': True, 'has_users': False, 'has_authorization_groups': False, 'name': 'public', 'description': '', 'is_public': True, 'ignore_component_types': ''}, {'id': 1002, 'is_manager': True, 'has_products': False, 'has_items': True, 'has_users': True, 'has_authorization_groups': False, 'name': 'internal_write_manager', 'description': '', 'is_public': False, 'ignore_component_types': ''}, {'id': 1003, 'is_manager': True, 'has_products': False, 'has_items': True, 'has_users': False, 'has_authorization_groups': True, 'name': 'authorization_group_not_manager', 'description': '', 'is_public': False, 'ignore_component_types': ''}]}" self._test_api( APITest( "db_internal_write", @@ -29,7 +29,20 @@ def test_authorization_license_policies(self): ) ) - expected_data = "{'id': 1002, 'is_manager': True, 'has_products': False, 'name': 'internal_write_manager', 'description': '', 'is_public': False, 'ignore_component_types': '', 'users': [2]}" + expected_data = "{'count': 3, 'next': None, 'previous': None, 'results': [{'id': 1000, 'is_manager': False, 'has_products': False, 'has_items': True, 'has_users': False, 'has_authorization_groups': False, 'name': 'public', 'description': '', 'is_public': True, 'ignore_component_types': ''}, {'id': 1003, 'is_manager': False, 'has_products': False, 'has_items': True, 'has_users': False, 'has_authorization_groups': True, 'name': 'authorization_group_not_manager', 'description': '', 'is_public': False, 'ignore_component_types': ''}, {'id': 1004, 'is_manager': True, 'has_products': False, 'has_items': True, 'has_users': False, 'has_authorization_groups': True, 'name': 'authorization_group_manager', 'description': '', 'is_public': False, 'ignore_component_types': ''}]}" + self._test_api( + APITest( + "db_product_group_user", + "get", + "/api/license_policies/", + None, + 200, + expected_data, + no_second_user=True, + ) + ) + + expected_data = "{'id': 1002, 'is_manager': True, 'has_products': False, 'has_items': True, 'has_users': True, 'has_authorization_groups': False, 'name': 'internal_write_manager', 'description': '', 'is_public': False, 'ignore_component_types': ''}" self._test_api( APITest( "db_internal_write", @@ -66,7 +79,7 @@ def test_authorization_license_policies(self): ) post_data = {"name": "new_license_policy"} - expected_data = "{'id': 1003, 'is_manager': True, 'has_products': False, 'name': 'new_license_policy', 'description': '', 'is_public': False, 'ignore_component_types': '', 'users': [2]}" + expected_data = "{'id': 1005, 'is_manager': True, 'has_products': False, 'has_items': False, 'has_users': True, 'has_authorization_groups': False, 'name': 'new_license_policy', 'description': '', 'is_public': False, 'ignore_component_types': ''}" self._test_api( APITest( "db_internal_write", @@ -95,7 +108,7 @@ def test_authorization_license_policies(self): ) ) - expected_data = "{'id': 1002, 'is_manager': True, 'has_products': False, 'name': 'internal_write_manager', 'description': 'changed', 'is_public': False, 'ignore_component_types': '', 'users': [2]}" + expected_data = "{'id': 1002, 'is_manager': True, 'has_products': False, 'has_items': True, 'has_users': True, 'has_authorization_groups': False, 'name': 'internal_write_manager', 'description': 'changed', 'is_public': False, 'ignore_component_types': ''}" self._test_api( APITest( "db_internal_write", @@ -123,6 +136,34 @@ def test_authorization_license_policies(self): ) ) + expected_data = "{'id': 1004, 'is_manager': True, 'has_products': False, 'has_items': True, 'has_users': False, 'has_authorization_groups': True, 'name': 'authorization_group_manager', 'description': 'changed', 'is_public': False, 'ignore_component_types': ''}" + self._test_api( + APITest( + "db_product_group_user", + "patch", + "/api/license_policies/1004/", + {"description": "changed"}, + 200, + expected_data, + no_second_user=True, + ) + ) + + expected_data = ( + "{'message': 'You do not have permission to perform this action.'}" + ) + self._test_api( + APITest( + "db_product_group_user", + "patch", + "/api/license_policies/1003/", + {"description": "changed"}, + 403, + expected_data, + no_second_user=True, + ) + ) + self._test_api( APITest( "db_internal_read", @@ -136,7 +177,7 @@ def test_authorization_license_policies(self): ) post_data = {"name": "copied_license_policy"} - expected_data = "{'id': 1004, 'is_manager': True, 'has_products': False, 'name': 'copied_license_policy', 'description': 'changed', 'is_public': False, 'ignore_component_types': '', 'users': [2]}" + expected_data = "{'id': 1006, 'is_manager': True, 'has_products': False, 'has_items': True, 'has_users': True, 'has_authorization_groups': False, 'name': 'copied_license_policy', 'description': 'changed', 'is_public': False, 'ignore_component_types': ''}" self._test_api( APITest( "db_internal_write", @@ -252,3 +293,27 @@ def test_authorization_license_policies(self): no_second_user=True, ) ) + + self._test_api( + APITest( + "db_product_group_user", + "delete", + "/api/license_policies/1004/", + None, + 204, + None, + no_second_user=True, + ) + ) + + self._test_api( + APITest( + "db_product_group_user", + "delete", + "/api/license_policies/1003/", + None, + 403, + None, + no_second_user=True, + ) + ) diff --git a/backend/unittests/access_control/api/test_authorization_license_policy_authorization_group_members.py b/backend/unittests/access_control/api/test_authorization_license_policy_authorization_group_members.py new file mode 100644 index 000000000..8c71a91fa --- /dev/null +++ b/backend/unittests/access_control/api/test_authorization_license_policy_authorization_group_members.py @@ -0,0 +1,186 @@ +from application.licenses.models import License_Policy +from unittests.access_control.api.test_authorization import ( + APITest, + TestAuthorizationBase, +) + + +class TestAuthorizationLicensePolicyAuthorizationGroupMembers(TestAuthorizationBase): + def test_authorization_license_policy_authorization_group_members(self): + License_Policy.objects.filter(pk__lt=1000).delete() + + expected_data = "{'count': 3, 'next': None, 'previous': None, 'results': [{'id': 1000, 'license_policy_data': {'id': 1003, 'is_manager': False, 'has_products': False, 'has_items': True, 'has_users': False, 'has_authorization_groups': True, 'name': 'authorization_group_not_manager', 'description': '', 'is_public': False, 'ignore_component_types': ''}, 'authorization_group_data': {'id': 2, 'name': 'oidc_group_2', 'oidc_group': 'oidc_2'}, 'is_manager': False, 'license_policy': 1003, 'authorization_group': 2}, {'id': 1001, 'license_policy_data': {'id': 1004, 'is_manager': False, 'has_products': False, 'has_items': True, 'has_users': False, 'has_authorization_groups': True, 'name': 'authorization_group_manager', 'description': '', 'is_public': False, 'ignore_component_types': ''}, 'authorization_group_data': {'id': 2, 'name': 'oidc_group_2', 'oidc_group': 'oidc_2'}, 'is_manager': True, 'license_policy': 1004, 'authorization_group': 2}, {'id': 1002, 'license_policy_data': {'id': 1003, 'is_manager': False, 'has_products': False, 'has_items': True, 'has_users': False, 'has_authorization_groups': True, 'name': 'authorization_group_not_manager', 'description': '', 'is_public': False, 'ignore_component_types': ''}, 'authorization_group_data': {'id': 3, 'name': 'non_oidc_group', 'oidc_group': ''}, 'is_manager': True, 'license_policy': 1003, 'authorization_group': 3}]}" + self._test_api( + APITest( + "db_admin", + "get", + "/api/license_policy_authorization_group_members/", + None, + 200, + expected_data, + ) + ) + + expected_data = "{'count': 2, 'next': None, 'previous': None, 'results': [{'id': 1000, 'license_policy_data': {'id': 1003, 'is_manager': False, 'has_products': False, 'has_items': True, 'has_users': False, 'has_authorization_groups': True, 'name': 'authorization_group_not_manager', 'description': '', 'is_public': False, 'ignore_component_types': ''}, 'authorization_group_data': {'id': 2, 'name': 'oidc_group_2', 'oidc_group': 'oidc_2'}, 'is_manager': False, 'license_policy': 1003, 'authorization_group': 2}, {'id': 1001, 'license_policy_data': {'id': 1004, 'is_manager': True, 'has_products': False, 'has_items': True, 'has_users': False, 'has_authorization_groups': True, 'name': 'authorization_group_manager', 'description': '', 'is_public': False, 'ignore_component_types': ''}, 'authorization_group_data': {'id': 2, 'name': 'oidc_group_2', 'oidc_group': 'oidc_2'}, 'is_manager': True, 'license_policy': 1004, 'authorization_group': 2}]}" + self._test_api( + APITest( + "db_product_group_user", + "get", + "/api/license_policy_authorization_group_members/", + None, + 200, + expected_data, + no_second_user=True, + ) + ) + + expected_data = "{'id': 1000, 'license_policy_data': {'id': 1003, 'is_manager': False, 'has_products': False, 'has_items': True, 'has_users': False, 'has_authorization_groups': True, 'name': 'authorization_group_not_manager', 'description': '', 'is_public': False, 'ignore_component_types': ''}, 'authorization_group_data': {'id': 2, 'name': 'oidc_group_2', 'oidc_group': 'oidc_2'}, 'is_manager': False, 'license_policy': 1003, 'authorization_group': 2}" + self._test_api( + APITest( + "db_product_group_user", + "get", + "/api/license_policy_authorization_group_members/1000/", + None, + 200, + expected_data, + no_second_user=True, + ) + ) + + expected_data = "{'message': 'No License_Policy_Authorization_Group_Member matches the given query.'}" + self._test_api( + APITest( + "db_product_group_user", + "get", + "/api/license_policy_authorization_group_members/99999/", + None, + 404, + expected_data, + no_second_user=True, + ) + ) + + post_data = { + "license_policy": 1004, + "authorization_group": 1, + "is_manager": False, + } + expected_data = "{'id': 1003, 'license_policy_data': {'id': 1004, 'is_manager': True, 'has_products': False, 'has_items': True, 'has_users': False, 'has_authorization_groups': True, 'name': 'authorization_group_manager', 'description': '', 'is_public': False, 'ignore_component_types': ''}, 'authorization_group_data': {'id': 1, 'name': 'oidc_group_1', 'oidc_group': 'oidc_1'}, 'is_manager': False, 'license_policy': 1004, 'authorization_group': 1}" + self._test_api( + APITest( + "db_product_group_user", + "post", + "/api/license_policy_authorization_group_members/", + post_data, + 201, + expected_data, + no_second_user=True, + ) + ) + + post_data = { + "license_policy": 1004, + "authorization_group": 3, + "is_manager": False, + } + expected_data = "{'message': 'Authorization_Group not found.'}" + self._test_api( + APITest( + "db_product_group_user", + "post", + "/api/license_policy_authorization_group_members/", + post_data, + 404, + expected_data, + no_second_user=True, + ) + ) + + post_data = { + "license_policy": 1001, + "authorization_group": 2, + "is_manager": False, + } + expected_data = ( + "{'message': 'You do not have permission to perform this action.'}" + ) + self._test_api( + APITest( + "db_product_group_user", + "post", + "/api/license_policy_authorization_group_members/", + post_data, + 403, + expected_data, + no_second_user=True, + ) + ) + + post_data = { + "license_policy": 1003, + "authorization_group": 1, + "is_manager": False, + } + self._test_api( + APITest( + "db_product_group_user", + "post", + "/api/license_policy_authorization_group_members/", + post_data, + 403, + expected_data, + no_second_user=True, + ) + ) + + expected_data = "{'id': 1003, 'license_policy_data': {'id': 1004, 'is_manager': True, 'has_products': False, 'has_items': True, 'has_users': False, 'has_authorization_groups': True, 'name': 'authorization_group_manager', 'description': '', 'is_public': False, 'ignore_component_types': ''}, 'authorization_group_data': {'id': 1, 'name': 'oidc_group_1', 'oidc_group': 'oidc_1'}, 'is_manager': True, 'license_policy': 1004, 'authorization_group': 1}" + self._test_api( + APITest( + "db_product_group_user", + "patch", + "/api/license_policy_authorization_group_members/1003/", + {"is_manager": "True"}, + 200, + expected_data, + no_second_user=True, + ) + ) + + expected_data = ( + "{'message': 'You do not have permission to perform this action.'}" + ) + self._test_api( + APITest( + "db_product_group_user", + "patch", + "/api/license_policy_authorization_group_members/1000/", + {"is_manager": "True"}, + 403, + expected_data, + no_second_user=True, + ) + ) + + self._test_api( + APITest( + "db_product_group_user", + "delete", + "/api/license_policy_authorization_group_members/1003/", + None, + 204, + None, + no_second_user=True, + ) + ) + + self._test_api( + APITest( + "db_product_group_user", + "delete", + "/api/license_policy_authorization_group_members/1000/", + None, + 403, + None, + no_second_user=True, + ) + ) diff --git a/backend/unittests/access_control/api/test_authorization_license_policy_items.py b/backend/unittests/access_control/api/test_authorization_license_policy_items.py index 147b6a1dc..692076721 100644 --- a/backend/unittests/access_control/api/test_authorization_license_policy_items.py +++ b/backend/unittests/access_control/api/test_authorization_license_policy_items.py @@ -9,7 +9,7 @@ class TestAuthorizationLicensePolicyItems(TestAuthorizationBase): def test_authorization_license_policy_items(self): License_Policy.objects.filter(pk__lt=1000).delete() - expected_data = "{'count': 3, 'next': None, 'previous': None, 'results': [{'id': 1000, 'license_spdx_id': '', 'license_group_name': 'Permissive Model (Blue Oak Council)', 'license_policy_data': {'id': 1000, 'is_manager': False, 'has_products': False, 'name': 'public', 'description': '', 'is_public': True, 'ignore_component_types': '', 'users': []}, 'unknown_license': '', 'evaluation_result': 'Allowed', 'license_policy': 1000, 'license_group': 1, 'license': None}, {'id': 1001, 'license_spdx_id': '0BSD', 'license_group_name': '', 'license_policy_data': {'id': 1001, 'is_manager': False, 'has_products': False, 'name': 'internal_read_not_manager', 'description': '', 'is_public': False, 'ignore_component_types': '', 'users': [3, 4]}, 'unknown_license': '', 'evaluation_result': 'Forbidden', 'license_policy': 1001, 'license_group': None, 'license': 1}, {'id': 1002, 'license_spdx_id': '', 'license_group_name': '', 'license_policy_data': {'id': 1002, 'is_manager': False, 'has_products': False, 'name': 'internal_write_manager', 'description': '', 'is_public': False, 'ignore_component_types': '', 'users': [2]}, 'unknown_license': 'Two unknown licenses', 'evaluation_result': 'Unknown', 'license_policy': 1002, 'license_group': None, 'license': None}]}" + expected_data = "{'count': 5, 'next': None, 'previous': None, 'results': [{'id': 1000, 'license_spdx_id': '', 'license_group_name': 'Permissive Model (Blue Oak Council)', 'license_policy_data': {'id': 1000, 'is_manager': False, 'has_products': False, 'has_items': True, 'has_users': False, 'has_authorization_groups': False, 'name': 'public', 'description': '', 'is_public': True, 'ignore_component_types': ''}, 'unknown_license': '', 'evaluation_result': 'Allowed', 'license_policy': 1000, 'license_group': 1, 'license': None}, {'id': 1001, 'license_spdx_id': '0BSD', 'license_group_name': '', 'license_policy_data': {'id': 1001, 'is_manager': False, 'has_products': False, 'has_items': True, 'has_users': True, 'has_authorization_groups': False, 'name': 'internal_read_not_manager', 'description': '', 'is_public': False, 'ignore_component_types': ''}, 'unknown_license': '', 'evaluation_result': 'Forbidden', 'license_policy': 1001, 'license_group': None, 'license': 1}, {'id': 1002, 'license_spdx_id': '', 'license_group_name': '', 'license_policy_data': {'id': 1002, 'is_manager': False, 'has_products': False, 'has_items': True, 'has_users': True, 'has_authorization_groups': False, 'name': 'internal_write_manager', 'description': '', 'is_public': False, 'ignore_component_types': ''}, 'unknown_license': 'Two unknown licenses', 'evaluation_result': 'Unknown', 'license_policy': 1002, 'license_group': None, 'license': None}, {'id': 1003, 'license_spdx_id': '', 'license_group_name': '', 'license_policy_data': {'id': 1003, 'is_manager': False, 'has_products': False, 'has_items': True, 'has_users': False, 'has_authorization_groups': True, 'name': 'authorization_group_not_manager', 'description': '', 'is_public': False, 'ignore_component_types': ''}, 'unknown_license': 'Three unknown licenses', 'evaluation_result': 'Unknown', 'license_policy': 1003, 'license_group': None, 'license': None}, {'id': 1004, 'license_spdx_id': '', 'license_group_name': '', 'license_policy_data': {'id': 1004, 'is_manager': False, 'has_products': False, 'has_items': True, 'has_users': False, 'has_authorization_groups': True, 'name': 'authorization_group_manager', 'description': '', 'is_public': False, 'ignore_component_types': ''}, 'unknown_license': 'Four unknown licenses', 'evaluation_result': 'Unknown', 'license_policy': 1004, 'license_group': None, 'license': None}]}" self._test_api( APITest( "db_admin", @@ -21,7 +21,7 @@ def test_authorization_license_policy_items(self): ) ) - expected_data = "{'count': 2, 'next': None, 'previous': None, 'results': [{'id': 1000, 'license_spdx_id': '', 'license_group_name': 'Permissive Model (Blue Oak Council)', 'license_policy_data': {'id': 1000, 'is_manager': False, 'has_products': False, 'name': 'public', 'description': '', 'is_public': True, 'ignore_component_types': '', 'users': []}, 'unknown_license': '', 'evaluation_result': 'Allowed', 'license_policy': 1000, 'license_group': 1, 'license': None}, {'id': 1002, 'license_spdx_id': '', 'license_group_name': '', 'license_policy_data': {'id': 1002, 'is_manager': True, 'has_products': False, 'name': 'internal_write_manager', 'description': '', 'is_public': False, 'ignore_component_types': '', 'users': [2]}, 'unknown_license': 'Two unknown licenses', 'evaluation_result': 'Unknown', 'license_policy': 1002, 'license_group': None, 'license': None}]}" + expected_data = "{'count': 3, 'next': None, 'previous': None, 'results': [{'id': 1000, 'license_spdx_id': '', 'license_group_name': 'Permissive Model (Blue Oak Council)', 'license_policy_data': {'id': 1000, 'is_manager': False, 'has_products': False, 'has_items': True, 'has_users': False, 'has_authorization_groups': False, 'name': 'public', 'description': '', 'is_public': True, 'ignore_component_types': ''}, 'unknown_license': '', 'evaluation_result': 'Allowed', 'license_policy': 1000, 'license_group': 1, 'license': None}, {'id': 1002, 'license_spdx_id': '', 'license_group_name': '', 'license_policy_data': {'id': 1002, 'is_manager': True, 'has_products': False, 'has_items': True, 'has_users': True, 'has_authorization_groups': False, 'name': 'internal_write_manager', 'description': '', 'is_public': False, 'ignore_component_types': ''}, 'unknown_license': 'Two unknown licenses', 'evaluation_result': 'Unknown', 'license_policy': 1002, 'license_group': None, 'license': None}, {'id': 1003, 'license_spdx_id': '', 'license_group_name': '', 'license_policy_data': {'id': 1003, 'is_manager': True, 'has_products': False, 'has_items': True, 'has_users': False, 'has_authorization_groups': True, 'name': 'authorization_group_not_manager', 'description': '', 'is_public': False, 'ignore_component_types': ''}, 'unknown_license': 'Three unknown licenses', 'evaluation_result': 'Unknown', 'license_policy': 1003, 'license_group': None, 'license': None}]}" self._test_api( APITest( "db_internal_write", @@ -34,7 +34,20 @@ def test_authorization_license_policy_items(self): ) ) - expected_data = "{'id': 1002, 'license_spdx_id': '', 'license_group_name': '', 'license_policy_data': {'id': 1002, 'is_manager': True, 'has_products': False, 'name': 'internal_write_manager', 'description': '', 'is_public': False, 'ignore_component_types': '', 'users': [2]}, 'unknown_license': 'Two unknown licenses', 'evaluation_result': 'Unknown', 'license_policy': 1002, 'license_group': None, 'license': None}" + expected_data = "{'count': 3, 'next': None, 'previous': None, 'results': [{'id': 1000, 'license_spdx_id': '', 'license_group_name': 'Permissive Model (Blue Oak Council)', 'license_policy_data': {'id': 1000, 'is_manager': False, 'has_products': False, 'has_items': True, 'has_users': False, 'has_authorization_groups': False, 'name': 'public', 'description': '', 'is_public': True, 'ignore_component_types': ''}, 'unknown_license': '', 'evaluation_result': 'Allowed', 'license_policy': 1000, 'license_group': 1, 'license': None}, {'id': 1003, 'license_spdx_id': '', 'license_group_name': '', 'license_policy_data': {'id': 1003, 'is_manager': False, 'has_products': False, 'has_items': True, 'has_users': False, 'has_authorization_groups': True, 'name': 'authorization_group_not_manager', 'description': '', 'is_public': False, 'ignore_component_types': ''}, 'unknown_license': 'Three unknown licenses', 'evaluation_result': 'Unknown', 'license_policy': 1003, 'license_group': None, 'license': None}, {'id': 1004, 'license_spdx_id': '', 'license_group_name': '', 'license_policy_data': {'id': 1004, 'is_manager': True, 'has_products': False, 'has_items': True, 'has_users': False, 'has_authorization_groups': True, 'name': 'authorization_group_manager', 'description': '', 'is_public': False, 'ignore_component_types': ''}, 'unknown_license': 'Four unknown licenses', 'evaluation_result': 'Unknown', 'license_policy': 1004, 'license_group': None, 'license': None}]}" + self._test_api( + APITest( + "db_product_group_user", + "get", + "/api/license_policy_items/", + None, + 200, + expected_data, + no_second_user=True, + ) + ) + + expected_data = "{'id': 1002, 'license_spdx_id': '', 'license_group_name': '', 'license_policy_data': {'id': 1002, 'is_manager': True, 'has_products': False, 'has_items': True, 'has_users': True, 'has_authorization_groups': False, 'name': 'internal_write_manager', 'description': '', 'is_public': False, 'ignore_component_types': ''}, 'unknown_license': 'Two unknown licenses', 'evaluation_result': 'Unknown', 'license_policy': 1002, 'license_group': None, 'license': None}" self._test_api( APITest( "db_internal_write", @@ -76,7 +89,7 @@ def test_authorization_license_policy_items(self): "unknown_license": "", "evaluation_result": "Allowed", } - expected_data = "{'id': 1003, 'license_spdx_id': '', 'license_group_name': 'Permissive Gold (Blue Oak Council)', 'license_policy_data': {'id': 1002, 'is_manager': True, 'has_products': False, 'name': 'internal_write_manager', 'description': '', 'is_public': False, 'ignore_component_types': '', 'users': [2]}, 'unknown_license': '', 'evaluation_result': 'Allowed', 'license_policy': 1002, 'license_group': 2, 'license': None}" + expected_data = "{'id': 1005, 'license_spdx_id': '', 'license_group_name': 'Permissive Gold (Blue Oak Council)', 'license_policy_data': {'id': 1002, 'is_manager': True, 'has_products': False, 'has_items': True, 'has_users': True, 'has_authorization_groups': False, 'name': 'internal_write_manager', 'description': '', 'is_public': False, 'ignore_component_types': ''}, 'unknown_license': '', 'evaluation_result': 'Allowed', 'license_policy': 1002, 'license_group': 2, 'license': None}" self._test_api( APITest( "db_internal_write", @@ -110,6 +123,46 @@ def test_authorization_license_policy_items(self): ) ) + post_data = { + "license_policy": 1004, + "license_group": 2, + "unknown_license": "", + "evaluation_result": "Allowed", + } + expected_data = "{'id': 1006, 'license_spdx_id': '', 'license_group_name': 'Permissive Gold (Blue Oak Council)', 'license_policy_data': {'id': 1004, 'is_manager': True, 'has_products': False, 'has_items': True, 'has_users': False, 'has_authorization_groups': True, 'name': 'authorization_group_manager', 'description': '', 'is_public': False, 'ignore_component_types': ''}, 'unknown_license': '', 'evaluation_result': 'Allowed', 'license_policy': 1004, 'license_group': 2, 'license': None}" + self._test_api( + APITest( + "db_product_group_user", + "post", + "/api/license_policy_items/", + post_data, + 201, + expected_data, + no_second_user=True, + ) + ) + + post_data = { + "license_policy": 1003, + "license_group": 2, + "unknown_license": "", + "evaluation_result": "Allowed", + } + expected_data = ( + "{'message': 'You do not have permission to perform this action.'}" + ) + self._test_api( + APITest( + "db_product_group_user", + "post", + "/api/license_policy_items/", + post_data, + 403, + expected_data, + no_second_user=True, + ) + ) + post_data = { "license_policy": 1001, "license_group": 2, @@ -128,7 +181,7 @@ def test_authorization_license_policy_items(self): ) ) - expected_data = "{'id': 1002, 'license_spdx_id': '', 'license_group_name': '', 'license_policy_data': {'id': 1002, 'is_manager': True, 'has_products': False, 'name': 'internal_write_manager', 'description': '', 'is_public': False, 'ignore_component_types': '', 'users': [2]}, 'unknown_license': 'Two unknown licenses', 'evaluation_result': 'Review required', 'license_policy': 1002, 'license_group': None, 'license': None}" + expected_data = "{'id': 1002, 'license_spdx_id': '', 'license_group_name': '', 'license_policy_data': {'id': 1002, 'is_manager': True, 'has_products': False, 'has_items': True, 'has_users': True, 'has_authorization_groups': False, 'name': 'internal_write_manager', 'description': '', 'is_public': False, 'ignore_component_types': ''}, 'unknown_license': 'Two unknown licenses', 'evaluation_result': 'Review required', 'license_policy': 1002, 'license_group': None, 'license': None}" self._test_api( APITest( "db_internal_write", @@ -159,6 +212,37 @@ def test_authorization_license_policy_items(self): ) ) + expected_data = "{'id': 1004, 'license_spdx_id': '', 'license_group_name': '', 'license_policy_data': {'id': 1004, 'is_manager': True, 'has_products': False, 'has_items': True, 'has_users': False, 'has_authorization_groups': True, 'name': 'authorization_group_manager', 'description': '', 'is_public': False, 'ignore_component_types': ''}, 'unknown_license': 'Four unknown licenses', 'evaluation_result': 'Review required', 'license_policy': 1004, 'license_group': None, 'license': None}" + self._test_api( + APITest( + "db_product_group_user", + "patch", + "/api/license_policy_items/1004/", + { + "unknown_license": "Four unknown licenses", + "evaluation_result": "Review required", + }, + 200, + expected_data, + no_second_user=True, + ) + ) + + expected_data = ( + "{'message': 'You do not have permission to perform this action.'}" + ) + self._test_api( + APITest( + "db_product_group_user", + "patch", + "/api/license_policy_items/1003/", + {"is_manager": "True"}, + 403, + expected_data, + no_second_user=True, + ) + ) + self._test_api( APITest( "db_internal_write", @@ -182,3 +266,27 @@ def test_authorization_license_policy_items(self): no_second_user=True, ) ) + + self._test_api( + APITest( + "db_product_group_user", + "delete", + "/api/license_policy_items/1004/", + None, + 204, + None, + no_second_user=True, + ) + ) + + self._test_api( + APITest( + "db_product_group_user", + "delete", + "/api/license_policy_items/1003/", + None, + 403, + None, + no_second_user=True, + ) + ) diff --git a/backend/unittests/access_control/api/test_authorization_license_policy_members.py b/backend/unittests/access_control/api/test_authorization_license_policy_members.py index 313367b23..b29181bc3 100644 --- a/backend/unittests/access_control/api/test_authorization_license_policy_members.py +++ b/backend/unittests/access_control/api/test_authorization_license_policy_members.py @@ -9,7 +9,7 @@ class TestAuthorizationLicensePolicyMembers(TestAuthorizationBase): def test_authorization_license_policy_members(self): License_Policy.objects.filter(pk__lt=1000).delete() - expected_data = "{'count': 3, 'next': None, 'previous': None, 'results': [{'id': 1001, 'license_policy_data': {'id': 1001, 'is_manager': False, 'has_products': False, 'name': 'internal_read_not_manager', 'description': '', 'is_public': False, 'ignore_component_types': '', 'users': [3, 4]}, 'user_data': {'id': 3, 'username': 'db_internal_read', 'first_name': '', 'last_name': '', 'full_name': 'db_internal_read', 'email': '', 'is_active': True, 'is_superuser': False, 'is_external': False, 'setting_theme': 'light', 'setting_list_size': 'medium', 'permissions': [, ], 'setting_list_properties': '', 'oidc_groups_hash': '', 'is_oidc_user': False, 'date_joined': '2022-12-07T20:25:06+01:00', 'has_password': False}, 'is_manager': False, 'license_policy': 1001, 'user': 3}, {'id': 1002, 'license_policy_data': {'id': 1002, 'is_manager': False, 'has_products': False, 'name': 'internal_write_manager', 'description': '', 'is_public': False, 'ignore_component_types': '', 'users': [2]}, 'user_data': {'id': 2, 'username': 'db_internal_write', 'first_name': '', 'last_name': '', 'full_name': 'db_internal_write', 'email': '', 'is_active': True, 'is_superuser': False, 'is_external': False, 'setting_theme': 'light', 'setting_list_size': 'medium', 'permissions': [, ], 'setting_list_properties': '', 'oidc_groups_hash': '', 'is_oidc_user': False, 'date_joined': '2022-12-07T20:24:53+01:00', 'has_password': False}, 'is_manager': True, 'license_policy': 1002, 'user': 2}, {'id': 1003, 'license_policy_data': {'id': 1001, 'is_manager': False, 'has_products': False, 'name': 'internal_read_not_manager', 'description': '', 'is_public': False, 'ignore_component_types': '', 'users': [3, 4]}, 'user_data': {'id': 4, 'username': 'db_external', 'first_name': '', 'last_name': '', 'full_name': 'db_external', 'email': '', 'is_active': True, 'is_superuser': False, 'is_external': True, 'setting_theme': 'light', 'setting_list_size': 'medium', 'permissions': [], 'setting_list_properties': '', 'oidc_groups_hash': '', 'is_oidc_user': False, 'date_joined': '2022-12-12T19:48:08.514000+01:00', 'has_password': False}, 'is_manager': False, 'license_policy': 1001, 'user': 4}]}" + expected_data = "{'count': 3, 'next': None, 'previous': None, 'results': [{'id': 1001, 'license_policy_data': {'id': 1001, 'is_manager': False, 'has_products': False, 'has_items': True, 'has_users': True, 'has_authorization_groups': False, 'name': 'internal_read_not_manager', 'description': '', 'is_public': False, 'ignore_component_types': ''}, 'user_data': {'id': 3, 'username': 'db_internal_read', 'first_name': '', 'last_name': '', 'full_name': 'db_internal_read', 'email': '', 'is_active': True, 'is_superuser': False, 'is_external': False, 'setting_theme': 'light', 'setting_list_size': 'medium', 'permissions': [, ], 'setting_list_properties': '', 'oidc_groups_hash': '', 'is_oidc_user': False, 'date_joined': '2022-12-07T20:25:06+01:00', 'has_password': False}, 'is_manager': False, 'license_policy': 1001, 'user': 3}, {'id': 1002, 'license_policy_data': {'id': 1002, 'is_manager': False, 'has_products': False, 'has_items': True, 'has_users': True, 'has_authorization_groups': False, 'name': 'internal_write_manager', 'description': '', 'is_public': False, 'ignore_component_types': ''}, 'user_data': {'id': 2, 'username': 'db_internal_write', 'first_name': '', 'last_name': '', 'full_name': 'db_internal_write', 'email': '', 'is_active': True, 'is_superuser': False, 'is_external': False, 'setting_theme': 'light', 'setting_list_size': 'medium', 'permissions': [, ], 'setting_list_properties': '', 'oidc_groups_hash': '', 'is_oidc_user': False, 'date_joined': '2022-12-07T20:24:53+01:00', 'has_password': False}, 'is_manager': True, 'license_policy': 1002, 'user': 2}, {'id': 1003, 'license_policy_data': {'id': 1001, 'is_manager': False, 'has_products': False, 'has_items': True, 'has_users': True, 'has_authorization_groups': False, 'name': 'internal_read_not_manager', 'description': '', 'is_public': False, 'ignore_component_types': ''}, 'user_data': {'id': 4, 'username': 'db_external', 'first_name': '', 'last_name': '', 'full_name': 'db_external', 'email': '', 'is_active': True, 'is_superuser': False, 'is_external': True, 'setting_theme': 'light', 'setting_list_size': 'medium', 'permissions': [], 'setting_list_properties': '', 'oidc_groups_hash': '', 'is_oidc_user': False, 'date_joined': '2022-12-12T19:48:08.514000+01:00', 'has_password': False}, 'is_manager': False, 'license_policy': 1001, 'user': 4}]}" self._test_api( APITest( "db_admin", @@ -21,7 +21,7 @@ def test_authorization_license_policy_members(self): ) ) - expected_data = "{'count': 1, 'next': None, 'previous': None, 'results': [{'id': 1002, 'license_policy_data': {'id': 1002, 'is_manager': True, 'has_products': False, 'name': 'internal_write_manager', 'description': '', 'is_public': False, 'ignore_component_types': '', 'users': [2]}, 'user_data': {'id': 2, 'username': 'db_internal_write', 'first_name': '', 'last_name': '', 'full_name': 'db_internal_write', 'email': '', 'is_active': True, 'is_superuser': False, 'is_external': False, 'setting_theme': 'light', 'setting_list_size': 'medium', 'permissions': [, ], 'setting_list_properties': '', 'oidc_groups_hash': '', 'is_oidc_user': False, 'date_joined': '2022-12-07T20:24:53+01:00', 'has_password': False}, 'is_manager': True, 'license_policy': 1002, 'user': 2}]}" + expected_data = "{'count': 1, 'next': None, 'previous': None, 'results': [{'id': 1002, 'license_policy_data': {'id': 1002, 'is_manager': True, 'has_products': False, 'has_items': True, 'has_users': True, 'has_authorization_groups': False, 'name': 'internal_write_manager', 'description': '', 'is_public': False, 'ignore_component_types': ''}, 'user_data': {'id': 2, 'username': 'db_internal_write', 'first_name': '', 'last_name': '', 'full_name': 'db_internal_write', 'email': '', 'is_active': True, 'is_superuser': False, 'is_external': False, 'setting_theme': 'light', 'setting_list_size': 'medium', 'permissions': [, ], 'setting_list_properties': '', 'oidc_groups_hash': '', 'is_oidc_user': False, 'date_joined': '2022-12-07T20:24:53+01:00', 'has_password': False}, 'is_manager': True, 'license_policy': 1002, 'user': 2}]}" self._test_api( APITest( "db_internal_write", @@ -34,7 +34,7 @@ def test_authorization_license_policy_members(self): ) ) - expected_data = "{'id': 1002, 'license_policy_data': {'id': 1002, 'is_manager': True, 'has_products': False, 'name': 'internal_write_manager', 'description': '', 'is_public': False, 'ignore_component_types': '', 'users': [2]}, 'user_data': {'id': 2, 'username': 'db_internal_write', 'first_name': '', 'last_name': '', 'full_name': 'db_internal_write', 'email': '', 'is_active': True, 'is_superuser': False, 'is_external': False, 'setting_theme': 'light', 'setting_list_size': 'medium', 'permissions': [, ], 'setting_list_properties': '', 'oidc_groups_hash': '', 'is_oidc_user': False, 'date_joined': '2022-12-07T20:24:53+01:00', 'has_password': False}, 'is_manager': True, 'license_policy': 1002, 'user': 2}" + expected_data = "{'id': 1002, 'license_policy_data': {'id': 1002, 'is_manager': True, 'has_products': False, 'has_items': True, 'has_users': True, 'has_authorization_groups': False, 'name': 'internal_write_manager', 'description': '', 'is_public': False, 'ignore_component_types': ''}, 'user_data': {'id': 2, 'username': 'db_internal_write', 'first_name': '', 'last_name': '', 'full_name': 'db_internal_write', 'email': '', 'is_active': True, 'is_superuser': False, 'is_external': False, 'setting_theme': 'light', 'setting_list_size': 'medium', 'permissions': [, ], 'setting_list_properties': '', 'oidc_groups_hash': '', 'is_oidc_user': False, 'date_joined': '2022-12-07T20:24:53+01:00', 'has_password': False}, 'is_manager': True, 'license_policy': 1002, 'user': 2}" self._test_api( APITest( "db_internal_write", @@ -73,7 +73,7 @@ def test_authorization_license_policy_members(self): ) post_data = {"license_policy": 1002, "user": 6, "is_manager": False} - expected_data = "{'id': 1004, 'license_policy_data': {'id': 1002, 'is_manager': True, 'has_products': False, 'name': 'internal_write_manager', 'description': '', 'is_public': False, 'ignore_component_types': '', 'users': [2, 6]}, 'user_data': {'id': 6, 'username': 'db_product_group_user', 'full_name': 'db_product_group_user'}, 'is_manager': False, 'license_policy': 1002, 'user': 6}" + expected_data = "{'id': 1004, 'license_policy_data': {'id': 1002, 'is_manager': True, 'has_products': False, 'has_items': True, 'has_users': True, 'has_authorization_groups': False, 'name': 'internal_write_manager', 'description': '', 'is_public': False, 'ignore_component_types': ''}, 'user_data': {'id': 6, 'username': 'db_product_group_user', 'full_name': 'db_product_group_user'}, 'is_manager': False, 'license_policy': 1002, 'user': 6}" self._test_api( APITest( "db_internal_write", @@ -115,7 +115,7 @@ def test_authorization_license_policy_members(self): ) ) - expected_data = "{'id': 1004, 'license_policy_data': {'id': 1002, 'is_manager': True, 'has_products': False, 'name': 'internal_write_manager', 'description': '', 'is_public': False, 'ignore_component_types': '', 'users': [2, 6]}, 'user_data': {'id': 6, 'username': 'db_product_group_user', 'full_name': 'db_product_group_user'}, 'is_manager': True, 'license_policy': 1002, 'user': 6}" + expected_data = "{'id': 1004, 'license_policy_data': {'id': 1002, 'is_manager': True, 'has_products': False, 'has_items': True, 'has_users': True, 'has_authorization_groups': False, 'name': 'internal_write_manager', 'description': '', 'is_public': False, 'ignore_component_types': ''}, 'user_data': {'id': 6, 'username': 'db_product_group_user', 'full_name': 'db_product_group_user'}, 'is_manager': True, 'license_policy': 1002, 'user': 6}" self._test_api( APITest( "db_internal_write", diff --git a/backend/unittests/fixtures/unittests_fixtures.json b/backend/unittests/fixtures/unittests_fixtures.json index bbab53fbb..2c8dafd4f 100644 --- a/backend/unittests/fixtures/unittests_fixtures.json +++ b/backend/unittests/fixtures/unittests_fixtures.json @@ -169,6 +169,24 @@ "is_manager": false } }, + { + "model": "access_control.authorization_group_member", + "pk": 3, + "fields": { + "authorization_group": 1, + "user": 6, + "is_manager": false + } + }, + { + "model": "access_control.authorization_group_member", + "pk": 4, + "fields": { + "authorization_group": 2, + "user": 6, + "is_manager": false + } + }, { "model": "core.product", "pk": 1, diff --git a/backend/unittests/fixtures/unittests_license_fixtures.json b/backend/unittests/fixtures/unittests_license_fixtures.json index c73ab566e..eeb754ffd 100644 --- a/backend/unittests/fixtures/unittests_license_fixtures.json +++ b/backend/unittests/fixtures/unittests_license_fixtures.json @@ -83,6 +83,24 @@ ] } }, + { + "model": "licenses.license_group", + "pk": 1003, + "fields": { + "name": "authorization_group_not_manager", + "description": "", + "is_public": false + } + }, + { + "model": "licenses.license_group", + "pk": 1004, + "fields": { + "name": "authorization_group_manager", + "description": "", + "is_public": false + } + }, { "model": "licenses.license_group_member", "pk": 1001, @@ -110,6 +128,33 @@ "is_manager": false } }, + { + "model": "licenses.license_group_authorization_group_member", + "pk": 1000, + "fields": { + "license_group": 1003, + "authorization_group": 2, + "is_manager": false + } + }, + { + "model": "licenses.license_group_authorization_group_member", + "pk": 1001, + "fields": { + "license_group": 1004, + "authorization_group": 2, + "is_manager": true + } + }, + { + "model": "licenses.license_group_authorization_group_member", + "pk": 1002, + "fields": { + "license_group": 1003, + "authorization_group": 3, + "is_manager": true + } + }, { "model": "licenses.license_policy", "pk": 1000, @@ -137,6 +182,24 @@ "is_public": false } }, + { + "model": "licenses.license_policy", + "pk": 1003, + "fields": { + "name": "authorization_group_not_manager", + "description": "", + "is_public": false + } + }, + { + "model": "licenses.license_policy", + "pk": 1004, + "fields": { + "name": "authorization_group_manager", + "description": "", + "is_public": false + } + }, { "model": "licenses.license_policy_item", "pk": 1000, @@ -169,6 +232,26 @@ "numerical_evaluation_result": 3 } }, + { + "model": "licenses.license_policy_item", + "pk": 1003, + "fields": { + "license_policy": 1003, + "unknown_license": "Three unknown licenses", + "evaluation_result": "Unknown", + "numerical_evaluation_result": 3 + } + }, + { + "model": "licenses.license_policy_item", + "pk": 1004, + "fields": { + "license_policy": 1004, + "unknown_license": "Four unknown licenses", + "evaluation_result": "Unknown", + "numerical_evaluation_result": 3 + } + }, { "model": "licenses.license_policy_member", "pk": 1001, @@ -195,5 +278,32 @@ "user": 4, "is_manager": false } + }, + { + "model": "licenses.license_policy_authorization_group_member", + "pk": 1000, + "fields": { + "license_policy": 1003, + "authorization_group": 2, + "is_manager": false + } + }, + { + "model": "licenses.license_policy_authorization_group_member", + "pk": 1001, + "fields": { + "license_policy": 1004, + "authorization_group": 2, + "is_manager": true + } + }, + { + "model": "licenses.license_policy_authorization_group_member", + "pk": 1002, + "fields": { + "license_policy": 1003, + "authorization_group": 3, + "is_manager": true + } } ] \ No newline at end of file diff --git a/frontend/src/licenses/license_group_authorization_group_members/LicenseGroupAuthorizationGroupMemberAdd.tsx b/frontend/src/licenses/license_group_authorization_group_members/LicenseGroupAuthorizationGroupMemberAdd.tsx new file mode 100644 index 000000000..0321ceb7d --- /dev/null +++ b/frontend/src/licenses/license_group_authorization_group_members/LicenseGroupAuthorizationGroupMemberAdd.tsx @@ -0,0 +1,96 @@ +import AddIcon from "@mui/icons-material/Add"; +import CancelIcon from "@mui/icons-material/Cancel"; +import { Button, Dialog, DialogContent, DialogTitle } from "@mui/material"; +import { Fragment, useState } from "react"; +import { BooleanInput, ReferenceInput, SaveButton, SimpleForm, Toolbar, useNotify, useRefresh } from "react-admin"; + +import { validate_required } from "../../commons/custom_validators"; +import { AutocompleteInputWide } from "../../commons/layout/themes"; +import { httpClient } from "../../commons/ra-data-django-rest-framework"; + +export type LicenseGroupAuthorizationGroupMemberAddProps = { + id: any; +}; + +const LicenseGroupAuthorizationGroupMemberAdd = ({ id }: LicenseGroupAuthorizationGroupMemberAddProps) => { + const [open, setOpen] = useState(false); + const refresh = useRefresh(); + const notify = useNotify(); + const handleOpen = () => setOpen(true); + const handleCancel = () => setOpen(false); + const handleClose = (event: object, reason: string) => { + if (reason && reason == "backdropClick") return; + setOpen(false); + }; + const CancelButton = () => ( + + ); + + const CustomToolbar = () => ( + + + + + ); + + const add_authorization_group = (data: any) => { + const url = window.__RUNTIME_CONFIG__.API_BASE_URL + "/license_group_authorization_group_members/"; + const body = JSON.stringify({ license_group: id, ...data }); + httpClient(url, { + method: "POST", + body: body, + }) + .then(() => { + refresh(); + notify("Authorization group added", { type: "success" }); + setOpen(false); + }) + .catch((error) => { + notify(error.message, { type: "warning" }); + }); + }; + + return ( + + + + Add authorization group + + }> + + + + + + + + + ); +}; + +export default LicenseGroupAuthorizationGroupMemberAdd; diff --git a/frontend/src/licenses/license_group_authorization_group_members/LicenseGroupAuthorizationGroupMemberEdit.tsx b/frontend/src/licenses/license_group_authorization_group_members/LicenseGroupAuthorizationGroupMemberEdit.tsx new file mode 100644 index 000000000..0997c4684 --- /dev/null +++ b/frontend/src/licenses/license_group_authorization_group_members/LicenseGroupAuthorizationGroupMemberEdit.tsx @@ -0,0 +1,96 @@ +import CancelIcon from "@mui/icons-material/Cancel"; +import EditIcon from "@mui/icons-material/Edit"; +import { Button, Dialog, DialogContent, DialogTitle } from "@mui/material"; +import { Fragment, useState } from "react"; +import { BooleanInput, SaveButton, SimpleForm, Toolbar, useNotify, useRefresh, useUpdate } from "react-admin"; + +import { TextInputWide } from "../../commons/layout/themes"; + +const LicenseGroupAuthorizationGroupMemberEdit = () => { + const [open, setOpen] = useState(false); + const [update] = useUpdate(); + const refresh = useRefresh(); + const notify = useNotify(); + const handleOpen = () => setOpen(true); + const handleCancel = () => setOpen(false); + const handleClose = (event: object, reason: string) => { + if (reason && reason == "backdropClick") return; + setOpen(false); + }; + + const member_update = async (data: any) => { + const patch = { + is_manager: data.is_manager, + }; + + update( + "license_group_authorization_group_members", + + { + id: data.id, + data: patch, + }, + { + onSuccess: () => { + refresh(); + notify("Authorization group member updated", { + type: "success", + }); + }, + onError: (error: any) => { + notify(error.message, { + type: "warning", + }); + }, + } + ); + setOpen(false); + }; + + const CancelButton = () => ( + + ); + + const CustomToolbar = () => ( + + + + + ); + return ( + + + + Edit authorization group + + }> + + + + + + + ); +}; + +export default LicenseGroupAuthorizationGroupMemberEdit; diff --git a/frontend/src/licenses/license_group_authorization_group_members/LicenseGroupAuthorizationGroupMemberEmbeddedList.tsx b/frontend/src/licenses/license_group_authorization_group_members/LicenseGroupAuthorizationGroupMemberEmbeddedList.tsx new file mode 100644 index 000000000..08155335b --- /dev/null +++ b/frontend/src/licenses/license_group_authorization_group_members/LicenseGroupAuthorizationGroupMemberEmbeddedList.tsx @@ -0,0 +1,108 @@ +import { Stack } from "@mui/material"; +import { Fragment } from "react"; +import { + BooleanField, + Datagrid, + FilterForm, + Identifier, + ListContextProvider, + NullableBooleanInput, + ResourceContextProvider, + TextInput, + WithRecord, + useListController, +} from "react-admin"; + +import { CustomPagination } from "../../commons/custom_fields/CustomPagination"; +import TextUrlField from "../../commons/custom_fields/TextUrlField"; +import { is_superuser } from "../../commons/functions"; +import { getSettingListSize } from "../../commons/user_settings/functions"; +import LicenseGroupAuthorizationGroupMemberAdd from "./LicenseGroupAuthorizationGroupMemberAdd"; +import LicenseGroupAuthorizationGroupMemberEdit from "./LicenseGroupAuthorizationGroupMemberEdit"; +import LicenseGroupAuthorizationGroupMemberRemove from "./LicenseGroupAuthorizationGroupMemberRemove"; + +function listFilters() { + return [ + , + , + ]; +} + +const showAuthorizationGroup = (id: Identifier) => { + return "#/authorization_groups/" + id + "/show"; +}; + +type LicenseGroupAuthorizationGroupMemberEmbeddedListProps = { + license_group: any; +}; + +const LicenseGroupAuthorizationGroupMemberEmbeddedList = ({ + license_group, +}: LicenseGroupAuthorizationGroupMemberEmbeddedListProps) => { + const listContext = useListController({ + filter: { license_group: Number(license_group.id) }, + perPage: 25, + resource: "license_group_authorization_group_members", + sort: { field: "authorization_group_data.name", order: "ASC" }, + filterDefaultValues: {}, + disableSyncWithLocation: true, + }); + + if (listContext.isLoading) { + return
Loading...
; + } + + return ( + + +
+ {(is_superuser() || license_group.is_manager) && ( + + )} + {license_group.has_authorization_groups && ( + + + + ( + + )} + /> + + {(is_superuser() || license_group.is_manager) && ( + ( + + + + + )} + /> + )} + + + + )} +
+
+
+ ); +}; + +export default LicenseGroupAuthorizationGroupMemberEmbeddedList; diff --git a/frontend/src/licenses/license_group_authorization_group_members/LicenseGroupAuthorizationGroupMemberRemove.tsx b/frontend/src/licenses/license_group_authorization_group_members/LicenseGroupAuthorizationGroupMemberRemove.tsx new file mode 100644 index 000000000..b24b0959f --- /dev/null +++ b/frontend/src/licenses/license_group_authorization_group_members/LicenseGroupAuthorizationGroupMemberRemove.tsx @@ -0,0 +1,58 @@ +import DeleteIcon from "@mui/icons-material/Delete"; +import { useState } from "react"; +import { Button, Confirm, useNotify, useRefresh } from "react-admin"; + +import { httpClient } from "../../commons/ra-data-django-rest-framework"; + +type LicenseGroupAuthorizationGroupMemberRemoveProps = { + license_group_authorization_group_member: any; +}; + +const LicenseGroupAuthorizationGroupMemberRemove = ({ + license_group_authorization_group_member, +}: LicenseGroupAuthorizationGroupMemberRemoveProps) => { + const [open, setOpen] = useState(false); + const refresh = useRefresh(); + const notify = useNotify(); + const handleClick = () => setOpen(true); + const handleDialogClose = () => setOpen(false); + + const removeUser = async () => { + const url = + window.__RUNTIME_CONFIG__.API_BASE_URL + + "/license_group_authorization_group_members/" + + license_group_authorization_group_member.id + + "/"; + httpClient(url, { + method: "DELETE", + }) + .then(() => { + refresh(); + notify("Authorization group removed", { type: "success" }); + }) + .catch((error) => { + notify(error.message, { type: "warning" }); + }); + + setOpen(false); + }; + + return ( + <> + + ); + + const CustomToolbar = () => ( + + + + + ); + + const add_authorization_group = (data: any) => { + const url = window.__RUNTIME_CONFIG__.API_BASE_URL + "/license_policy_authorization_group_members/"; + const body = JSON.stringify({ license_policy: id, ...data }); + httpClient(url, { + method: "POST", + body: body, + }) + .then(() => { + refresh(); + notify("Authorization group added", { type: "success" }); + setOpen(false); + }) + .catch((error) => { + notify(error.message, { type: "warning" }); + }); + }; + + return ( + + + + Add authorization group + + }> + + + + + + + + + ); +}; + +export default LicensePolicyAuthorizationGroupMemberAdd; diff --git a/frontend/src/licenses/license_policy_authorization_group_members/LicensePolicyAuthorizationGroupMemberEdit.tsx b/frontend/src/licenses/license_policy_authorization_group_members/LicensePolicyAuthorizationGroupMemberEdit.tsx new file mode 100644 index 000000000..ee880f3e8 --- /dev/null +++ b/frontend/src/licenses/license_policy_authorization_group_members/LicensePolicyAuthorizationGroupMemberEdit.tsx @@ -0,0 +1,96 @@ +import CancelIcon from "@mui/icons-material/Cancel"; +import EditIcon from "@mui/icons-material/Edit"; +import { Button, Dialog, DialogContent, DialogTitle } from "@mui/material"; +import { Fragment, useState } from "react"; +import { BooleanInput, SaveButton, SimpleForm, Toolbar, useNotify, useRefresh, useUpdate } from "react-admin"; + +import { TextInputWide } from "../../commons/layout/themes"; + +const LicensePolicyAuthorizationGroupMemberEdit = () => { + const [open, setOpen] = useState(false); + const [update] = useUpdate(); + const refresh = useRefresh(); + const notify = useNotify(); + const handleOpen = () => setOpen(true); + const handleCancel = () => setOpen(false); + const handleClose = (event: object, reason: string) => { + if (reason && reason == "backdropClick") return; + setOpen(false); + }; + + const member_update = async (data: any) => { + const patch = { + is_manager: data.is_manager, + }; + + update( + "license_policy_authorization_group_members", + + { + id: data.id, + data: patch, + }, + { + onSuccess: () => { + refresh(); + notify("Authorization group member updated", { + type: "success", + }); + }, + onError: (error: any) => { + notify(error.message, { + type: "warning", + }); + }, + } + ); + setOpen(false); + }; + + const CancelButton = () => ( + + ); + + const CustomToolbar = () => ( + + + + + ); + return ( + + + + Edit authorization group + + }> + + + + + + + ); +}; + +export default LicensePolicyAuthorizationGroupMemberEdit; diff --git a/frontend/src/licenses/license_policy_authorization_group_members/LicensePolicyAuthorizationGroupMemberEmbeddedList.tsx b/frontend/src/licenses/license_policy_authorization_group_members/LicensePolicyAuthorizationGroupMemberEmbeddedList.tsx new file mode 100644 index 000000000..1c81e6177 --- /dev/null +++ b/frontend/src/licenses/license_policy_authorization_group_members/LicensePolicyAuthorizationGroupMemberEmbeddedList.tsx @@ -0,0 +1,108 @@ +import { Stack } from "@mui/material"; +import { Fragment } from "react"; +import { + BooleanField, + Datagrid, + FilterForm, + Identifier, + ListContextProvider, + NullableBooleanInput, + ResourceContextProvider, + TextInput, + WithRecord, + useListController, +} from "react-admin"; + +import { CustomPagination } from "../../commons/custom_fields/CustomPagination"; +import TextUrlField from "../../commons/custom_fields/TextUrlField"; +import { is_superuser } from "../../commons/functions"; +import { getSettingListSize } from "../../commons/user_settings/functions"; +import LicensePolicyAuthorizationGroupMemberAdd from "./LicensePolicyAuthorizationGroupMemberAdd"; +import LicensePolicyAuthorizationGroupMemberEdit from "./LicensePolicyAuthorizationGroupMemberEdit"; +import LicensePolicyAuthorizationGroupMemberRemove from "./LicensePolicyAuthorizationGroupMemberRemove"; + +function listFilters() { + return [ + , + , + ]; +} + +const showAuthorizationGroup = (id: Identifier) => { + return "#/authorization_groups/" + id + "/show"; +}; + +type LicensePolicyAuthorizationGroupMemberEmbeddedListProps = { + license_policy: any; +}; + +const LicensePolicyAuthorizationGroupMemberEmbeddedList = ({ + license_policy, +}: LicensePolicyAuthorizationGroupMemberEmbeddedListProps) => { + const listContext = useListController({ + filter: { license_policy: Number(license_policy.id) }, + perPage: 25, + resource: "license_policy_authorization_group_members", + sort: { field: "authorization_group_data.name", order: "ASC" }, + filterDefaultValues: {}, + disableSyncWithLocation: true, + }); + + if (listContext.isLoading) { + return
Loading...
; + } + + return ( + + +
+ {(is_superuser() || license_policy.is_manager) && ( + + )} + {license_policy.has_authorization_groups && ( + + + + ( + + )} + /> + + {(is_superuser() || license_policy.is_manager) && ( + ( + + + + + )} + /> + )} + + + + )} +
+
+
+ ); +}; + +export default LicensePolicyAuthorizationGroupMemberEmbeddedList; diff --git a/frontend/src/licenses/license_policy_authorization_group_members/LicensePolicyAuthorizationGroupMemberRemove.tsx b/frontend/src/licenses/license_policy_authorization_group_members/LicensePolicyAuthorizationGroupMemberRemove.tsx new file mode 100644 index 000000000..37722ddf5 --- /dev/null +++ b/frontend/src/licenses/license_policy_authorization_group_members/LicensePolicyAuthorizationGroupMemberRemove.tsx @@ -0,0 +1,58 @@ +import DeleteIcon from "@mui/icons-material/Delete"; +import { useState } from "react"; +import { Button, Confirm, useNotify, useRefresh } from "react-admin"; + +import { httpClient } from "../../commons/ra-data-django-rest-framework"; + +type LicensePolicyAuthorizationGroupMemberRemoveProps = { + license_policy_authorization_group_member: any; +}; + +const LicensePolicyAuthorizationGroupMemberRemove = ({ + license_policy_authorization_group_member, +}: LicensePolicyAuthorizationGroupMemberRemoveProps) => { + const [open, setOpen] = useState(false); + const refresh = useRefresh(); + const notify = useNotify(); + const handleClick = () => setOpen(true); + const handleDialogClose = () => setOpen(false); + + const removeUser = async () => { + const url = + window.__RUNTIME_CONFIG__.API_BASE_URL + + "/license_policy_authorization_group_members/" + + license_policy_authorization_group_member.id + + "/"; + httpClient(url, { + method: "DELETE", + }) + .then(() => { + refresh(); + notify("Authorization group removed", { type: "success" }); + }) + .catch((error) => { + notify(error.message, { type: "warning" }); + }); + + setOpen(false); + }; + + return ( + <> +