From dc9b55625691b8c13b76603cbbafce90b0f9c1f8 Mon Sep 17 00:00:00 2001 From: Toby Drane Date: Mon, 4 Sep 2023 11:45:45 +0100 Subject: [PATCH] lint all files --- .env.example | 2 +- .github/workflows/dev.yml | 10 +- .github/workflows/main.yml | 4 +- .github/workflows/release.yml | 4 +- .../scheduled-vulnerability-check.yml | 11 +- .github/workflows/ui-tests.yml | 2 +- .gitignore | 2 +- README.md | 3 + SECURITY.md | 8 +- api/batect.yml | 18 +- api/static/main.css | 428 +++++++++++++++++- api/test/e2e/README.md | 2 +- .../test_e2e_protected-do_not_delete.json | 118 ++--- docs/api/routes/client.md | 18 +- docs/api/routes/dataset.md | 92 ++-- docs/api/routes/permissions.md | 16 +- docs/api/routes/protected_domain.md | 11 +- docs/api/routes/schema.md | 16 +- docs/api/routes/subject.md | 16 +- docs/api/routes/user.md | 24 +- docs/api/schema.md | 45 +- docs/api/usage.md | 4 +- docs/getting_started.md | 2 - docs/index.md | 1 - docs/infrastructure/deployment.md | 14 +- docs/infrastructure/diagrams.md | 2 +- docs/infrastructure/domains_subdomains.md | 14 +- docs/ui/todo.md | 2 +- infrastructure/batect.yml | 2 +- .../blocks/pipeline-ami/provider.tf | 1 - .../blocks/pipeline-ami/template.json | 104 ++--- infrastructure/blocks/pipeline/iam.tf | 19 +- .../pipeline/initialisation-script.sh.tpl | 2 +- infrastructure/modules/app-cluster/README.md | 222 ++++----- infrastructure/modules/auth/README.md | 130 +++--- .../modules/data-workflow/README.md | 80 ++-- infrastructure/modules/rapid/README.md | 84 ++-- infrastructure/modules/rapid/main.tf | 2 +- infrastructure/modules/ui/README.md | 100 ++-- infrastructure/modules/ui/scripts/ui.sh.tpl | 2 +- mkdocs.yml | 58 +-- sdk/rapid/__init__.py | 4 +- ui/.storybook/preview-head.html | 6 +- ui/playwright/test-data-flow.spec.ts | 6 +- ui/playwright/utils.ts | 12 +- ui/src/__tests__/data/delete.test.tsx | 16 +- ui/src/__tests__/data/download.test.tsx | 9 +- ui/src/__tests__/data/upload.test.tsx | 18 +- ui/src/__tests__/schema/create.test.tsx | 8 +- ui/src/__tests__/subject/create.test.tsx | 17 +- .../components/Autocomplete/Autocomplete.tsx | 42 +- .../DatasetSelector/DatasetSelector.tsx | 81 ++-- ui/src/components/FormControl/FormControl.tsx | 17 +- .../PermissionsTable/PermissionsTable.tsx | 26 +- ui/src/components/SchemaCreate.tsx | 47 +- ui/src/components/Select/Select.tsx | 3 +- .../UploadProgress/UploadProgress.tsx | 126 +++--- ui/src/pages/data/delete/index.tsx | 6 +- .../download/[layer]/[domain]/[dataset].tsx | 5 +- ui/src/pages/data/download/index.tsx | 29 +- ui/src/pages/data/upload/index.tsx | 44 +- ui/src/pages/schema/create/index.tsx | 19 +- ui/src/pages/subject/create/index.tsx | 12 +- ui/src/pages/subject/modify/[subjectId].tsx | 14 +- ui/src/service/fetch.ts | 17 +- ui/src/service/permissions.ts | 38 +- ui/src/service/schema.ts | 28 +- ui/src/service/types.ts | 6 +- ui/src/utils/data.ts | 2 +- ui/src/utils/testing.tsx | 54 ++- 70 files changed, 1440 insertions(+), 967 deletions(-) diff --git a/.env.example b/.env.example index b0399a9..95657e4 100644 --- a/.env.example +++ b/.env.example @@ -20,4 +20,4 @@ NEXT_PUBLIC_API_URL_PROXY= # UI Specific for integration tests DOMAIN= -RESOURCE_PREFIX= \ No newline at end of file +RESOURCE_PREFIX= diff --git a/.github/workflows/dev.yml b/.github/workflows/dev.yml index 3835c6e..72c4d25 100644 --- a/.github/workflows/dev.yml +++ b/.github/workflows/dev.yml @@ -3,7 +3,7 @@ name: rAPId Dev Deployment on: push: branches: - - "**" + - '**' workflow_dispatch: @@ -25,8 +25,8 @@ jobs: - name: Setup Python uses: actions/setup-python@v4 with: - python-version: "3.10" - cache: "pip" + python-version: '3.10' + cache: 'pip' - run: pip install -r requirements.txt @@ -79,8 +79,8 @@ jobs: - name: Setup Python uses: actions/setup-python@v4 with: - python-version: "3.10" - cache: "pip" + python-version: '3.10' + cache: 'pip' - name: Setup Python Environment run: | diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 65a0807..c82597a 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -24,8 +24,8 @@ jobs: - name: Setup Python uses: actions/setup-python@v4 with: - python-version: "3.10" - cache: "pip" + python-version: '3.10' + cache: 'pip' - run: pip install -r requirements.txt diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1b432be..e1997dd 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -51,8 +51,8 @@ jobs: - name: Setup Python uses: actions/setup-python@v4 with: - python-version: "3.10" - cache: "pip" + python-version: '3.10' + cache: 'pip' - name: Setup Python Environment run: | diff --git a/.github/workflows/scheduled-vulnerability-check.yml b/.github/workflows/scheduled-vulnerability-check.yml index d23d235..cba5212 100644 --- a/.github/workflows/scheduled-vulnerability-check.yml +++ b/.github/workflows/scheduled-vulnerability-check.yml @@ -1,7 +1,7 @@ name: Scheduled api vulnerability scan results check on: schedule: - - cron: "0 9,15 * * *" + - cron: '0 9,15 * * *' workflow_dispatch: @@ -13,16 +13,13 @@ jobs: - uses: actions/checkout@v3 - name: Export env vars - run: - cp ./.github/.github.env .env + run: cp ./.github/.github.env .env - name: Export AWS_ACCOUNT - run: - echo AWS_ACCOUNT=${{ secrets.AWS_ACCOUNT }} >> .env + run: echo AWS_ACCOUNT=${{ secrets.AWS_ACCOUNT }} >> .env - name: Export AWS_REGION - run: - echo AWS_REGION=${{ secrets.AWS_REGION }} >> .env + run: echo AWS_REGION=${{ secrets.AWS_REGION }} >> .env - name: Check for vulnerabilities run: make api-scheduled-prod-scan diff --git a/.github/workflows/ui-tests.yml b/.github/workflows/ui-tests.yml index adadd61..6a88e87 100644 --- a/.github/workflows/ui-tests.yml +++ b/.github/workflows/ui-tests.yml @@ -31,6 +31,6 @@ jobs: - name: Run playwright tests run: make ui-test-e2e env: - DOMAIN_NAME: "https://${{ secrets.DOMAIN_NAME }}" + DOMAIN_NAME: 'https://${{ secrets.DOMAIN_NAME }}' RESOURCE_PREFIX: ${{ secrets.RESOURCE_PREFIX }} AWS_REGION: ${{ secrets.AWS_REGION }} diff --git a/.gitignore b/.gitignore index b8e63d4..b0a0c68 100644 --- a/.gitignore +++ b/.gitignore @@ -184,4 +184,4 @@ docs/_build/ ui/playwright/.auth ui/playwright/.downloads -ui/test-results/ \ No newline at end of file +ui/test-results/ diff --git a/README.md b/README.md index b32278d..64f2912 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,7 @@ # Project rAPId + ![Deployment Pipeline](https://github.com/no10ds/rapid/actions/workflows/main.yml/badge.svg) @@ -37,9 +38,11 @@ Or you can consult the [Infrastructure Repo](https://github.com/no10ds/rapid/tre # Developing This is a quick guide to running rAPId locally for development. + ## Prerequisites Install all the required tools + - jq (use Homebrew) - Git - [pre-commit](https://pre-commit.com) diff --git a/SECURITY.md b/SECURITY.md index 24d30da..8438b79 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -11,22 +11,27 @@ Cabinet Office and No10 are advocates of responsible vulnerability disclosure. I You can report a vulnerability through our vulnerability disclosure programme at [HackerOne](https://hackerone.com/44c348eb-e030-4273-b445-d4a2f6f83ba8/embedded_submissions/new). Alternatively, you can send an email to [disclosure@digital.cabinet-office.gov.uk](mailto:disclosure@digital.cabinet-office.gov.uk); if you do this you may get a response from Zendesk, which is our ticketing system. When reporting a vulnerability to us, please include: + - the website, page or repository where the vulnerability can be observed - a brief description of the vulnerability - details of the steps we need to take to reproduce the vulnerability - non-destructive exploitation details If you are able to, please also include: + - the type of vulnerability, for example, the [OWASP category](https://owasp.org/www-community/vulnerabilities/) - screenshots or logs showing the exploitation of the vulnerability [Reach out via email](mailto:disclosure@digital.cabinet-office.gov.uk) if you are not sure if the vulnerability is genuine and exploitable, or you have found: + - a non-exploitable vulnerability - something you think could be improved - for example, missing security headers - TLS configuration weaknesses - for example weak cipher suite support or the presence of TLS1.0 support ## Guidelines for reporting a vulnerability + When you are investigating and reporting the vulnerability on a gov.uk domain or subdomain, you must not: + - break the law - access unnecessary or excessive amounts of data - modify data @@ -40,17 +45,18 @@ When you are investigating and reporting the vulnerability on a gov.uk domain or Only submit reports about exploitable vulnerabilities through HackerOne. ## Bug bounty + Unfortunately, Cabinet Office and No10 do not offer a paid bug bounty programme. We will make efforts to show appreciation to people who take the time and effort to disclose vulnerabilities responsibly. We do have [an acknowledgements page for legitimate issues found by researchers](https://vdp.cabinetoffice.gov.uk/thanks.txt). --- #### Further reading and inspiration about responsible disclosure and `SECURITY.md` + - - - - - - [CODE_OF_CONDUCT.md]: https://github.com/alphagov/.github/blob/master/CODE_OF_CONDUCT.md [OWASP category]: https://www.owasp.org/index.php/Category:OWASP_Top_Ten_2017_Project diff --git a/api/batect.yml b/api/batect.yml index da28282..68fd7f0 100644 --- a/api/batect.yml +++ b/api/batect.yml @@ -64,19 +64,19 @@ tasks: ports: - local: 8000 container: 8000 - command: "uvicorn api.entry:app --host 0.0.0.0 --port 8000 --reload" + command: 'uvicorn api.entry:app --host 0.0.0.0 --port 8000 --reload' test-unit: description: Run unit tests run: container: service-image - command: "pytest test/api -vv -s" + command: 'pytest test/api -vv -s' test-unit-focus: description: Run unit tests run: container: service-image - command: "pytest test/api -vv -m focus" + command: 'pytest test/api -vv -m focus' test-e2e: description: Run E2E tests @@ -86,7 +86,7 @@ tasks: AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID:-} AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY:-} AWS_SESSION_TOKEN: ${AWS_SESSION_TOKEN:-} - command: "pytest test/e2e -v" + command: 'pytest test/e2e -v' test-e2e-focus: description: Run E2E tests in focus mode @@ -96,28 +96,28 @@ tasks: AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID:-} AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY:-} AWS_SESSION_TOKEN: ${AWS_SESSION_TOKEN:-} - command: "pytest test/e2e -v -m focus" + command: 'pytest test/e2e -v -m focus' test-coverage: description: Run all tests with coverage report for source code only run: container: service-image - command: "pytest --durations=5 --cov=api --cov-report term-missing test/api" + command: 'pytest --durations=5 --cov=api --cov-report term-missing test/api' lint: description: Lint the source and test code run: container: service-image - command: "flake8 api test" + command: 'flake8 api test' format: description: Format the source and test code run: container: service-image - command: "black api test" + command: 'black api test' generate_latest_changelog: description: Parse the changelog file for the release's changes run: container: service-image - command: "python get_latest_release_changelog.py" + command: 'python get_latest_release_changelog.py' diff --git a/api/static/main.css b/api/static/main.css index bdfd8b6..6883b6e 100644 --- a/api/static/main.css +++ b/api/static/main.css @@ -1 +1,427 @@ -:root{--success: #0dc988;--failure: #c90d4e;--neutral: #00aeff;--success-text: #0dc988;--error-text: #c90d4e;--pink: #eb2f64;--light-pink: #FF3366;--dark-pink: #BA265D;--light-grey-pink: #f1e4ef;--light-grey-1: #faf9f9;--light-grey-2: #f4f2f2;--light-grey-3: #f0eeee;--light-grey-4: #ccc;--dark-grey-1: #333;--dark-grey-2: #777;--dark-grey-3: #999;--dark-shadow: 0 1rem 1rem rgba(0,0,0,.3);--light-shadow: 0 1rem 1rem rgba(0,0,0,.1);--grey-border-bottom-1: 1px solid var(--light-grey-2)}*,*::before,*::after{margin:0;padding:0;box-sizing:inherit}html{box-sizing:border-box;font-size:62.5%}body{font-family:'Open Sans', sans-serif;font-weight:400;line-height:1.6;color:var(--dark-grey-2);background-image:linear-gradient(to right bottom, var(--light-pink), var(--dark-pink));background-size:cover;background-repeat:no-repeat;min-height:100vh}.content{display:grid;grid-template-rows:[header-start] 20vh [header-end content-start] 30vh min-content [content-end footer-start] 10vh [footer-end];grid-template-columns:[full-start] minmax(6rem, 1fr) [center-start] repeat(8, [col-start] minmax(min-content, 14rem) [col-end]) [center-end] minmax(6rem, 1fr) [full-end]}.content_body{font-size:1.6rem;border-radius:1rem;grid-row-start:content-start;grid-row-end:content-end;grid-column-start:center-start;grid-column-end:center-end;display:grid;background-color:var(--light-grey-1);text-align:center;grid-template-rows:minmax(5rem, 1fr) minmax(5rem, 0.5fr)}.content_body--small{grid-template-rows:min-content minmax(min-content, 1fr)}.content-menu{align-content:space-around;display:grid;grid-template-rows:repeat(2, minmax(min-content, 2rem))}.content_header{padding:3rem;align-self:start}.form{font-size:1.6rem;border-radius:1rem;grid-row-start:content-start;grid-row-end:content-end;grid-column-start:center-start;grid-column-end:center-end;display:grid;background-color:var(--light-grey-1);text-align:center;grid-template-rows:minmax(10rem, 1fr) minmax(5rem, min-content);grid-row-gap:2rem}.form_body:not([hidden]){display:grid;grid-template-rows:repeat(2, minmax(5rem, 1fr));grid-row-gap:2rem}.form_body--headed:not([hidden]){grid-template-rows:auto}.form_submit:not([hidden]){display:grid;text-align:center;justify-items:center;align-items:center;grid-template-rows:minmax(2rem, min-content) minmax(3rem, 1fr) minmax(2rem, min-content);grid-row-gap:.6rem;margin:2rem 0}.form--logout{display:grid;grid-column-start:8;grid-column-end:center-end;justify-items:end;align-items:center}.form_helper-text{font-size:1.3rem;padding-bottom:.6rem}.form-select:not([hidden]){display:grid;justify-items:center;align-items:center}.form-select_dropdown{border-radius:.5rem;padding:.5rem;width:50%;box-shadow:var(--light-shadow);align-self:start;cursor:pointer}.form-select_dropdown_table{background-color:var(--light-grey-1);border:none;text-align-last:left;color:var(--dark-grey-2)}.form-checkbox:not([hidden]),.form-radio:not([hidden]){display:grid;grid-template-columns:repeat(auto-fit, minmax(min-content, 50%));grid-template-rows:auto;justify-content:space-around;align-content:center;grid-row-gap:1rem}.form-checkbox_input,.form-radio_input{display:grid;grid-template-columns:repeat(2, min-content);grid-column-gap:.5rem;justify-content:center}.form-checkbox_input label,.form-checkbox_input input,.form-radio_input label,.form-radio_input input{cursor:pointer}.form-checkbox_input label,.form-radio_input label{line-height:100%;padding:.2rem 0}.form-checkbox_legend,.form-radio_legend{padding:0 .5rem .5rem;font-weight:600}.form-input:not([hidden]){display:grid;align-items:start;justify-items:center}.form-input_label:hover{cursor:pointer}.form-input_error{color:var(--error-text)}.form-input_file{display:none}.form-input_text{min-width:40%;border-style:solid;border-color:var(--dark-grey-3);box-shadow:var(--light-shadow);border-radius:.5rem;font-size:1.8rem;text-align:center;padding:.8rem}.form-input_text--row{width:60%}.form-input_legend{padding:0 .5rem .5rem;font-weight:600}.form-input_text::placeholder{color:var(--light-grey-4);font-style:italic}.form-input--row:not([hidden]){display:flex;text-align:start;align-items:center;justify-content:space-between;width:80%;margin:1.5rem auto}.form-input_input_text{border-radius:.5rem;padding:.5rem;width:50%;align-self:start;cursor:pointer;background-color:var(--light-grey-1);border:1px solid var(--dark-grey-2)}.key-value-input:not([hidden]){display:grid;width:40%;grid-row-gap:5px}.key-value-input--row{display:grid;grid-template-columns:1fr 1fr 20px;grid-column-gap:10px}.key-input:not([hidden]){display:grid;width:40%;grid-row-gap:5px}.key-input--row{display:grid;grid-template-columns:1fr 20px;grid-column-gap:10px}.login{display:grid;justify-items:center;align-items:start}a.btn{text-decoration:none}a.btn--back{grid-row-start:header-start;grid-row-end:header-end;grid-column-start:center-start;grid-column-end:col-start;font-size:1.4rem;color:var(--light-grey-1);align-self:center}a.btn--discreet{color:var(--dark-grey-2)}a.link{color:var(--pink)}a.link:focus,a.link :active,a.link :hover{color:var(--dark-pink)}input.invalid{border-color:var(--error-text)}fieldset{border-color:var(--light-grey-4);margin:0 auto;border-width:0;border-top-width:2px;width:70%;padding-bottom:1rem}ul{padding:0 2rem}ul>li{text-align:left;max-width:80%;margin:0 auto}ul>li.clean{list-style:none}ul>li.center{text-align:center}.highlight{color:var(--pink)}.bold{font-weight:bold}.btn-set{padding-bottom:3rem;display:grid;grid-template-rows:repeat(2, min-content);grid-row-gap:1.5rem;justify-items:center}.btn{font-size:1.6rem;font-weight:600;border-radius:.8rem;border-style:none;padding:.6rem 0;width:80%;background-color:var(--light-pink);color:var(--light-grey-1);box-shadow:var(--light-shadow)}.btn:disabled{pointer-events:none;background-color:var(--dark-grey-2)}.btn:hover{background-color:var(--dark-pink);color:var(--light-grey-1);box-shadow:var(--dark-shadow);cursor:pointer}.btn:active{transform:translateY(0.2rem);background-color:var(--light-grey-4);color:var(--light-pink);box-shadow:var(--dark-shadow);cursor:pointer}.btn--secondary{background-color:var(--light-grey-1);color:var(--pink);border-style:solid;border-color:var(--pink);padding:.6rem 1rem;width:20%;min-width:min-content}.btn--secondary:hover,.btn--secondary:active{background-color:var(--light-grey-2);color:var(--dark-pink);border-color:var(--dark-pink)}.btn--medium{width:60%}.response-msg{align-self:start;padding:0 1rem 1rem}.response-msg--error{color:var(--error-text)}.response-msg--success{color:var(--success-text)}.status-icon{width:4.5rem;height:4.5rem}.rotating{animation:spin 2s linear infinite}@keyframes spin{from{transform:rotate(0deg)}to{transform:rotate(360deg)}}.info-table{margin-left:auto;margin-right:auto;min-width:60%;max-width:90%;border-collapse:collapse}.info-table tr{border:1px solid var(--light-grey-4)}.info-table tr :first-child{text-align:left}.info-table tr :last-child{text-align:right}.info-table td,.info-table th{padding:.25rem 1rem}.info-table td img,.info-table th img{display:block;margin:0 auto}.info-table_status-icon{max-height:3.25rem;aspect-ratio:1}.info-table--left{text-align:left}.loading-spinner{display:none;width:50px;height:50px;border:5px solid var(--light-grey-pink);border-radius:50%;border-top-color:var(--pink);animation:spin 1s ease-in-out infinite;text-align:center}@keyframes spin{to{-webkit-transform:rotate(360deg)}} +:root { + --success: #0dc988; + --failure: #c90d4e; + --neutral: #00aeff; + --success-text: #0dc988; + --error-text: #c90d4e; + --pink: #eb2f64; + --light-pink: #ff3366; + --dark-pink: #ba265d; + --light-grey-pink: #f1e4ef; + --light-grey-1: #faf9f9; + --light-grey-2: #f4f2f2; + --light-grey-3: #f0eeee; + --light-grey-4: #ccc; + --dark-grey-1: #333; + --dark-grey-2: #777; + --dark-grey-3: #999; + --dark-shadow: 0 1rem 1rem rgba(0, 0, 0, 0.3); + --light-shadow: 0 1rem 1rem rgba(0, 0, 0, 0.1); + --grey-border-bottom-1: 1px solid var(--light-grey-2); +} +*, +*::before, +*::after { + margin: 0; + padding: 0; + box-sizing: inherit; +} +html { + box-sizing: border-box; + font-size: 62.5%; +} +body { + font-family: 'Open Sans', sans-serif; + font-weight: 400; + line-height: 1.6; + color: var(--dark-grey-2); + background-image: linear-gradient(to right bottom, var(--light-pink), var(--dark-pink)); + background-size: cover; + background-repeat: no-repeat; + min-height: 100vh; +} +.content { + display: grid; + grid-template-rows: [header-start] 20vh [header-end content-start] 30vh min-content [content-end footer-start] 10vh [footer-end]; + grid-template-columns: + [full-start] minmax(6rem, 1fr) [center-start] repeat( + 8, + [col-start] minmax(min-content, 14rem) [col-end] + ) + [center-end] minmax(6rem, 1fr) [full-end]; +} +.content_body { + font-size: 1.6rem; + border-radius: 1rem; + grid-row-start: content-start; + grid-row-end: content-end; + grid-column-start: center-start; + grid-column-end: center-end; + display: grid; + background-color: var(--light-grey-1); + text-align: center; + grid-template-rows: minmax(5rem, 1fr) minmax(5rem, 0.5fr); +} +.content_body--small { + grid-template-rows: min-content minmax(min-content, 1fr); +} +.content-menu { + align-content: space-around; + display: grid; + grid-template-rows: repeat(2, minmax(min-content, 2rem)); +} +.content_header { + padding: 3rem; + align-self: start; +} +.form { + font-size: 1.6rem; + border-radius: 1rem; + grid-row-start: content-start; + grid-row-end: content-end; + grid-column-start: center-start; + grid-column-end: center-end; + display: grid; + background-color: var(--light-grey-1); + text-align: center; + grid-template-rows: minmax(10rem, 1fr) minmax(5rem, min-content); + grid-row-gap: 2rem; +} +.form_body:not([hidden]) { + display: grid; + grid-template-rows: repeat(2, minmax(5rem, 1fr)); + grid-row-gap: 2rem; +} +.form_body--headed:not([hidden]) { + grid-template-rows: auto; +} +.form_submit:not([hidden]) { + display: grid; + text-align: center; + justify-items: center; + align-items: center; + grid-template-rows: minmax(2rem, min-content) minmax(3rem, 1fr) minmax( + 2rem, + min-content + ); + grid-row-gap: 0.6rem; + margin: 2rem 0; +} +.form--logout { + display: grid; + grid-column-start: 8; + grid-column-end: center-end; + justify-items: end; + align-items: center; +} +.form_helper-text { + font-size: 1.3rem; + padding-bottom: 0.6rem; +} +.form-select:not([hidden]) { + display: grid; + justify-items: center; + align-items: center; +} +.form-select_dropdown { + border-radius: 0.5rem; + padding: 0.5rem; + width: 50%; + box-shadow: var(--light-shadow); + align-self: start; + cursor: pointer; +} +.form-select_dropdown_table { + background-color: var(--light-grey-1); + border: none; + text-align-last: left; + color: var(--dark-grey-2); +} +.form-checkbox:not([hidden]), +.form-radio:not([hidden]) { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(min-content, 50%)); + grid-template-rows: auto; + justify-content: space-around; + align-content: center; + grid-row-gap: 1rem; +} +.form-checkbox_input, +.form-radio_input { + display: grid; + grid-template-columns: repeat(2, min-content); + grid-column-gap: 0.5rem; + justify-content: center; +} +.form-checkbox_input label, +.form-checkbox_input input, +.form-radio_input label, +.form-radio_input input { + cursor: pointer; +} +.form-checkbox_input label, +.form-radio_input label { + line-height: 100%; + padding: 0.2rem 0; +} +.form-checkbox_legend, +.form-radio_legend { + padding: 0 0.5rem 0.5rem; + font-weight: 600; +} +.form-input:not([hidden]) { + display: grid; + align-items: start; + justify-items: center; +} +.form-input_label:hover { + cursor: pointer; +} +.form-input_error { + color: var(--error-text); +} +.form-input_file { + display: none; +} +.form-input_text { + min-width: 40%; + border-style: solid; + border-color: var(--dark-grey-3); + box-shadow: var(--light-shadow); + border-radius: 0.5rem; + font-size: 1.8rem; + text-align: center; + padding: 0.8rem; +} +.form-input_text--row { + width: 60%; +} +.form-input_legend { + padding: 0 0.5rem 0.5rem; + font-weight: 600; +} +.form-input_text::placeholder { + color: var(--light-grey-4); + font-style: italic; +} +.form-input--row:not([hidden]) { + display: flex; + text-align: start; + align-items: center; + justify-content: space-between; + width: 80%; + margin: 1.5rem auto; +} +.form-input_input_text { + border-radius: 0.5rem; + padding: 0.5rem; + width: 50%; + align-self: start; + cursor: pointer; + background-color: var(--light-grey-1); + border: 1px solid var(--dark-grey-2); +} +.key-value-input:not([hidden]) { + display: grid; + width: 40%; + grid-row-gap: 5px; +} +.key-value-input--row { + display: grid; + grid-template-columns: 1fr 1fr 20px; + grid-column-gap: 10px; +} +.key-input:not([hidden]) { + display: grid; + width: 40%; + grid-row-gap: 5px; +} +.key-input--row { + display: grid; + grid-template-columns: 1fr 20px; + grid-column-gap: 10px; +} +.login { + display: grid; + justify-items: center; + align-items: start; +} +a.btn { + text-decoration: none; +} +a.btn--back { + grid-row-start: header-start; + grid-row-end: header-end; + grid-column-start: center-start; + grid-column-end: col-start; + font-size: 1.4rem; + color: var(--light-grey-1); + align-self: center; +} +a.btn--discreet { + color: var(--dark-grey-2); +} +a.link { + color: var(--pink); +} +a.link:focus, +a.link :active, +a.link :hover { + color: var(--dark-pink); +} +input.invalid { + border-color: var(--error-text); +} +fieldset { + border-color: var(--light-grey-4); + margin: 0 auto; + border-width: 0; + border-top-width: 2px; + width: 70%; + padding-bottom: 1rem; +} +ul { + padding: 0 2rem; +} +ul > li { + text-align: left; + max-width: 80%; + margin: 0 auto; +} +ul > li.clean { + list-style: none; +} +ul > li.center { + text-align: center; +} +.highlight { + color: var(--pink); +} +.bold { + font-weight: bold; +} +.btn-set { + padding-bottom: 3rem; + display: grid; + grid-template-rows: repeat(2, min-content); + grid-row-gap: 1.5rem; + justify-items: center; +} +.btn { + font-size: 1.6rem; + font-weight: 600; + border-radius: 0.8rem; + border-style: none; + padding: 0.6rem 0; + width: 80%; + background-color: var(--light-pink); + color: var(--light-grey-1); + box-shadow: var(--light-shadow); +} +.btn:disabled { + pointer-events: none; + background-color: var(--dark-grey-2); +} +.btn:hover { + background-color: var(--dark-pink); + color: var(--light-grey-1); + box-shadow: var(--dark-shadow); + cursor: pointer; +} +.btn:active { + transform: translateY(0.2rem); + background-color: var(--light-grey-4); + color: var(--light-pink); + box-shadow: var(--dark-shadow); + cursor: pointer; +} +.btn--secondary { + background-color: var(--light-grey-1); + color: var(--pink); + border-style: solid; + border-color: var(--pink); + padding: 0.6rem 1rem; + width: 20%; + min-width: min-content; +} +.btn--secondary:hover, +.btn--secondary:active { + background-color: var(--light-grey-2); + color: var(--dark-pink); + border-color: var(--dark-pink); +} +.btn--medium { + width: 60%; +} +.response-msg { + align-self: start; + padding: 0 1rem 1rem; +} +.response-msg--error { + color: var(--error-text); +} +.response-msg--success { + color: var(--success-text); +} +.status-icon { + width: 4.5rem; + height: 4.5rem; +} +.rotating { + animation: spin 2s linear infinite; +} +@keyframes spin { + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } +} +.info-table { + margin-left: auto; + margin-right: auto; + min-width: 60%; + max-width: 90%; + border-collapse: collapse; +} +.info-table tr { + border: 1px solid var(--light-grey-4); +} +.info-table tr :first-child { + text-align: left; +} +.info-table tr :last-child { + text-align: right; +} +.info-table td, +.info-table th { + padding: 0.25rem 1rem; +} +.info-table td img, +.info-table th img { + display: block; + margin: 0 auto; +} +.info-table_status-icon { + max-height: 3.25rem; + aspect-ratio: 1; +} +.info-table--left { + text-align: left; +} +.loading-spinner { + display: none; + width: 50px; + height: 50px; + border: 5px solid var(--light-grey-pink); + border-radius: 50%; + border-top-color: var(--pink); + animation: spin 1s ease-in-out infinite; + text-align: center; +} +@keyframes spin { + to { + -webkit-transform: rotate(360deg); + } +} diff --git a/api/test/e2e/README.md b/api/test/e2e/README.md index cf30d25..db4d54f 100644 --- a/api/test/e2e/README.md +++ b/api/test/e2e/README.md @@ -9,7 +9,7 @@ performed that require the relevant resources to be available in AWS (files in S Run [this](./setup_e2e_tests.py) script, passing in values for the environment variables listed below. -``` bash +```bash CLIENT_ID CLIENT_SECRET BASE_URL diff --git a/api/test/e2e/test_files/schemas/test_e2e_protected-do_not_delete.json b/api/test/e2e/test_files/schemas/test_e2e_protected-do_not_delete.json index c67347c..eacc553 100644 --- a/api/test/e2e/test_files/schemas/test_e2e_protected-do_not_delete.json +++ b/api/test/e2e/test_files/schemas/test_e2e_protected-do_not_delete.json @@ -1,62 +1,62 @@ { - "metadata": { - "layer": "default", - "domain": "test_e2e_protected", - "dataset": "do_not_delete", - "sensitivity": "PROTECTED", - "description": "A test dataset", - "key_value_tags": {}, - "key_only_tags": [], - "owners": [ - { - "name": "test_e2e_protected", - "email": "test_e2e_protected@email.com" - } - ], - "update_behaviour": "OVERWRITE" + "metadata": { + "layer": "default", + "domain": "test_e2e_protected", + "dataset": "do_not_delete", + "sensitivity": "PROTECTED", + "description": "A test dataset", + "key_value_tags": {}, + "key_only_tags": [], + "owners": [ + { + "name": "test_e2e_protected", + "email": "test_e2e_protected@email.com" + } + ], + "update_behaviour": "OVERWRITE" + }, + "columns": [ + { + "name": "year", + "partition_index": null, + "data_type": "int", + "allow_null": true, + "format": null }, - "columns": [ - { - "name": "year", - "partition_index": null, - "data_type": "int", - "allow_null": true, - "format": null - }, - { - "name": "month", - "partition_index": null, - "data_type": "int", - "allow_null": true, - "format": null - }, - { - "name": "destination", - "partition_index": null, - "data_type": "string", - "allow_null": true, - "format": null - }, - { - "name": "arrival", - "partition_index": null, - "data_type": "string", - "allow_null": true, - "format": null - }, - { - "name": "type", - "partition_index": null, - "data_type": "string", - "allow_null": true, - "format": null - }, - { - "name": "status", - "partition_index": null, - "data_type": "string", - "allow_null": true, - "format": null - } - ] + { + "name": "month", + "partition_index": null, + "data_type": "int", + "allow_null": true, + "format": null + }, + { + "name": "destination", + "partition_index": null, + "data_type": "string", + "allow_null": true, + "format": null + }, + { + "name": "arrival", + "partition_index": null, + "data_type": "string", + "allow_null": true, + "format": null + }, + { + "name": "type", + "partition_index": null, + "data_type": "string", + "allow_null": true, + "format": null + }, + { + "name": "status", + "partition_index": null, + "data_type": "string", + "allow_null": true, + "format": null + } + ] } diff --git a/docs/api/routes/client.md b/docs/api/routes/client.md index 4096438..88cbf39 100644 --- a/docs/api/routes/client.md +++ b/docs/api/routes/client.md @@ -12,17 +12,14 @@ As a maintainer of a rAPId you can create new clients to interact with the API t ### Inputs -| Parameters | Usage | Example values | Definition | -|------------------|---------------------|------------------|---------------------------------------------------------------------------| -| `client details` | JSON Request Body | See below | The name of the client application to onboard and the granted permissions | +| Parameters | Usage | Example values | Definition | +| ---------------- | ----------------- | -------------- | ------------------------------------------------------------------------- | +| `client details` | JSON Request Body | See below | The name of the client application to onboard and the granted permissions | ```json { - "client_name": "department_for_education", - "permissions": [ - "READ_ALL", - "WRITE_PUBLIC" - ] + "client_name": "department_for_education", + "permissions": ["READ_ALL", "WRITE_PUBLIC"] } ``` @@ -42,10 +39,7 @@ Once the new client has been created, the following information is returned in t ```json { "client_name": "department_for_education", - "permissions": [ - "READ_ALL", - "WRITE_PUBLIC" - ], + "permissions": ["READ_ALL", "WRITE_PUBLIC"], "client_id": "1234567890-abcdefghijk", "client_secret": "987654321" } diff --git a/docs/api/routes/dataset.md b/docs/api/routes/dataset.md index f1c157d..089919a 100644 --- a/docs/api/routes/dataset.md +++ b/docs/api/routes/dataset.md @@ -15,7 +15,7 @@ You will need a relevant `WRITE` permission that matches the dataset senstivity ### Inputs | Parameters | Required | Usage | Example values | Definition | -|------------|----------|-----------------------------------------|-----------------------------|-------------------------| +| ---------- | -------- | --------------------------------------- | --------------------------- | ----------------------- | | `layer` | True | URL parameter | `default` | layer of the dataset | | `domain` | True | URL parameter | `air` | domain of the dataset | | `dataset` | True | URL parameter | `passengers_by_airport` | dataset title | @@ -52,11 +52,11 @@ Use this endpoint to delete all the contents linked to a layer/domain/dataset. I ### Inputs -| Parameters | Required | Usage | Example values | Definition | -|------------|----------|---------------|---------------------------------|-------------------------------| -| `layer` | True | URL parameter | `raw` | layer of the dataset | -| `domain` | True | URL parameter | `land` | domain of the dataset | -| `dataset` | True | URL parameter | `train_journeys` | dataset title | +| Parameters | Required | Usage | Example values | Definition | +| ---------- | -------- | ------------- | ---------------- | --------------------- | +| `layer` | True | URL parameter | `raw` | layer of the dataset | +| `domain` | True | URL parameter | `land` | domain of the dataset | +| `dataset` | True | URL parameter | `train_journeys` | dataset title | ### Outputs @@ -64,7 +64,7 @@ If successful returns the dataset has been deleted ```json { - "details": "{dataset} has been deleted." + "details": "{dataset} has been deleted." } ``` @@ -86,7 +86,7 @@ You will need a relevant `WRITE` permission that matches the dataset senstivity ### Inputs | Parameters | Required | Usage | Example values | Definition | -|------------|----------|---------------|---------------------------------|-------------------------------| +| ---------- | -------- | ------------- | ------------------------------- | ----------------------------- | | `layer` | True | URL parameter | `raw` | layer of the dataset | | `domain` | True | URL parameter | `land` | domain of the dataset | | `dataset` | True | URL parameter | `train_journeys` | dataset title | @@ -99,7 +99,7 @@ If successful returns the file has been deleted ```json { - "details": "{filename} has been deleted." + "details": "{filename} has been deleted." } ``` @@ -112,7 +112,6 @@ If you do not specify any filter values, you will retrieve all available dataset You can optionally enrich the information returned, this will include values like `Last Updated Time`, `Description` and `Tags`. - ### Required Permissions None @@ -123,11 +122,10 @@ None ### Inputs -| Parameters | Required| Usage | Example values | Definition | -|---------------|---------|-----------------------------------------|------------------------------------------------------------------------------------------------------- |-----------------------| -| enriched | False | Boolean Query parameter | True | enriches the metadata | -| query | False | JSON Request Body | Consult the [docs](https://github.com/no10ds/rapid-api/blob/main/docs/guides/usage/usage.md#examples-2)| the filtering query | - +| Parameters | Required | Usage | Example values | Definition | +| ---------- | -------- | ----------------------- | ------------------------------------------------------------------------------------------------------- | --------------------- | +| enriched | False | Boolean Query parameter | True | enriches the metadata | +| query | False | JSON Request Body | Consult the [docs](https://github.com/no10ds/rapid-api/blob/main/docs/guides/usage/usage.md#examples-2) | the filtering query | ### Outputs @@ -181,22 +179,19 @@ None ### Inputs -| Parameters | Required | Usage | Example values | Definition | -|---------------|-----------|-----------------------------------------|------------------------------|-----------------------| -| `layer` | True | URL parameter | `raw` | layer of the dataset | -| `domain` | True | URL parameter | `land` | domain of the dataset | -| `dataset` | True | URL parameter | `train_journeys` | dataset title | -| `version` | True | URL parameter | `3` | dataset version | +| Parameters | Required | Usage | Example values | Definition | +| ---------- | -------- | ------------- | ---------------- | --------------------- | +| `layer` | True | URL parameter | `raw` | layer of the dataset | +| `domain` | True | URL parameter | `land` | domain of the dataset | +| `dataset` | True | URL parameter | `train_journeys` | dataset title | +| `version` | True | URL parameter | `3` | dataset version | ### Outputs List of raw files in json format, e.g.: ```json -[ - "2022-01-21T17:12:31-file1.csv", - "2022-01-24T11:43:28-file2.csv" -] +["2022-01-21T17:12:31-file1.csv", "2022-01-24T11:43:28-file2.csv"] ``` ## Query @@ -213,14 +208,13 @@ You will need `READ` permission appropriate to the dataset sensitivity level, e. ### Inputs -| Parameters | Required | Usage | Example values | Definition | -|---------------|--------------|-------------------------|-----------------------------------------------------------------------------------------------------------------------------|-------------------------------| -| `layer` | True | URL parameter | `raw` | layer of the dataset | -| `domain` | True | URL parameter | `space` | domain of the dataset | -| `dataset` | True | URL parameter | `rocket_launches` | dataset title | -| `version` | False | Query parameter | '3' | dataset version | -| `query` | False | JSON Request Body | Consult the [docs](https://github.com/no10ds/rapid-api/blob/main/docs/guides/usage/usage.md#how-to-construct-a-query-object)| the query object | - +| Parameters | Required | Usage | Example values | Definition | +| ---------- | -------- | ----------------- | ---------------------------------------------------------------------------------------------------------------------------- | --------------------- | +| `layer` | True | URL parameter | `raw` | layer of the dataset | +| `domain` | True | URL parameter | `space` | domain of the dataset | +| `dataset` | True | URL parameter | `rocket_launches` | dataset title | +| `version` | False | Query parameter | '3' | dataset version | +| `query` | False | JSON Request Body | Consult the [docs](https://github.com/no10ds/rapid-api/blob/main/docs/guides/usage/usage.md#how-to-construct-a-query-object) | the query object | ### Outputs @@ -264,14 +258,13 @@ You will need a `READ` permission appropriate to the dataset sensitivity level, ### Inputs -| Parameters | Required | Usage | Example values | Definition | -|---------------|--------------|-------------------------|-----------------------------------------------------------------------------------------------------------------------------|-------------------------------| -| `layer` | True | URL parameter | `raw` | layer of the dataset | -| `domain` | True | URL parameter | `space` | domain of the dataset | -| `dataset` | True | URL parameter | `rocket_launches` | dataset title | -| `version` | False | Query parameter | '3' | dataset version | -| `query` | False | JSON Request Body | Consult the [docs](https://github.com/no10ds/rapid-api/blob/main/docs/guides/usage/usage.md#how-to-construct-a-query-object)| the query object | - +| Parameters | Required | Usage | Example values | Definition | +| ---------- | -------- | ----------------- | ---------------------------------------------------------------------------------------------------------------------------- | --------------------- | +| `layer` | True | URL parameter | `raw` | layer of the dataset | +| `domain` | True | URL parameter | `space` | domain of the dataset | +| `dataset` | True | URL parameter | `rocket_launches` | dataset title | +| `version` | False | Query parameter | '3' | dataset version | +| `query` | False | JSON Request Body | Consult the [docs](https://github.com/no10ds/rapid-api/blob/main/docs/guides/usage/usage.md#how-to-construct-a-query-object) | the query object | ### Outputs @@ -281,10 +274,7 @@ Asynchronous Job ID that can be used to track the progress of the query. Once th Use this endpoint to retrieve basic information for specific datasets, if there is no data stored for the dataset and error will be thrown. -When a valid dataset is retrieved the available data will be the schema definition with some extra values such as: - - number of rows - - number of columns - - statistics data for date columns +When a valid dataset is retrieved the available data will be the schema definition with some extra values such as: - number of rows - number of columns - statistics data for date columns ### Required Permissions @@ -296,12 +286,12 @@ You will need any `READ` permission, e.g.: `READ_ALL`, `READ_PUBLIC`, `READ_PRIV ### Inputs -| Parameters | Required | Usage | Example values | Definition | -|------------|----------|-------------------|------------------|-----------------------| -| `layer` | True | URL parameter | `raw` | layer of the dataset | -| `domain` | True | URL parameter | `land` | domain of the dataset | -| `dataset` | True | URL parameter | `train_journeys` | dataset title | -| `version` | False | Query parameter | `3` | dataset version | +| Parameters | Required | Usage | Example values | Definition | +| ---------- | -------- | --------------- | ---------------- | --------------------- | +| `layer` | True | URL parameter | `raw` | layer of the dataset | +| `domain` | True | URL parameter | `land` | domain of the dataset | +| `dataset` | True | URL parameter | `train_journeys` | dataset title | +| `version` | False | Query parameter | `3` | dataset version | ### Outputs diff --git a/docs/api/routes/permissions.md b/docs/api/routes/permissions.md index aa195ce..3c106ea 100644 --- a/docs/api/routes/permissions.md +++ b/docs/api/routes/permissions.md @@ -15,13 +15,7 @@ Use this endpoint to list all available permissions that can be granted to users List of permissions: ```json -[ - "DATA_ADMIN", - "USER_ADMIN", - "WRITE_ALL", - "READ_PROTECTED_", - "..." -] +["DATA_ADMIN", "USER_ADMIN", "WRITE_ALL", "READ_PROTECTED_", "..."] ``` ## List Subject Permissions @@ -41,11 +35,5 @@ Use this endpoint to list all permissions that are assigned to a subject. List of permissions: ```json -[ - "DATA_ADMIN", - "USER_ADMIN", - "WRITE_ALL", - "READ_PROTECTED_", - "..." -] +["DATA_ADMIN", "USER_ADMIN", "WRITE_ALL", "READ_PROTECTED_", "..."] ``` diff --git a/docs/api/routes/protected_domain.md b/docs/api/routes/protected_domain.md index fb308ed..9d12b9c 100644 --- a/docs/api/routes/protected_domain.md +++ b/docs/api/routes/protected_domain.md @@ -12,9 +12,9 @@ Protected domains can be created to restrict access permissions to specific doma ### Inputs -| Parameters | Usage | Example values | Definition | -|------------------|---------------------|------------------|----------------------------------| -| `domain` | URL Parameter | `land` | The name of the protected domain | +| Parameters | Usage | Example values | Definition | +| ---------- | ------------- | -------------- | -------------------------------- | +| `domain` | URL Parameter | `land` | The name of the protected domain | ## List @@ -33,8 +33,5 @@ Use this endpoint to list the protected domains that currently exist. List of protected permissions in json format in the response body: ```json -[ - "land", - "department" -] +["land", "department"] ``` diff --git a/docs/api/routes/schema.md b/docs/api/routes/schema.md index a4b7b2d..0e3b5d4 100644 --- a/docs/api/routes/schema.md +++ b/docs/api/routes/schema.md @@ -4,7 +4,6 @@ In order to upload the dataset for the first time, you need to define its schema > The first 50MB of the uploaded file (regardless of size) are used to infer the schema. Consider uploading a representative sample of your dataset (e.g.: the first 10,000 rows) instead of uploading the entire large file which could take a long time - ### Permissions Any @@ -13,11 +12,10 @@ Any `POST /schema/{sensitivity}/{domain}/{dataset}/generate` - ### Inputs | Parameters | Usage | Example values | Definition | -|---------------|-----------------------------------------|------------------------------|----------------------------| +| ------------- | --------------------------------------- | ---------------------------- | -------------------------- | | `layer` | URL parameter | `default` | layer of the dataset | | `sensitivity` | URL parameter | `PUBLIC, PRIVATE, PROTECTED` | sensitivity of the dataset | | `domain` | URL parameter | `land` | domain of the dataset | @@ -77,9 +75,9 @@ When you have a schema definition you can use this endpoint to upload it. This w ### Inputs -| Parameters | Usage | Example values | Definition | -|---------------|-----------------------------------------|------------------------------|-----------------------| -| schema | JSON request body | see below | the schema definition | +| Parameters | Usage | Example values | Definition | +| ---------- | ----------------- | -------------- | --------------------- | +| schema | JSON request body | see below | the schema definition | Example schema JSON body: @@ -93,9 +91,7 @@ Example schema JSON body: "key_value_tags": { "train": "passenger" }, - "key_only_tags": [ - "land" - ], + "key_only_tags": ["land"], "owners": [ { "name": "Stanley Shunpike", @@ -141,7 +137,7 @@ Any relevant `WRITE` permissions that matches dataset sensitivity level, e.g. `W ### Inputs | Parameters | Required | Usage | Example values | Definition | -|------------|----------|-----------------------------------------|-----------------------------|-------------------------| +| ---------- | -------- | --------------------------------------- | --------------------------- | ----------------------- | | `layer` | True | URL parameter | `default` | layer of the dataset | | `domain` | True | URL parameter | `air` | domain of the dataset | | `dataset` | True | URL parameter | `passengers_by_airport` | dataset title | diff --git a/docs/api/routes/subject.md b/docs/api/routes/subject.md index 298dd3f..d1dea54 100644 --- a/docs/api/routes/subject.md +++ b/docs/api/routes/subject.md @@ -43,17 +43,14 @@ Use this endpoint to modify the permissions that are granted to users and client ### Inputs -| Parameters | Usage | Example values | Definition | -|-----------------------|---------------------|------------------|----------------------------------------| -| `Subject Permissions` | JSON Request Body | See below | The details used to modify permissions | +| Parameters | Usage | Example values | Definition | +| --------------------- | ----------------- | -------------- | -------------------------------------- | +| `Subject Permissions` | JSON Request Body | See below | The details used to modify permissions | ```json { "subject_id": "123456789", - "permissions": [ - "READ_ALL", - "WRITE_PUBLIC" - ] + "permissions": ["READ_ALL", "WRITE_PUBLIC"] } ``` @@ -64,9 +61,6 @@ Confirmation of permissions: ```json { "subject_id": "123456789", - "permissions": [ - "READ_ALL", - "WRITE_PUBLIC" - ] + "permissions": ["READ_ALL", "WRITE_PUBLIC"] } ``` diff --git a/docs/api/routes/user.md b/docs/api/routes/user.md index d7a5f29..5da8a99 100644 --- a/docs/api/routes/user.md +++ b/docs/api/routes/user.md @@ -12,18 +12,15 @@ As a maintainer of a rAPId you can create new users to interact with the API to ### Inputs -| Parameters | Usage | Example values | Definition | -|------------------|---------------------|------------------|---------------------------------------------------------------------------| -| `User details` | JSON Request Body | See below | The name of the user application to onboard and the granted permissions | +| Parameters | Usage | Example values | Definition | +| -------------- | ----------------- | -------------- | ----------------------------------------------------------------------- | +| `User details` | JSON Request Body | See below | The name of the user application to onboard and the granted permissions | ```json { "username": "jhon_doe", "email": "jhon.doe@email.com", - "permissions": [ - "READ_ALL", - "WRITE_PUBLIC" - ] + "permissions": ["READ_ALL", "WRITE_PUBLIC"] } ``` @@ -39,11 +36,11 @@ The username must adhere to the following conditions: #### Email address The email must adhere to the following conditions: + - The domain must be included on the `ALLOWED_EMAIL_DOMAINS` environment - Must satisfy the Email Standard Structure `RFC5322` ( see [Email Address in Wikipedia](https://en.wikipedia.org/wiki/Email_address)) - ### Outputs Once the new user has been created, the following information will be shown in the response: @@ -52,10 +49,7 @@ Once the new user has been created, the following information will be shown in t { "username": "jhon_doe", "email": "jhon.doe@email.com", - "permissions": [ - "READ_ALL", - "WRITE_PUBLIC" - ], + "permissions": ["READ_ALL", "WRITE_PUBLIC"], "user_id": "some-generated-id-eq2e3q-eqwe32-12eqwe214q" } ``` @@ -74,9 +68,9 @@ Given a user already exists you can delete them from rAPId. ### Inputs -| Parameters | Usage | Example values | Definition | -|------------------|---------------------|------------------|---------------------------------------| -| `user details` | JSON Request Body | See below | The name and id of the user to delete | +| Parameters | Usage | Example values | Definition | +| -------------- | ----------------- | -------------- | ------------------------------------- | +| `user details` | JSON Request Body | See below | The name and id of the user to delete | ```json { diff --git a/docs/api/schema.md b/docs/api/schema.md index 6dc4fd8..314cbb4 100644 --- a/docs/api/schema.md +++ b/docs/api/schema.md @@ -10,50 +10,57 @@ A schema is defined with the following structure: #### General information of the schema. - - `layer` - String value, this is the name of the layer within rAPId that you wish to place the dataset within. The possible values of this are unique to the rAPId instance and specified on creation. If none is provided, the option will be `default`. - - `domain` - String value, is the name of the domain that owns the dataset, it could be for example the name of the department that handles the data. - - `dataset` - String value, is the name of the dataset. e.g.: "receipts" or "address". - - `sensitivity` - String value, is the sensitivity level of the dataset. e.g.: "PUBLIC", "PRIVATE", "PROTECTED" - - `description` - Free text string that provides human readable information about the details of the dataset. - - `version` - int value, denotes the schema version - - `key_value_tags` - Dictionary of string keys and values to associate to the dataset. e.g.: `{"school_level": "primary", "school_type": "private"}` - - `key_only_tags` - List of strings of tags to associate to the dataset. e.g.: `["schooling", "benefits", "archive", "historic"]` - - `update_behaviour` - String value, the action to take when a new file is uploaded. e.g.: `APPEND`, `OVERWRITE`. +- `layer` - String value, this is the name of the layer within rAPId that you wish to place the dataset within. The possible values of this are unique to the rAPId instance and specified on creation. If none is provided, the option will be `default`. +- `domain` - String value, is the name of the domain that owns the dataset, it could be for example the name of the department that handles the data. +- `dataset` - String value, is the name of the dataset. e.g.: "receipts" or "address". +- `sensitivity` - String value, is the sensitivity level of the dataset. e.g.: "PUBLIC", "PRIVATE", "PROTECTED" +- `description` - Free text string that provides human readable information about the details of the dataset. +- `version` - int value, denotes the schema version +- `key_value_tags` - Dictionary of string keys and values to associate to the dataset. e.g.: `{"school_level": "primary", "school_type": "private"}` +- `key_only_tags` - List of strings of tags to associate to the dataset. e.g.: `["schooling", "benefits", "archive", "historic"]` +- `update_behaviour` - String value, the action to take when a new file is uploaded. e.g.: `APPEND`, `OVERWRITE`. ### Columns #### A list defining the columns that are to be expected within the dataset. - - `name` - String value, name of the column. - - `data_type` - String value, this is an accepted pandas' data type, will be used to validate the schema. - - `allow_null` - Boolean value, specifies whether the columns can have empty values or not. - - `partition_index` (Optional) - Integer value, whether the column is a [partition](#partitions) and its index. - - `format` (Conditional) - String value, regular expression used to specify the format of the dates. Will only be used and required if the data_type is date. +- `name` - String value, name of the column. +- `data_type` - String value, this is an accepted pandas' data type, will be used to validate the schema. +- `allow_null` - Boolean value, specifies whether the columns can have empty values or not. +- `partition_index` (Optional) - Integer value, whether the column is a [partition](#partitions) and its index. +- `format` (Conditional) - String value, regular expression used to specify the format of the dates. Will only be used and required if the data_type is date. ### Sensitivity + The sensitivity level of a dataset can be described by one of three values: `PUBLIC`, `PRIVATE` and `PROTECTED`. These determine the access level that different clients will have to the data depending on their permissions. Notes if you wish to use the sensitivity level `PROTECTED` then you must first create a Protected Domain for your Dataset. See the [data access docs](data_access.md) ### Description + The description is where you can specify human readable details about the dataset so that a user can quickly understand the contents and purpose of a dataset. ### Version + The schema version is automatically generated and cannot be updated by the user ### Tags + You can add up to 30 custom tags to a dataset. These are in a key: value format which allow for identification and categorisation of the datasets. Restrictions applying to the keys: + - Only alphanumeric characters, hyphens and underscores - Length between 1 and 128 characters Restrictions applying to the values: + - Only alphanumeric characters, hyphens and underscores - Length between 0 and 256 characters ### Owners + You must specify at least one dataset owner. Typically this is a point of contact if there are issues or questions surrounding the dataset. @@ -61,18 +68,23 @@ Typically this is a point of contact if there are issues or questions surroundin You MUST change the default values, otherwise an error will be thrown and schema upload will fail. ### Update Behaviour + The behaviour of the API when a new file is uploaded to the dataset. The possible values are: + - `APPEND` - New files will be added to the dataset, there are no duplication checks so new data must be unique. This is the default behaviour. - `OVERWRITE` - Any new file will overwrite the current content. The overwrite will happen on the partitions, so if there is an old partition that is not included in the new dataset, that will not be overwritten. ### Column headings + Column heading names should follow a strict format. The [requirements](https://docs.aws.amazon.com/glue/latest/dg/add-classifier.html) are: + - Lowercase - No whitespace - No other punctuation except underscores, but not be exclusively underscores - CAN include digits, but not be exclusively digits ### Accepted data types + The data accepted data types for a rAPId instance can be found detailed [here](https://docs.aws.amazon.com/athena/latest/ug/data-types.html). The only Athena types that are currently unsupported are array, map and struct types. - `integer` - Use it to define integer values. @@ -110,6 +122,7 @@ In order to make the application more efficient in terms of time and money when maker in the rAPId service, in order to use it, just add an integer into the partition_index when creating a schema. The partition columns must: + - Start with 0 as the first index. - Be a positive integer. - Be sequential (0, 1, 2, ... N), the lower the index number the higher the hierarchy. @@ -195,10 +208,10 @@ Once all the values have been set up, just upload the json using the POST `/sche ## Auto-generated - Use the POST `/schema/{my_domain_name}/{my_datase_name}/generate` endpoint to automatically generate a draft for the schema. Consider the following: + - The domain and dataset names will be taken from the url, but can be changed manually afterwards. - It will not set any [partition columns](#partitions), ensure you add them after the schema has been generated. - It might not infer the `date` type and its format, ensure you add this information if required. @@ -315,4 +328,4 @@ You might then change the values that fit your data and come with something like } ``` -Once all the values have been set up, just upload the json using the POST ```/schema``` endpoint of the rAPId instance to create a dataset. +Once all the values have been set up, just upload the json using the POST `/schema` endpoint of the rAPId instance to create a dataset. diff --git a/docs/api/usage.md b/docs/api/usage.md index 36c8f91..1b43be8 100644 --- a/docs/api/usage.md +++ b/docs/api/usage.md @@ -3,7 +3,7 @@ The rAPId API serves to make data storage and retrieval as easy and consistent a The API functionality includes: - [Uploading a schema (i.e. creating a new dataset definition)](/api/routes/schema/) - - Also creating a new version of an existing schema + - Also creating a new version of an existing schema - [Uploading data to any version of a dataset](/api/routes/dataset/#upload) - [Listing available data](/api/routes/dataset/#list) - [Querying data from any version of a dataset](/api/routes/dataset/#query) @@ -17,8 +17,8 @@ The first step is to create a dataset, which we can do by uploading a schema. Th After a schema has been uploaded, data can then be uploaded to the dataset. During the upload process, the API checks if the data matches the schema. This ensures that each of the datasets remain consistent. - + ## Data upload and query flows ### No schema exists + upload data + query diff --git a/docs/getting_started.md b/docs/getting_started.md index c3b9634..51a3f4c 100644 --- a/docs/getting_started.md +++ b/docs/getting_started.md @@ -5,12 +5,10 @@ We provide two options for deploying rAPId within an AWS environment: 1. If you have existing infrastructure (e.g a VPC) that you would like to deploy rAPId within, then you can use the [rAPId module](/infrastructure/deployment/existing/), passing in specific variables relating to your AWS account. 2. If you do not have any exisiting infrastructure, you can instead deploy the [entire rAPId stack](/infrastructure/deployment/full_stack/) creating all the relevant infrastructure. - # Developing - diff --git a/docs/index.md b/docs/index.md index 103273e..f434b06 100644 --- a/docs/index.md +++ b/docs/index.md @@ -12,7 +12,6 @@ Pioneered by 10 Downing Street, rAPId aims to improve the government's use of da rAPId is comprised of several components that together form a replicable template for simple data storage infrastructure in AWS with a RESTful API and user-friendly UI. It allows the simple ingestion and sharing of standardised datasets. - ## API The rAPId API is a RESTful API built using FastAPI and Python. It handles all the serving for user management, schema definitions and data storage and retrieval. diff --git a/docs/infrastructure/deployment.md b/docs/infrastructure/deployment.md index c2c67d7..a2cd954 100644 --- a/docs/infrastructure/deployment.md +++ b/docs/infrastructure/deployment.md @@ -59,11 +59,9 @@ There are also these optional inputs: Once you apply the Terraform, a new instance of the application should be created. - - ## rAPId Full Stack -For teams with no existing infrastructure and just a blank AWS Account, we have ```make``` commands that will set up the necessary infrastructure from scratch with sensible defaults. +For teams with no existing infrastructure and just a blank AWS Account, we have `make` commands that will set up the necessary infrastructure from scratch with sensible defaults. ### Pre-requisites @@ -146,7 +144,7 @@ mechanism to ensure infrastructure changes are applied atomically. To set up the S3 backend follow these steps: - Replace the values in `backend.hcl` with your custom values (these can be any value you would like). They will be referenced to create the Terraform state components and used going forwards as the backend config. -- In the root folder run ```make infra-backend```, this will initialise Terraform by creating both the state bucket and dynamodb table in AWS. +- In the root folder run `make infra-backend`, this will initialise Terraform by creating both the state bucket and dynamodb table in AWS. ### IAM User Setup (Optional) @@ -216,14 +214,14 @@ Optional: Then, run the following command on each block: -- ```make infra-init block=``` to initialise Terraform -- ```make infra-plan block=``` to plan (to check the changes ensuring nothing will be run) -- ```make infra-apply block=``` to apply changes, when prompted type ```yes``` +- `make infra-init block=` to initialise Terraform +- `make infra-plan block=` to plan (to check the changes ensuring nothing will be run) +- `make infra-apply block=` to apply changes, when prompted type `yes` Run the blocks in this order: 1. [iam-config](#iam-user-setup-optional) -> All the users' roles/policies will be handled here and will delete any previous config + > All the users' roles/policies will be handled here and will delete any previous config 2. vpc 3. s3 4. auth diff --git a/docs/infrastructure/diagrams.md b/docs/infrastructure/diagrams.md index 95161aa..421672b 100644 --- a/docs/infrastructure/diagrams.md +++ b/docs/infrastructure/diagrams.md @@ -1 +1 @@ - \ No newline at end of file + diff --git a/docs/infrastructure/domains_subdomains.md b/docs/infrastructure/domains_subdomains.md index 79a09a4..2af3d7b 100644 --- a/docs/infrastructure/domains_subdomains.md +++ b/docs/infrastructure/domains_subdomains.md @@ -2,16 +2,16 @@ When creating a rAPId instance you will need a hostname to be able to access the to achieve this: 1. Using an existing domain from route53: AWS creates a hosted zone linked to your domain, just use this HZ id in the -inputs along the domain, and you are ready to go. (If the domain is currently being used, a subdomain can be created -automatically by providing the HZ id and the subdomain name in the `input-params.tfvars`). + inputs along the domain, and you are ready to go. (If the domain is currently being used, a subdomain can be created + automatically by providing the HZ id and the subdomain name in the `input-params.tfvars`). 2. Creating a new domain in route53: you will need to manually register a domain in the AWS console, once this is done -the steps are the same as scenario 1. + the steps are the same as scenario 1. 3. Using an existing domain outside AWS: you will need to leave the HZ id field empty and provide a -domain/subdomain, copy the NS values from the output and use them in your DNS provider. + domain/subdomain, copy the NS values from the output and use them in your DNS provider. 4. Using an existing domain from a different AWS account to create a subdomain: you will need to leave the HZ id field -empty and provide the subdomain name, then copy the NS values from the output, go to the AWS -account that owns the domain, go to route 53, in the domain hosted zone, create a new record of the type NS with the -subdomain name and add the NS values copied from the outputs. + empty and provide the subdomain name, then copy the NS values from the output, go to the AWS + account that owns the domain, go to route 53, in the domain hosted zone, create a new record of the type NS with the + subdomain name and add the NS values copied from the outputs. diff --git a/docs/ui/todo.md b/docs/ui/todo.md index 50d60da..dde43ac 100644 --- a/docs/ui/todo.md +++ b/docs/ui/todo.md @@ -1 +1 @@ -- Give examples of UI usage - until we have a sandbox \ No newline at end of file +- Give examples of UI usage - until we have a sandbox diff --git a/infrastructure/batect.yml b/infrastructure/batect.yml index 1c33378..779a359 100644 --- a/infrastructure/batect.yml +++ b/infrastructure/batect.yml @@ -18,4 +18,4 @@ tasks: description: Parse the changelog file for the release's changes run: container: utility - command: "python get_latest_release_changelog.py" + command: 'python get_latest_release_changelog.py' diff --git a/infrastructure/blocks/pipeline-ami/provider.tf b/infrastructure/blocks/pipeline-ami/provider.tf index c54d77e..214eedc 100644 --- a/infrastructure/blocks/pipeline-ami/provider.tf +++ b/infrastructure/blocks/pipeline-ami/provider.tf @@ -3,4 +3,3 @@ terraform { key = "pipeline-ami/terraform.tfstate" } } - diff --git a/infrastructure/blocks/pipeline-ami/template.json b/infrastructure/blocks/pipeline-ami/template.json index 69a8a89..f606ce2 100644 --- a/infrastructure/blocks/pipeline-ami/template.json +++ b/infrastructure/blocks/pipeline-ami/template.json @@ -1,58 +1,54 @@ { - "variables": { - "version": "", - "region": "", - "subnet_id": "", - "vpc_id": "" - }, - "builders": [ + "variables": { + "version": "", + "region": "", + "subnet_id": "", + "vpc_id": "" + }, + "builders": [ + { + "ami_description": "An AMI for creating github runners", + "ami_name": "pipeline-ami-{{user `version`}}", + "instance_type": "t3.large", + "region": "{{user `region`}}", + "force_deregister": "true", + "force_delete_snapshot": "true", + "vpc_id": "{{user `vpc_id`}}", + "subnet_id": "{{user `subnet_id`}}", + "associate_public_ip_address": true, + "ami_block_device_mappings": [ { - "ami_description": "An AMI for creating github runners", - "ami_name": "pipeline-ami-{{user `version`}}", - "instance_type": "t3.large", - "region": "{{user `region`}}", - "force_deregister": "true", - "force_delete_snapshot": "true", - "vpc_id": "{{user `vpc_id`}}", - "subnet_id": "{{user `subnet_id`}}", - "associate_public_ip_address": true, - "ami_block_device_mappings": [ - { - "device_name": "/dev/sda1", - "encrypted": false, - "volume_type": "gp2", - "volume_size": 32, - "delete_on_termination": true - } - ], - "source_ami_filter": { - "filters": { - "name": "ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*", - "virtualization-type": "hvm", - "root-device-type": "ebs" - }, - "most_recent": true, - "owners": [ - "099720109477" - ] - }, - "ssh_username": "ubuntu", - "type": "amazon-ebs" + "device_name": "/dev/sda1", + "encrypted": false, + "volume_type": "gp2", + "volume_size": 32, + "delete_on_termination": true } - ], - "provisioners": [ - { - "inline": [ - "echo 'Sleeping for 30 seconds to give Ubuntu enough time to initialize (otherwise, packages may fail to install).'", - "sleep 30" - ], - "type": "shell" + ], + "source_ami_filter": { + "filters": { + "name": "ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*", + "virtualization-type": "hvm", + "root-device-type": "ebs" }, - { - "scripts": [ - "{{template_dir}}/install.sh" - ], - "type": "shell" - } - ] -} \ No newline at end of file + "most_recent": true, + "owners": ["099720109477"] + }, + "ssh_username": "ubuntu", + "type": "amazon-ebs" + } + ], + "provisioners": [ + { + "inline": [ + "echo 'Sleeping for 30 seconds to give Ubuntu enough time to initialize (otherwise, packages may fail to install).'", + "sleep 30" + ], + "type": "shell" + }, + { + "scripts": ["{{template_dir}}/install.sh"], + "type": "shell" + } + ] +} diff --git a/infrastructure/blocks/pipeline/iam.tf b/infrastructure/blocks/pipeline/iam.tf index c8546f4..54fa363 100644 --- a/infrastructure/blocks/pipeline/iam.tf +++ b/infrastructure/blocks/pipeline/iam.tf @@ -6,13 +6,6 @@ resource "aws_iam_policy" "pipeline_ecr_access" { policy = jsonencode({ "Version" : "2012-10-17", "Statement" : [ - { - Effect : "Allow", - Action : [ - "ecr:GetAuthorizationToken", - ], - Resource : "*" - }, { Effect : "Allow", Action : [ @@ -60,14 +53,6 @@ resource "aws_iam_policy" "pipeline_ecr_public_access" { policy = jsonencode({ "Version" : "2012-10-17", "Statement" : [ - { - Effect : "Allow", - Action : [ - "ecr-public:GetAuthorizationToken", - "sts:GetServiceBearerToken", - ], - Resource : "*" - }, { Effect : "Allow", Action : [ @@ -77,12 +62,14 @@ resource "aws_iam_policy" "pipeline_ecr_public_access" { "ecr-public:DescribeRegistries", "ecr-public:DescribeImages", "ecr-public:DescribeImageTags", + "ecr-public:GetAuthorizationToken", "ecr-public:GetRepositoryCatalogData", "ecr-public:GetRegistryCatalogData", "ecr-public:InitiateLayerUpload", "ecr-public:UploadLayerPart", "ecr-public:CompleteLayerUpload", - "ecr-public:PutImage" + "ecr-public:PutImage", + "sts:GetServiceBearerToken", ], Resource : [ data.terraform_remote_state.ecr-state.outputs.ecr_public_repo_arn, diff --git a/infrastructure/blocks/pipeline/initialisation-script.sh.tpl b/infrastructure/blocks/pipeline/initialisation-script.sh.tpl index 786abf9..0099504 100644 --- a/infrastructure/blocks/pipeline/initialisation-script.sh.tpl +++ b/infrastructure/blocks/pipeline/initialisation-script.sh.tpl @@ -1,4 +1,4 @@ -#!/bin/bash +#!/bin/bash # ---- Start docker service sudo service docker start diff --git a/infrastructure/modules/app-cluster/README.md b/infrastructure/modules/app-cluster/README.md index a4d5a44..6e7edf3 100644 --- a/infrastructure/modules/app-cluster/README.md +++ b/infrastructure/modules/app-cluster/README.md @@ -1,13 +1,14 @@ + ## Requirements No requirements. ## Providers -| Name | Version | -|------|---------| -| [aws](#provider\_aws) | 4.50.0 | +| Name | Version | +| ------------------------------------------------ | ------- | +| [aws](#provider_aws) | 4.50.0 | ## Modules @@ -15,117 +16,118 @@ No modules. ## Resources -| Name | Type | -|------|------| -| [aws_acm_certificate.rapid-certificate](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/acm_certificate) | resource | -| [aws_acm_certificate_validation.rapid-certificate-validation](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/acm_certificate_validation) | resource | -| [aws_alb.application_load_balancer](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/alb) | resource | -| [aws_appautoscaling_policy.ecs_policy_cpu](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/appautoscaling_policy) | resource | -| [aws_appautoscaling_policy.ecs_policy_memory](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/appautoscaling_policy) | resource | -| [aws_appautoscaling_target.ecs_target](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/appautoscaling_target) | resource | -| [aws_cloudtrail.access_logs_trail](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudtrail) | resource | -| [aws_cloudwatch_log_group.access_logs_log_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource | -| [aws_cloudwatch_log_group.log-group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource | -| [aws_cloudwatch_log_metric_filter.rapid-service-log-error-count](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_metric_filter) | resource | -| [aws_cloudwatch_metric_alarm.log-error-alarm](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_metric_alarm) | resource | -| [aws_dynamodb_table.service_table](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/dynamodb_table) | resource | -| [aws_ecs_cluster.aws-ecs-cluster](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecs_cluster) | resource | -| [aws_ecs_service.aws-ecs-service](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecs_service) | resource | -| [aws_ecs_task_definition.aws-ecs-task](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecs_task_definition) | resource | -| [aws_iam_policy.app_athena_query_access](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | -| [aws_iam_policy.app_cognito_access](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | -| [aws_iam_policy.app_dynamodb_access](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | -| [aws_iam_policy.app_glue_services_passrole](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | -| [aws_iam_policy.app_s3_access](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | -| [aws_iam_policy.app_secrets_manager_access](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | -| [aws_iam_policy.app_tags_access](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | -| [aws_iam_policy.aws_iam_policy_cloudtrail_cloudwatch](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | -| [aws_iam_policy_attachment.aws_iam_policy_cloudtrail_cloudwatch_attachment](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy_attachment) | resource | -| [aws_iam_role.cloud_trail_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | -| [aws_iam_role.ecsTaskExecutionRole](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | -| [aws_iam_role_policy_attachment.ecsTaskExecutionRole_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | -| [aws_iam_role_policy_attachment.role_app_glue_services_passrole_policy_attachment](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | -| [aws_iam_role_policy_attachment.role_athena_access_policy_attachment](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | -| [aws_iam_role_policy_attachment.role_cognito_access_policy_attachment](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | -| [aws_iam_role_policy_attachment.role_dynamodb_access_policy_attachment](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | -| [aws_iam_role_policy_attachment.role_s3_access_policy_attachment](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | -| [aws_iam_role_policy_attachment.role_secrets_manager_access_policy_attachment](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | -| [aws_iam_role_policy_attachment.role_tags_access_policy_attachment](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | -| [aws_kms_key.access_logs_key](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_key) | resource | -| [aws_lb_listener.http-listener](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lb_listener) | resource | -| [aws_lb_listener.listener](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lb_listener) | resource | -| [aws_lb_target_group.target_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lb_target_group) | resource | -| [aws_route53_record.rapid_validation_record](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_record) | resource | -| [aws_route53_zone.primary-hosted-zone](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_zone) | resource | -| [aws_s3_bucket.access_logs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource | -| [aws_s3_bucket_lifecycle_configuration.access_logs_lifecycle](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_lifecycle_configuration) | resource | -| [aws_s3_bucket_policy.access_logs_bucket_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_policy) | resource | -| [aws_s3_bucket_policy.allow_alb_logging](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_policy) | resource | -| [aws_s3_bucket_public_access_block.access_logs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block) | resource | -| [aws_s3_bucket_server_side_encryption_configuration.access_logs_s3_encryption_config](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_server_side_encryption_configuration) | resource | -| [aws_security_group.load_balancer_security_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource | -| [aws_security_group.service_security_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource | -| [aws_sns_topic.log-error-alarm-notification](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sns_topic) | resource | -| [aws_sns_topic_subscription.log-error-alarm-subscription](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sns_topic_subscription) | resource | -| [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | -| [aws_ec2_managed_prefix_list.cloudwatch](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ec2_managed_prefix_list) | data source | -| [aws_ecs_task_definition.main](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ecs_task_definition) | data source | -| [aws_elb_service_account.main](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/elb_service_account) | data source | -| [aws_iam_policy_document.access_logs_key_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | -| [aws_iam_policy_document.assume_role_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | -| [aws_region.region](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source | +| Name | Type | +| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- | +| [aws_acm_certificate.rapid-certificate](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/acm_certificate) | resource | +| [aws_acm_certificate_validation.rapid-certificate-validation](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/acm_certificate_validation) | resource | +| [aws_alb.application_load_balancer](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/alb) | resource | +| [aws_appautoscaling_policy.ecs_policy_cpu](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/appautoscaling_policy) | resource | +| [aws_appautoscaling_policy.ecs_policy_memory](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/appautoscaling_policy) | resource | +| [aws_appautoscaling_target.ecs_target](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/appautoscaling_target) | resource | +| [aws_cloudtrail.access_logs_trail](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudtrail) | resource | +| [aws_cloudwatch_log_group.access_logs_log_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource | +| [aws_cloudwatch_log_group.log-group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource | +| [aws_cloudwatch_log_metric_filter.rapid-service-log-error-count](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_metric_filter) | resource | +| [aws_cloudwatch_metric_alarm.log-error-alarm](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_metric_alarm) | resource | +| [aws_dynamodb_table.service_table](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/dynamodb_table) | resource | +| [aws_ecs_cluster.aws-ecs-cluster](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecs_cluster) | resource | +| [aws_ecs_service.aws-ecs-service](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecs_service) | resource | +| [aws_ecs_task_definition.aws-ecs-task](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecs_task_definition) | resource | +| [aws_iam_policy.app_athena_query_access](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | +| [aws_iam_policy.app_cognito_access](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | +| [aws_iam_policy.app_dynamodb_access](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | +| [aws_iam_policy.app_glue_services_passrole](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | +| [aws_iam_policy.app_s3_access](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | +| [aws_iam_policy.app_secrets_manager_access](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | +| [aws_iam_policy.app_tags_access](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | +| [aws_iam_policy.aws_iam_policy_cloudtrail_cloudwatch](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | +| [aws_iam_policy_attachment.aws_iam_policy_cloudtrail_cloudwatch_attachment](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy_attachment) | resource | +| [aws_iam_role.cloud_trail_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | +| [aws_iam_role.ecsTaskExecutionRole](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | +| [aws_iam_role_policy_attachment.ecsTaskExecutionRole_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | +| [aws_iam_role_policy_attachment.role_app_glue_services_passrole_policy_attachment](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | +| [aws_iam_role_policy_attachment.role_athena_access_policy_attachment](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | +| [aws_iam_role_policy_attachment.role_cognito_access_policy_attachment](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | +| [aws_iam_role_policy_attachment.role_dynamodb_access_policy_attachment](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | +| [aws_iam_role_policy_attachment.role_s3_access_policy_attachment](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | +| [aws_iam_role_policy_attachment.role_secrets_manager_access_policy_attachment](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | +| [aws_iam_role_policy_attachment.role_tags_access_policy_attachment](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | +| [aws_kms_key.access_logs_key](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_key) | resource | +| [aws_lb_listener.http-listener](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lb_listener) | resource | +| [aws_lb_listener.listener](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lb_listener) | resource | +| [aws_lb_target_group.target_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lb_target_group) | resource | +| [aws_route53_record.rapid_validation_record](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_record) | resource | +| [aws_route53_zone.primary-hosted-zone](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_zone) | resource | +| [aws_s3_bucket.access_logs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource | +| [aws_s3_bucket_lifecycle_configuration.access_logs_lifecycle](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_lifecycle_configuration) | resource | +| [aws_s3_bucket_policy.access_logs_bucket_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_policy) | resource | +| [aws_s3_bucket_policy.allow_alb_logging](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_policy) | resource | +| [aws_s3_bucket_public_access_block.access_logs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block) | resource | +| [aws_s3_bucket_server_side_encryption_configuration.access_logs_s3_encryption_config](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_server_side_encryption_configuration) | resource | +| [aws_security_group.load_balancer_security_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource | +| [aws_security_group.service_security_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource | +| [aws_sns_topic.log-error-alarm-notification](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sns_topic) | resource | +| [aws_sns_topic_subscription.log-error-alarm-subscription](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sns_topic_subscription) | resource | +| [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | +| [aws_ec2_managed_prefix_list.cloudwatch](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ec2_managed_prefix_list) | data source | +| [aws_ecs_task_definition.main](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ecs_task_definition) | data source | +| [aws_elb_service_account.main](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/elb_service_account) | data source | +| [aws_iam_policy_document.access_logs_key_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.assume_role_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_region.region](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source | ## Inputs -| Name | Description | Type | Default | Required | -|------|-------------|------|---------|:--------:| -| [allowed\_email\_domains](#input\_allowed\_email\_domains) | List of allowed emails domains that can be associated with users | `string` | n/a | yes | -| [app-replica-count-desired](#input\_app-replica-count-desired) | The desired number of replicas of the app | `number` | `1` | no | -| [app-replica-count-max](#input\_app-replica-count-max) | The maximum desired number of replicas of the app | `number` | `2` | no | -| [application\_version](#input\_application\_version) | The version number for the application image (e.g.: v1.0.4, v1.0.x-latest, etc.) | `string` | n/a | yes | -| [athena\_query\_output\_bucket\_arn](#input\_athena\_query\_output\_bucket\_arn) | The S3 bucket ARN where Athena stores its query results. This bucket is created dynamically with a unique name in the data-workflow module. Reference it by remote state, module output or ARN string directly | `string` | n/a | yes | -| [aws\_account](#input\_aws\_account) | AWS Account number to host the rAPId service | `string` | n/a | yes | -| [aws\_region](#input\_aws\_region) | The region of the AWS Account for the rAPId service | `string` | n/a | yes | -| [catalog\_disabled](#input\_catalog\_disabled) | Optional value on whether to disable the internal rAPId data catalog | `bool` | `false` | no | -| [certificate\_validation\_arn](#input\_certificate\_validation\_arn) | Arn of the certificate used by the domain | `string` | n/a | yes | -| [cognito\_user\_login\_app\_credentials\_secrets\_name](#input\_cognito\_user\_login\_app\_credentials\_secrets\_name) | Secret name for Cognito user login app credentials | `string` | n/a | yes | -| [cognito\_user\_pool\_id](#input\_cognito\_user\_pool\_id) | User pool id for cognito | `string` | n/a | yes | -| [container\_port](#input\_container\_port) | The port for the running ECS containers | `number` | `8000` | no | -| [data\_s3\_bucket\_arn](#input\_data\_s3\_bucket\_arn) | S3 Bucket arn to store application data | `string` | n/a | yes | -| [data\_s3\_bucket\_name](#input\_data\_s3\_bucket\_name) | S3 Bucket name to store application data | `string` | n/a | yes | -| [domain\_name](#input\_domain\_name) | Domain name for the rAPId instance | `string` | n/a | yes | -| [ecs\_cluster\_arn](#input\_ecs\_cluster\_arn) | ECS cliuster arn to attach the rAPId api to | `string` | `null` | no | -| [ecs\_cluster\_id](#input\_ecs\_cluster\_id) | ECS cluster id to attach the rAPId api to | `string` | `null` | no | -| [ecs\_cluster\_name](#input\_ecs\_cluster\_name) | ECS cluster name to attach the rAPId api to | `string` | `null` | no | -| [enable\_cloudtrail](#input\_enable\_cloudtrail) | Whether to enable the logging of db events to CloudTrail | `bool` | `true` | no | -| [host\_port](#input\_host\_port) | The host port for the running ECS containers | `number` | `8000` | no | -| [hosted\_zone\_id](#input\_hosted\_zone\_id) | Hosted Zone ID with the domain Name Servers, pass quotes to create a new one from scratch | `string` | n/a | yes | -| [ip\_whitelist](#input\_ip\_whitelist) | A list of IPs to whitelist for access to the service | `list(string)` | n/a | yes | -| [log\_bucket\_name](#input\_log\_bucket\_name) | A bucket to send the Load Balancer logs | `string` | n/a | yes | -| [permissions\_table](#input\_permissions\_table) | Users permissions table in dynamoDB | `string` | n/a | yes | -| [permissions\_table\_arn](#input\_permissions\_table\_arn) | Users permissions table arn in dynamoDB | `string` | n/a | yes | -| [private\_subnet\_ids\_list](#input\_private\_subnet\_ids\_list) | Application Private subnet list | `list(string)` | n/a | yes | -| [project\_information](#input\_project\_information) | n/a |
object({
project_name = optional(string),
project_description = optional(string),
project_contact = optional(string),
project_organisation = optional(string)
})
|
{
"project_contact": "",
"project_description": "",
"project_name": "",
"project_organisation": ""
}
| no | -| [protocol](#input\_protocol) | The protocol for the running ECS container | `string` | `"tcp"` | no | -| [public\_subnet\_ids\_list](#input\_public\_subnet\_ids\_list) | Application Public subnet list | `list(string)` | n/a | yes | -| [rapid\_ecr\_url](#input\_rapid\_ecr\_url) | ECR Url for task definition | `string` | n/a | yes | -| [resource-name-prefix](#input\_resource-name-prefix) | The prefix to add to resources for easier identification | `string` | n/a | yes | -| [support\_emails\_for\_cloudwatch\_alerts](#input\_support\_emails\_for\_cloudwatch\_alerts) | List of emails that will receive alerts from CloudWatch | `list(string)` | n/a | yes | -| [tags](#input\_tags) | A common map of tags for all VPC resources that are created (for e.g. billing purposes) | `map(string)` |
{
"Resource": "data-f1-rapid"
}
| no | -| [vpc\_id](#input\_vpc\_id) | Application VPC | `string` | n/a | yes | +| Name | Description | Type | Default | Required | +| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | :------: | +| [allowed_email_domains](#input_allowed_email_domains) | List of allowed emails domains that can be associated with users | `string` | n/a | yes | +| [app-replica-count-desired](#input_app-replica-count-desired) | The desired number of replicas of the app | `number` | `1` | no | +| [app-replica-count-max](#input_app-replica-count-max) | The maximum desired number of replicas of the app | `number` | `2` | no | +| [application_version](#input_application_version) | The version number for the application image (e.g.: v1.0.4, v1.0.x-latest, etc.) | `string` | n/a | yes | +| [athena_query_output_bucket_arn](#input_athena_query_output_bucket_arn) | The S3 bucket ARN where Athena stores its query results. This bucket is created dynamically with a unique name in the data-workflow module. Reference it by remote state, module output or ARN string directly | `string` | n/a | yes | +| [aws_account](#input_aws_account) | AWS Account number to host the rAPId service | `string` | n/a | yes | +| [aws_region](#input_aws_region) | The region of the AWS Account for the rAPId service | `string` | n/a | yes | +| [catalog_disabled](#input_catalog_disabled) | Optional value on whether to disable the internal rAPId data catalog | `bool` | `false` | no | +| [certificate_validation_arn](#input_certificate_validation_arn) | Arn of the certificate used by the domain | `string` | n/a | yes | +| [cognito_user_login_app_credentials_secrets_name](#input_cognito_user_login_app_credentials_secrets_name) | Secret name for Cognito user login app credentials | `string` | n/a | yes | +| [cognito_user_pool_id](#input_cognito_user_pool_id) | User pool id for cognito | `string` | n/a | yes | +| [container_port](#input_container_port) | The port for the running ECS containers | `number` | `8000` | no | +| [data_s3_bucket_arn](#input_data_s3_bucket_arn) | S3 Bucket arn to store application data | `string` | n/a | yes | +| [data_s3_bucket_name](#input_data_s3_bucket_name) | S3 Bucket name to store application data | `string` | n/a | yes | +| [domain_name](#input_domain_name) | Domain name for the rAPId instance | `string` | n/a | yes | +| [ecs_cluster_arn](#input_ecs_cluster_arn) | ECS cliuster arn to attach the rAPId api to | `string` | `null` | no | +| [ecs_cluster_id](#input_ecs_cluster_id) | ECS cluster id to attach the rAPId api to | `string` | `null` | no | +| [ecs_cluster_name](#input_ecs_cluster_name) | ECS cluster name to attach the rAPId api to | `string` | `null` | no | +| [enable_cloudtrail](#input_enable_cloudtrail) | Whether to enable the logging of db events to CloudTrail | `bool` | `true` | no | +| [host_port](#input_host_port) | The host port for the running ECS containers | `number` | `8000` | no | +| [hosted_zone_id](#input_hosted_zone_id) | Hosted Zone ID with the domain Name Servers, pass quotes to create a new one from scratch | `string` | n/a | yes | +| [ip_whitelist](#input_ip_whitelist) | A list of IPs to whitelist for access to the service | `list(string)` | n/a | yes | +| [log_bucket_name](#input_log_bucket_name) | A bucket to send the Load Balancer logs | `string` | n/a | yes | +| [permissions_table](#input_permissions_table) | Users permissions table in dynamoDB | `string` | n/a | yes | +| [permissions_table_arn](#input_permissions_table_arn) | Users permissions table arn in dynamoDB | `string` | n/a | yes | +| [private_subnet_ids_list](#input_private_subnet_ids_list) | Application Private subnet list | `list(string)` | n/a | yes | +| [project_information](#input_project_information) | n/a |
object({
project_name = optional(string),
project_description = optional(string),
project_contact = optional(string),
project_organisation = optional(string)
})
|
{
"project_contact": "",
"project_description": "",
"project_name": "",
"project_organisation": ""
}
| no | +| [protocol](#input_protocol) | The protocol for the running ECS container | `string` | `"tcp"` | no | +| [public_subnet_ids_list](#input_public_subnet_ids_list) | Application Public subnet list | `list(string)` | n/a | yes | +| [rapid_ecr_url](#input_rapid_ecr_url) | ECR Url for task definition | `string` | n/a | yes | +| [resource-name-prefix](#input_resource-name-prefix) | The prefix to add to resources for easier identification | `string` | n/a | yes | +| [support_emails_for_cloudwatch_alerts](#input_support_emails_for_cloudwatch_alerts) | List of emails that will receive alerts from CloudWatch | `list(string)` | n/a | yes | +| [tags](#input_tags) | A common map of tags for all VPC resources that are created (for e.g. billing purposes) | `map(string)` |
{
"Resource": "data-f1-rapid"
}
| no | +| [vpc_id](#input_vpc_id) | Application VPC | `string` | n/a | yes | ## Outputs -| Name | Description | -|------|-------------| -| [ecs\_cluster\_arn](#output\_ecs\_cluster\_arn) | Cluster identifier | -| [ecs\_task\_execution\_role\_arn](#output\_ecs\_task\_execution\_role\_arn) | The ECS task execution role ARN | -| [hosted\_zone\_id](#output\_hosted\_zone\_id) | n/a | -| [hosted\_zone\_name\_servers](#output\_hosted\_zone\_name\_servers) | Name servers of the primary hosted zone linked to the domain | -| [load\_balancer\_arn](#output\_load\_balancer\_arn) | The arn of the load balancer | -| [load\_balancer\_dns](#output\_load\_balancer\_dns) | The DNS name of the load balancer | -| [log\_error\_alarm\_notification\_arn](#output\_log\_error\_alarm\_notification\_arn) | The arn of the sns topic that receives notifications on log error alerts | -| [rapid\_metric\_log\_error\_alarm\_arn](#output\_rapid\_metric\_log\_error\_alarm\_arn) | The arn of the log error alarm metric | -| [route\_53\_validation\_record\_fqdns](#output\_route\_53\_validation\_record\_fqdns) | The fqdns of the route53 validation records for the certificate | -| [service\_table\_arn](#output\_service\_table\_arn) | The arn of the dynamoDB table that stores the user service | +| Name | Description | +| ----------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------ | +| [ecs_cluster_arn](#output_ecs_cluster_arn) | Cluster identifier | +| [ecs_task_execution_role_arn](#output_ecs_task_execution_role_arn) | The ECS task execution role ARN | +| [hosted_zone_id](#output_hosted_zone_id) | n/a | +| [hosted_zone_name_servers](#output_hosted_zone_name_servers) | Name servers of the primary hosted zone linked to the domain | +| [load_balancer_arn](#output_load_balancer_arn) | The arn of the load balancer | +| [load_balancer_dns](#output_load_balancer_dns) | The DNS name of the load balancer | +| [log_error_alarm_notification_arn](#output_log_error_alarm_notification_arn) | The arn of the sns topic that receives notifications on log error alerts | +| [rapid_metric_log_error_alarm_arn](#output_rapid_metric_log_error_alarm_arn) | The arn of the log error alarm metric | +| [route_53_validation_record_fqdns](#output_route_53_validation_record_fqdns) | The fqdns of the route53 validation records for the certificate | +| [service_table_arn](#output_service_table_arn) | The arn of the dynamoDB table that stores the user service | + diff --git a/infrastructure/modules/auth/README.md b/infrastructure/modules/auth/README.md index e8db51d..6c592e9 100644 --- a/infrastructure/modules/auth/README.md +++ b/infrastructure/modules/auth/README.md @@ -1,14 +1,15 @@ + ## Requirements No requirements. ## Providers -| Name | Version | -|------|---------| -| [aws](#provider\_aws) | n/a | -| [random](#provider\_random) | n/a | +| Name | Version | +| --------------------------------------------------------- | ------- | +| [aws](#provider_aws) | n/a | +| [random](#provider_random) | n/a | ## Modules @@ -16,70 +17,71 @@ No modules. ## Resources -| Name | Type | -|------|------| -| [aws_cognito_resource_server.rapid_resource_server](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cognito_resource_server) | resource | -| [aws_cognito_user.ui_test_user](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cognito_user) | resource | -| [aws_cognito_user_pool.rapid_user_pool](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cognito_user_pool) | resource | -| [aws_cognito_user_pool_client.e2e_test_client_data_admin](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cognito_user_pool_client) | resource | -| [aws_cognito_user_pool_client.e2e_test_client_read_and_write](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cognito_user_pool_client) | resource | -| [aws_cognito_user_pool_client.e2e_test_client_user_admin](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cognito_user_pool_client) | resource | -| [aws_cognito_user_pool_client.e2e_test_client_write_all](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cognito_user_pool_client) | resource | -| [aws_cognito_user_pool_client.test_client](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cognito_user_pool_client) | resource | -| [aws_cognito_user_pool_client.user_login](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cognito_user_pool_client) | resource | -| [aws_cognito_user_pool_domain.rapid_cognito_domain](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cognito_user_pool_domain) | resource | -| [aws_dynamodb_table.permissions_table](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/dynamodb_table) | resource | -| [aws_dynamodb_table_item.admin_permissions](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/dynamodb_table_item) | resource | -| [aws_dynamodb_table_item.data_permissions](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/dynamodb_table_item) | resource | -| [aws_dynamodb_table_item.test_client_data_admin_permissions](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/dynamodb_table_item) | resource | -| [aws_dynamodb_table_item.test_client_permissions](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/dynamodb_table_item) | resource | -| [aws_dynamodb_table_item.test_client_read_and_write_permissions](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/dynamodb_table_item) | resource | -| [aws_dynamodb_table_item.test_client_user_admin_permissions](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/dynamodb_table_item) | resource | -| [aws_dynamodb_table_item.test_client_write_all_permissions](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/dynamodb_table_item) | resource | -| [aws_dynamodb_table_item.ui_test_user_permissions](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/dynamodb_table_item) | resource | -| [aws_secretsmanager_secret.client_secrets_cognito](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret) | resource | -| [aws_secretsmanager_secret.e2e_test_client_data_admin](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret) | resource | -| [aws_secretsmanager_secret.e2e_test_client_read_and_write](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret) | resource | -| [aws_secretsmanager_secret.e2e_test_client_user_admin](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret) | resource | -| [aws_secretsmanager_secret.e2e_test_client_write_all](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret) | resource | -| [aws_secretsmanager_secret.ui_test_user](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret) | resource | -| [aws_secretsmanager_secret.user_secrets_cognito](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret) | resource | -| [aws_secretsmanager_secret_version.client_secrets_version](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret_version) | resource | -| [aws_secretsmanager_secret_version.e2e_test_client_data_admin_secrets_version](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret_version) | resource | -| [aws_secretsmanager_secret_version.e2e_test_client_read_and_write_secrets_version](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret_version) | resource | -| [aws_secretsmanager_secret_version.e2e_test_client_user_admin_secrets_version](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret_version) | resource | -| [aws_secretsmanager_secret_version.e2e_test_client_write_all_secrets_version](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret_version) | resource | -| [aws_secretsmanager_secret_version.ui_test_user_secrets_version](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret_version) | resource | -| [aws_secretsmanager_secret_version.user_login_client_secrets_version](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret_version) | resource | -| [random_password.password](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/password) | resource | -| [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | -| [aws_region.region](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source | +| Name | Type | +| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- | +| [aws_cognito_resource_server.rapid_resource_server](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cognito_resource_server) | resource | +| [aws_cognito_user.ui_test_user](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cognito_user) | resource | +| [aws_cognito_user_pool.rapid_user_pool](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cognito_user_pool) | resource | +| [aws_cognito_user_pool_client.e2e_test_client_data_admin](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cognito_user_pool_client) | resource | +| [aws_cognito_user_pool_client.e2e_test_client_read_and_write](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cognito_user_pool_client) | resource | +| [aws_cognito_user_pool_client.e2e_test_client_user_admin](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cognito_user_pool_client) | resource | +| [aws_cognito_user_pool_client.e2e_test_client_write_all](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cognito_user_pool_client) | resource | +| [aws_cognito_user_pool_client.test_client](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cognito_user_pool_client) | resource | +| [aws_cognito_user_pool_client.user_login](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cognito_user_pool_client) | resource | +| [aws_cognito_user_pool_domain.rapid_cognito_domain](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cognito_user_pool_domain) | resource | +| [aws_dynamodb_table.permissions_table](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/dynamodb_table) | resource | +| [aws_dynamodb_table_item.admin_permissions](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/dynamodb_table_item) | resource | +| [aws_dynamodb_table_item.data_permissions](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/dynamodb_table_item) | resource | +| [aws_dynamodb_table_item.test_client_data_admin_permissions](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/dynamodb_table_item) | resource | +| [aws_dynamodb_table_item.test_client_permissions](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/dynamodb_table_item) | resource | +| [aws_dynamodb_table_item.test_client_read_and_write_permissions](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/dynamodb_table_item) | resource | +| [aws_dynamodb_table_item.test_client_user_admin_permissions](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/dynamodb_table_item) | resource | +| [aws_dynamodb_table_item.test_client_write_all_permissions](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/dynamodb_table_item) | resource | +| [aws_dynamodb_table_item.ui_test_user_permissions](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/dynamodb_table_item) | resource | +| [aws_secretsmanager_secret.client_secrets_cognito](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret) | resource | +| [aws_secretsmanager_secret.e2e_test_client_data_admin](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret) | resource | +| [aws_secretsmanager_secret.e2e_test_client_read_and_write](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret) | resource | +| [aws_secretsmanager_secret.e2e_test_client_user_admin](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret) | resource | +| [aws_secretsmanager_secret.e2e_test_client_write_all](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret) | resource | +| [aws_secretsmanager_secret.ui_test_user](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret) | resource | +| [aws_secretsmanager_secret.user_secrets_cognito](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret) | resource | +| [aws_secretsmanager_secret_version.client_secrets_version](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret_version) | resource | +| [aws_secretsmanager_secret_version.e2e_test_client_data_admin_secrets_version](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret_version) | resource | +| [aws_secretsmanager_secret_version.e2e_test_client_read_and_write_secrets_version](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret_version) | resource | +| [aws_secretsmanager_secret_version.e2e_test_client_user_admin_secrets_version](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret_version) | resource | +| [aws_secretsmanager_secret_version.e2e_test_client_write_all_secrets_version](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret_version) | resource | +| [aws_secretsmanager_secret_version.ui_test_user_secrets_version](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret_version) | resource | +| [aws_secretsmanager_secret_version.user_login_client_secrets_version](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret_version) | resource | +| [random_password.password](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/password) | resource | +| [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | +| [aws_region.region](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source | ## Inputs -| Name | Description | Type | Default | Required | -|------|-------------|------|---------|:--------:| -| [admin\_permissions](#input\_admin\_permissions) | n/a | `map(map(any))` |
{
"DATA_ADMIN": {
"type": "DATA_ADMIN"
},
"USER_ADMIN": {
"type": "USER_ADMIN"
}
}
| no | -| [data\_permissions](#input\_data\_permissions) | n/a | `map(map(any))` |
{
"READ_ALL": {
"sensitivity": "ALL",
"type": "READ"
},
"READ_PRIVATE": {
"sensitivity": "PRIVATE",
"type": "READ"
},
"READ_PUBLIC": {
"sensitivity": "PUBLIC",
"type": "READ"
},
"READ_SENSITIVE": {
"sensitivity": "SENSITIVE",
"type": "READ"
},
"WRITE_ALL": {
"sensitivity": "ALL",
"type": "WRITE"
},
"WRITE_PRIVATE": {
"sensitivity": "PRIVATE",
"type": "WRITE"
},
"WRITE_PUBLIC": {
"sensitivity": "PUBLIC",
"type": "WRITE"
},
"WRITE_SENSITIVE": {
"sensitivity": "SENSITIVE",
"type": "WRITE"
}
}
| no | -| [domain\_name](#input\_domain\_name) | Domain name for the rAPId instance | `string` | n/a | yes | -| [password\_policy](#input\_password\_policy) | The Cognito pool password policy |
object({
minimum_length = number
require_lowercase = bool
require_numbers = bool
require_symbols = bool
require_uppercase = bool
temporary_password_validity_days = number
})
|
{
"minimum_length": 8,
"require_lowercase": true,
"require_numbers": true,
"require_symbols": true,
"require_uppercase": true,
"temporary_password_validity_days": 7
}
| no | -| [permissions\_table\_name](#input\_permissions\_table\_name) | The name of the users permissions table in DynamoDb | `string` | `"users_permissions"` | no | -| [rapid\_client\_explicit\_auth\_flows](#input\_rapid\_client\_explicit\_auth\_flows) | The list of auth flows supported by the client app | `list(string)` |
[
"ALLOW_REFRESH_TOKEN_AUTH",
"ALLOW_CUSTOM_AUTH",
"ALLOW_USER_SRP_AUTH"
]
| no | -| [rapid\_user\_login\_client\_explicit\_auth\_flows](#input\_rapid\_user\_login\_client\_explicit\_auth\_flows) | The list of auth flows supported by the user login app | `list(string)` |
[
"ALLOW_REFRESH_TOKEN_AUTH",
"ALLOW_USER_SRP_AUTH"
]
| no | -| [resource-name-prefix](#input\_resource-name-prefix) | The prefix to add to resources for easier identification | `string` | n/a | yes | -| [scopes](#input\_scopes) | n/a | `list(map(any))` |
[
{
"scope_description": "Client app default access",
"scope_name": "CLIENT_APP"
}
]
| no | -| [tags](#input\_tags) | A common map of tags for all VPC resources that are created (for e.g. billing purposes) | `map(string)` |
{
"Resource": "data-f1-rapid"
}
| no | +| Name | Description | Type | Default | Required | +| ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :------: | +| [admin_permissions](#input_admin_permissions) | n/a | `map(map(any))` |
{
"DATA_ADMIN": {
"type": "DATA_ADMIN"
},
"USER_ADMIN": {
"type": "USER_ADMIN"
}
}
| no | +| [data_permissions](#input_data_permissions) | n/a | `map(map(any))` |
{
"READ_ALL": {
"sensitivity": "ALL",
"type": "READ"
},
"READ_PRIVATE": {
"sensitivity": "PRIVATE",
"type": "READ"
},
"READ_PUBLIC": {
"sensitivity": "PUBLIC",
"type": "READ"
},
"READ_SENSITIVE": {
"sensitivity": "SENSITIVE",
"type": "READ"
},
"WRITE_ALL": {
"sensitivity": "ALL",
"type": "WRITE"
},
"WRITE_PRIVATE": {
"sensitivity": "PRIVATE",
"type": "WRITE"
},
"WRITE_PUBLIC": {
"sensitivity": "PUBLIC",
"type": "WRITE"
},
"WRITE_SENSITIVE": {
"sensitivity": "SENSITIVE",
"type": "WRITE"
}
}
| no | +| [domain_name](#input_domain_name) | Domain name for the rAPId instance | `string` | n/a | yes | +| [password_policy](#input_password_policy) | The Cognito pool password policy |
object({
minimum_length = number
require_lowercase = bool
require_numbers = bool
require_symbols = bool
require_uppercase = bool
temporary_password_validity_days = number
})
|
{
"minimum_length": 8,
"require_lowercase": true,
"require_numbers": true,
"require_symbols": true,
"require_uppercase": true,
"temporary_password_validity_days": 7
}
| no | +| [permissions_table_name](#input_permissions_table_name) | The name of the users permissions table in DynamoDb | `string` | `"users_permissions"` | no | +| [rapid_client_explicit_auth_flows](#input_rapid_client_explicit_auth_flows) | The list of auth flows supported by the client app | `list(string)` |
[
"ALLOW_REFRESH_TOKEN_AUTH",
"ALLOW_CUSTOM_AUTH",
"ALLOW_USER_SRP_AUTH"
]
| no | +| [rapid_user_login_client_explicit_auth_flows](#input_rapid_user_login_client_explicit_auth_flows) | The list of auth flows supported by the user login app | `list(string)` |
[
"ALLOW_REFRESH_TOKEN_AUTH",
"ALLOW_USER_SRP_AUTH"
]
| no | +| [resource-name-prefix](#input_resource-name-prefix) | The prefix to add to resources for easier identification | `string` | n/a | yes | +| [scopes](#input_scopes) | n/a | `list(map(any))` |
[
{
"scope_description": "Client app default access",
"scope_name": "CLIENT_APP"
}
]
| no | +| [tags](#input_tags) | A common map of tags for all VPC resources that are created (for e.g. billing purposes) | `map(string)` |
{
"Resource": "data-f1-rapid"
}
| no | ## Outputs -| Name | Description | -|------|-------------| -| [cognito\_client\_app\_secret\_manager\_name](#output\_cognito\_client\_app\_secret\_manager\_name) | Secret manager name where client app info is stored | -| [cognito\_user\_app\_secret\_manager\_name](#output\_cognito\_user\_app\_secret\_manager\_name) | Secret manager name where user login app info is stored | -| [cognito\_user\_pool\_id](#output\_cognito\_user\_pool\_id) | The Cognito rapid user pool id | -| [rapid\_test\_client\_id](#output\_rapid\_test\_client\_id) | The rapid test client id registered in the user pool | -| [resource\_server\_scopes](#output\_resource\_server\_scopes) | The scopes defined in the resource server | -| [user\_permission\_table\_arn](#output\_user\_permission\_table\_arn) | The arn of the dynamoDB table that stores permissions | -| [user\_permission\_table\_name](#output\_user\_permission\_table\_name) | The name of the dynamoDB table that stores permissions | -| [user\_pool\_endpoint](#output\_user\_pool\_endpoint) | The Cognito rapid user pool endpoint | +| Name | Description | +| ----------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------- | +| [cognito_client_app_secret_manager_name](#output_cognito_client_app_secret_manager_name) | Secret manager name where client app info is stored | +| [cognito_user_app_secret_manager_name](#output_cognito_user_app_secret_manager_name) | Secret manager name where user login app info is stored | +| [cognito_user_pool_id](#output_cognito_user_pool_id) | The Cognito rapid user pool id | +| [rapid_test_client_id](#output_rapid_test_client_id) | The rapid test client id registered in the user pool | +| [resource_server_scopes](#output_resource_server_scopes) | The scopes defined in the resource server | +| [user_permission_table_arn](#output_user_permission_table_arn) | The arn of the dynamoDB table that stores permissions | +| [user_permission_table_name](#output_user_permission_table_name) | The name of the dynamoDB table that stores permissions | +| [user_pool_endpoint](#output_user_pool_endpoint) | The Cognito rapid user pool endpoint | + diff --git a/infrastructure/modules/data-workflow/README.md b/infrastructure/modules/data-workflow/README.md index 0e28b19..9982211 100644 --- a/infrastructure/modules/data-workflow/README.md +++ b/infrastructure/modules/data-workflow/README.md @@ -1,13 +1,14 @@ + ## Requirements No requirements. ## Providers -| Name | Version | -|------|---------| -| [aws](#provider\_aws) | 4.50.0 | +| Name | Version | +| ------------------------------------------------ | ------- | +| [aws](#provider_aws) | 4.50.0 | ## Modules @@ -15,46 +16,47 @@ No modules. ## Resources -| Name | Type | -|------|------| -| [aws_athena_workgroup.rapid_athena_workgroup](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/athena_workgroup) | resource | -| [aws_cloudwatch_log_group.aws_glue_connection_error_log_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource | -| [aws_cloudwatch_log_group.aws_glue_connection_log_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource | -| [aws_cloudwatch_log_group.aws_glue_crawlers_log_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource | -| [aws_glue_catalog_database.catalogue_db](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/glue_catalog_database) | resource | -| [aws_glue_catalog_table.metadata](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/glue_catalog_table) | resource | -| [aws_glue_connection.glue_connection](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/glue_connection) | resource | -| [aws_iam_policy.crawler_s3_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | -| [aws_iam_role.glue_service_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | -| [aws_iam_role_policy_attachment.glue_service_role_managed_policy_attach](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | -| [aws_iam_role_policy_attachment.glue_service_role_s3_policy_attach](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | -| [aws_s3_bucket.rapid_athena_query_results_bucket](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource | -| [aws_s3_bucket_policy.athena_query_bucket_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_policy) | resource | -| [aws_s3_bucket_public_access_block.rapid_athena_query_results_bucket](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block) | resource | -| [aws_security_group.glue_connection_sg](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource | -| [aws_vpc_endpoint.s3_vpc_endpoint](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_endpoint) | resource | -| [aws_availability_zones.available](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/availability_zones) | data source | -| [aws_prefix_list.s3_prefix](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/prefix_list) | data source | +| Name | Type | +| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- | +| [aws_athena_workgroup.rapid_athena_workgroup](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/athena_workgroup) | resource | +| [aws_cloudwatch_log_group.aws_glue_connection_error_log_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource | +| [aws_cloudwatch_log_group.aws_glue_connection_log_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource | +| [aws_cloudwatch_log_group.aws_glue_crawlers_log_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource | +| [aws_glue_catalog_database.catalogue_db](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/glue_catalog_database) | resource | +| [aws_glue_catalog_table.metadata](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/glue_catalog_table) | resource | +| [aws_glue_connection.glue_connection](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/glue_connection) | resource | +| [aws_iam_policy.crawler_s3_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | +| [aws_iam_role.glue_service_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | +| [aws_iam_role_policy_attachment.glue_service_role_managed_policy_attach](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | +| [aws_iam_role_policy_attachment.glue_service_role_s3_policy_attach](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | +| [aws_s3_bucket.rapid_athena_query_results_bucket](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource | +| [aws_s3_bucket_policy.athena_query_bucket_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_policy) | resource | +| [aws_s3_bucket_public_access_block.rapid_athena_query_results_bucket](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block) | resource | +| [aws_security_group.glue_connection_sg](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource | +| [aws_vpc_endpoint.s3_vpc_endpoint](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_endpoint) | resource | +| [aws_availability_zones.available](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/availability_zones) | data source | +| [aws_prefix_list.s3_prefix](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/prefix_list) | data source | ## Inputs -| Name | Description | Type | Default | Required | -|------|-------------|------|---------|:--------:| -| [aws\_account](#input\_aws\_account) | AWS Account number to host the rAPId service | `string` | n/a | yes | -| [aws\_region](#input\_aws\_region) | The region of the AWS Account for the rAPId service | `string` | n/a | yes | -| [data\_s3\_bucket\_arn](#input\_data\_s3\_bucket\_arn) | S3 Bucket arn to store application data | `string` | n/a | yes | -| [data\_s3\_bucket\_name](#input\_data\_s3\_bucket\_name) | S3 Bucket name to store application data | `string` | n/a | yes | -| [private\_subnet](#input\_private\_subnet) | Application Private subnet | `string` | n/a | yes | -| [resource-name-prefix](#input\_resource-name-prefix) | The prefix to add to resources for easier identification | `string` | n/a | yes | -| [tags](#input\_tags) | A common map of tags for all VPC resources that are created (for e.g. billing purposes) | `map(string)` |
{
"Resource": "data-f1-rapid"
}
| no | -| [vpc\_id](#input\_vpc\_id) | Application VPC | `string` | n/a | yes | +| Name | Description | Type | Default | Required | +| --------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- | ------------- | ------------------------------------------------- | :------: | +| [aws_account](#input_aws_account) | AWS Account number to host the rAPId service | `string` | n/a | yes | +| [aws_region](#input_aws_region) | The region of the AWS Account for the rAPId service | `string` | n/a | yes | +| [data_s3_bucket_arn](#input_data_s3_bucket_arn) | S3 Bucket arn to store application data | `string` | n/a | yes | +| [data_s3_bucket_name](#input_data_s3_bucket_name) | S3 Bucket name to store application data | `string` | n/a | yes | +| [private_subnet](#input_private_subnet) | Application Private subnet | `string` | n/a | yes | +| [resource-name-prefix](#input_resource-name-prefix) | The prefix to add to resources for easier identification | `string` | n/a | yes | +| [tags](#input_tags) | A common map of tags for all VPC resources that are created (for e.g. billing purposes) | `map(string)` |
{
"Resource": "data-f1-rapid"
}
| no | +| [vpc_id](#input_vpc_id) | Application VPC | `string` | n/a | yes | ## Outputs -| Name | Description | -|------|-------------| -| [athena\_query\_result\_output\_bucket\_arn](#output\_athena\_query\_result\_output\_bucket\_arn) | Output S3 bucket ARN for Athena query results | -| [athena\_workgroup\_arn](#output\_athena\_workgroup\_arn) | Query workgroup for Athena | -| [glue\_catalog\_arn](#output\_glue\_catalog\_arn) | Catalog database arn | -| [tags](#output\_tags) | The tags used in the project | +| Name | Description | +| -------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------- | +| [athena_query_result_output_bucket_arn](#output_athena_query_result_output_bucket_arn) | Output S3 bucket ARN for Athena query results | +| [athena_workgroup_arn](#output_athena_workgroup_arn) | Query workgroup for Athena | +| [glue_catalog_arn](#output_glue_catalog_arn) | Catalog database arn | +| [tags](#output_tags) | The tags used in the project | + diff --git a/infrastructure/modules/rapid/README.md b/infrastructure/modules/rapid/README.md index bad5309..0b4b304 100644 --- a/infrastructure/modules/rapid/README.md +++ b/infrastructure/modules/rapid/README.md @@ -3,66 +3,68 @@ Use this module to spin up a rAPId instance within existing AWS infrastructure. + ## Requirements No requirements. ## Providers -| Name | Version | -|------|---------| -| [aws](#provider\_aws) | 4.50.0 | +| Name | Version | +| ------------------------------------------------ | ------- | +| [aws](#provider_aws) | 4.50.0 | ## Modules -| Name | Source | Version | -|------|--------|---------| -| [app\_cluster](#module\_app\_cluster) | ../app-cluster | n/a | -| [auth](#module\_auth) | ../auth | n/a | -| [data\_workflow](#module\_data\_workflow) | ../data-workflow | n/a | -| [ui](#module\_ui) | ../ui | n/a | +| Name | Source | Version | +| -------------------------------------------------------------------------- | ---------------- | ------- | +| [app_cluster](#module_app_cluster) | ../app-cluster | n/a | +| [auth](#module_auth) | ../auth | n/a | +| [data_workflow](#module_data_workflow) | ../data-workflow | n/a | +| [ui](#module_ui) | ../ui | n/a | ## Resources -| Name | Type | -|------|------| -| [aws_s3_bucket.logs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource | -| [aws_s3_bucket.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource | -| [aws_s3_bucket_policy.log_bucket_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_policy) | resource | +| Name | Type | +| --------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | +| [aws_s3_bucket.logs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource | +| [aws_s3_bucket.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource | +| [aws_s3_bucket_policy.log_bucket_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_policy) | resource | | [aws_s3_bucket_public_access_block.logs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block) | resource | | [aws_s3_bucket_public_access_block.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block) | resource | ## Inputs -| Name | Description | Type | Default | Required | -|------|-------------|------|---------|:--------:| -| [allowed\_email\_domains](#input\_allowed\_email\_domains) | List of allowed emails domains that can be associated with users | `string` | n/a | yes | -| [app-replica-count-desired](#input\_app-replica-count-desired) | The desired number of replicas of the app | `number` | `1` | no | -| [app-replica-count-max](#input\_app-replica-count-max) | The maximum desired number of replicas of the app | `number` | `2` | no | -| [application\_version](#input\_application\_version) | The version number for the application image (e.g.: v1.0.4, v1.0.x-latest, etc.) | `string` | `"v6.0.1"` | no | -| [aws\_account](#input\_aws\_account) | AWS Account number to host the rAPId service | `string` | n/a | yes | -| [aws\_region](#input\_aws\_region) | The region of the AWS Account for the rAPId service | `string` | n/a | yes | -| [catalog\_disabled](#input\_catalog\_disabled) | Optional value on whether to disable the internal rAPId data catalog | `bool` | `false` | no | -| [certificate\_validation\_arn](#input\_certificate\_validation\_arn) | Arn of the certificate used by the domain | `string` | `""` | no | -| [domain\_name](#input\_domain\_name) | Domain name for the rAPId instance | `string` | n/a | yes | -| [ecs\_cluster\_arn](#input\_ecs\_cluster\_arn) | ECS cliuster arn to attach the rAPId api to | `string` | `null` | no | -| [ecs\_cluster\_id](#input\_ecs\_cluster\_id) | ECS cluster id to attach the rAPId api to | `string` | `null` | no | -| [ecs\_cluster\_name](#input\_ecs\_cluster\_name) | ECS cluster name to attach the rAPId api to | `string` | `null` | no | -| [enable\_cloudtrail](#input\_enable\_cloudtrail) | Whether to enable the logging of db events to CloudTrail | `bool` | `true` | no | -| [hosted\_zone\_id](#input\_hosted\_zone\_id) | Hosted Zone ID with the domain Name Servers, pass quotes to create a new one from scratch | `string` | `""` | no | -| [ip\_whitelist](#input\_ip\_whitelist) | A list of IPs to whitelist for access to the service | `list(string)` | n/a | yes | -| [password\_policy](#input\_password\_policy) | The Cognito pool password policy |
object({
minimum_length = number
require_lowercase = bool
require_numbers = bool
require_symbols = bool
require_uppercase = bool
temporary_password_validity_days = number
})
|
{
"minimum_length": 8,
"require_lowercase": true,
"require_numbers": true,
"require_symbols": true,
"require_uppercase": true,
"temporary_password_validity_days": 7
}
| no | -| [private\_subnet\_ids\_list](#input\_private\_subnet\_ids\_list) | A list of private subnets from each organisation network config | `list(string)` | n/a | yes | -| [public\_subnet\_ids\_list](#input\_public\_subnet\_ids\_list) | A list of public subnets from the VPC config | `list(string)` | n/a | yes | -| [rapid\_ecr\_url](#input\_rapid\_ecr\_url) | ECR Url for task definition | `string` | `"public.ecr.aws/no10-rapid/api"` | no | -| [resource-name-prefix](#input\_resource-name-prefix) | organization prefix of for naming | `string` | n/a | yes | -| [support\_emails\_for\_cloudwatch\_alerts](#input\_support\_emails\_for\_cloudwatch\_alerts) | List of emails that will receive alerts from CloudWatch | `list(string)` | n/a | yes | -| [tags](#input\_tags) | A common map of tags for all VPC resources that are created (for e.g. billing purposes) | `map(string)` |
{
"Resource": "data-f1-rapid"
}
| no | -| [ui\_version](#input\_ui\_version) | The version number for the static ui (e.g.: v1.0.0, etc.) | `string` | `"v6.0.1"` | no | -| [us\_east\_certificate\_validation\_arn](#input\_us\_east\_certificate\_validation\_arn) | Arn of the certificate used by Cloudfront. Please note this has to live in us-east-1. | `string` | `""` | no | -| [vpc\_id](#input\_vpc\_id) | The ID of the multihost VPC | `string` | n/a | yes | +| Name | Description | Type | Default | Required | +| --------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :------: | +| [allowed_email_domains](#input_allowed_email_domains) | List of allowed emails domains that can be associated with users | `string` | n/a | yes | +| [app-replica-count-desired](#input_app-replica-count-desired) | The desired number of replicas of the app | `number` | `1` | no | +| [app-replica-count-max](#input_app-replica-count-max) | The maximum desired number of replicas of the app | `number` | `2` | no | +| [application_version](#input_application_version) | The version number for the application image (e.g.: v1.0.4, v1.0.x-latest, etc.) | `string` | `"v6.0.1"` | no | +| [aws_account](#input_aws_account) | AWS Account number to host the rAPId service | `string` | n/a | yes | +| [aws_region](#input_aws_region) | The region of the AWS Account for the rAPId service | `string` | n/a | yes | +| [catalog_disabled](#input_catalog_disabled) | Optional value on whether to disable the internal rAPId data catalog | `bool` | `false` | no | +| [certificate_validation_arn](#input_certificate_validation_arn) | Arn of the certificate used by the domain | `string` | `""` | no | +| [domain_name](#input_domain_name) | Domain name for the rAPId instance | `string` | n/a | yes | +| [ecs_cluster_arn](#input_ecs_cluster_arn) | ECS cliuster arn to attach the rAPId api to | `string` | `null` | no | +| [ecs_cluster_id](#input_ecs_cluster_id) | ECS cluster id to attach the rAPId api to | `string` | `null` | no | +| [ecs_cluster_name](#input_ecs_cluster_name) | ECS cluster name to attach the rAPId api to | `string` | `null` | no | +| [enable_cloudtrail](#input_enable_cloudtrail) | Whether to enable the logging of db events to CloudTrail | `bool` | `true` | no | +| [hosted_zone_id](#input_hosted_zone_id) | Hosted Zone ID with the domain Name Servers, pass quotes to create a new one from scratch | `string` | `""` | no | +| [ip_whitelist](#input_ip_whitelist) | A list of IPs to whitelist for access to the service | `list(string)` | n/a | yes | +| [password_policy](#input_password_policy) | The Cognito pool password policy |
object({
minimum_length = number
require_lowercase = bool
require_numbers = bool
require_symbols = bool
require_uppercase = bool
temporary_password_validity_days = number
})
|
{
"minimum_length": 8,
"require_lowercase": true,
"require_numbers": true,
"require_symbols": true,
"require_uppercase": true,
"temporary_password_validity_days": 7
}
| no | +| [private_subnet_ids_list](#input_private_subnet_ids_list) | A list of private subnets from each organisation network config | `list(string)` | n/a | yes | +| [public_subnet_ids_list](#input_public_subnet_ids_list) | A list of public subnets from the VPC config | `list(string)` | n/a | yes | +| [rapid_ecr_url](#input_rapid_ecr_url) | ECR Url for task definition | `string` | `"public.ecr.aws/no10-rapid/api"` | no | +| [resource-name-prefix](#input_resource-name-prefix) | organization prefix of for naming | `string` | n/a | yes | +| [support_emails_for_cloudwatch_alerts](#input_support_emails_for_cloudwatch_alerts) | List of emails that will receive alerts from CloudWatch | `list(string)` | n/a | yes | +| [tags](#input_tags) | A common map of tags for all VPC resources that are created (for e.g. billing purposes) | `map(string)` |
{
"Resource": "data-f1-rapid"
}
| no | +| [ui_version](#input_ui_version) | The version number for the static ui (e.g.: v1.0.0, etc.) | `string` | `"v6.0.1"` | no | +| [us_east_certificate_validation_arn](#input_us_east_certificate_validation_arn) | Arn of the certificate used by Cloudfront. Please note this has to live in us-east-1. | `string` | `""` | no | +| [vpc_id](#input_vpc_id) | The ID of the multihost VPC | `string` | n/a | yes | ## Outputs No outputs. + diff --git a/infrastructure/modules/rapid/main.tf b/infrastructure/modules/rapid/main.tf index c9b50e5..397a1a2 100644 --- a/infrastructure/modules/rapid/main.tf +++ b/infrastructure/modules/rapid/main.tf @@ -7,8 +7,8 @@ module "app_cluster" { support_emails_for_cloudwatch_alerts = var.support_emails_for_cloudwatch_alerts cognito_user_login_app_credentials_secrets_name = module.auth.cognito_user_app_secret_manager_name cognito_user_pool_id = module.auth.cognito_user_pool_id - permissions_table = module.auth.user_permission_table_name permissions_table_arn = module.auth.user_permission_table_arn + schema_table_arn = module.data_workflow.schema_table_arn domain_name = var.domain_name allowed_email_domains = var.allowed_email_domains rapid_ecr_url = var.rapid_ecr_url diff --git a/infrastructure/modules/ui/README.md b/infrastructure/modules/ui/README.md index f6203ef..86ed79c 100644 --- a/infrastructure/modules/ui/README.md +++ b/infrastructure/modules/ui/README.md @@ -1,16 +1,17 @@ + ## Requirements No requirements. ## Providers -| Name | Version | -|------|---------| -| [aws](#provider\_aws) | n/a | -| [aws.us\_east](#provider\_aws.us\_east) | n/a | -| [null](#provider\_null) | n/a | -| [random](#provider\_random) | n/a | +| Name | Version | +| ------------------------------------------------------------------------ | ------- | +| [aws](#provider_aws) | n/a | +| [aws.us_east](#provider_aws.us_east) | n/a | +| [null](#provider_null) | n/a | +| [random](#provider_random) | n/a | ## Modules @@ -18,53 +19,54 @@ No modules. ## Resources -| Name | Type | -|------|------| -| [aws_acm_certificate.rapid_certificate](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/acm_certificate) | resource | -| [aws_acm_certificate_validation.rapid_certificate](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/acm_certificate_validation) | resource | -| [aws_cloudfront_cache_policy.rapid_ui_lb](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudfront_cache_policy) | resource | -| [aws_cloudfront_distribution.rapid_ui](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudfront_distribution) | resource | -| [aws_cloudfront_origin_access_identity.rapid_ui](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudfront_origin_access_identity) | resource | -| [aws_cloudfront_origin_request_policy.rapid_ui_lb](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudfront_origin_request_policy) | resource | -| [aws_iam_role.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | -| [aws_iam_role_policy.github_runner_lambda](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | -| [aws_lambda_function.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_function) | resource | -| [aws_route53_record.rapid_validation_record](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_record) | resource | -| [aws_route53_record.route-to-cloudfront](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_record) | resource | -| [aws_s3_bucket.rapid_ui](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource | -| [aws_s3_bucket_acl.rapid_ui_storage_acl](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_acl) | resource | -| [aws_s3_bucket_policy.s3](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_policy) | resource | -| [aws_s3_bucket_website_configuration.rapid_ui_website](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_website_configuration) | resource | -| [aws_wafv2_ip_set.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/wafv2_ip_set) | resource | -| [aws_wafv2_web_acl.rapid_acl](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/wafv2_web_acl) | resource | -| [null_resource.download_static_ui](https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource) | resource | -| [random_string.bucket_id](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/string) | resource | -| [random_string.random_cloudfront_header](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/string) | resource | -| [aws_cloudfront_cache_policy.optimised](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/cloudfront_cache_policy) | data source | -| [aws_iam_policy_document.s3](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | -| [aws_iam_policy_document.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| Name | Type | +| ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- | +| [aws_acm_certificate.rapid_certificate](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/acm_certificate) | resource | +| [aws_acm_certificate_validation.rapid_certificate](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/acm_certificate_validation) | resource | +| [aws_cloudfront_cache_policy.rapid_ui_lb](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudfront_cache_policy) | resource | +| [aws_cloudfront_distribution.rapid_ui](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudfront_distribution) | resource | +| [aws_cloudfront_origin_access_identity.rapid_ui](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudfront_origin_access_identity) | resource | +| [aws_cloudfront_origin_request_policy.rapid_ui_lb](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudfront_origin_request_policy) | resource | +| [aws_iam_role.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | +| [aws_iam_role_policy.github_runner_lambda](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | +| [aws_lambda_function.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_function) | resource | +| [aws_route53_record.rapid_validation_record](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_record) | resource | +| [aws_route53_record.route-to-cloudfront](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_record) | resource | +| [aws_s3_bucket.rapid_ui](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource | +| [aws_s3_bucket_acl.rapid_ui_storage_acl](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_acl) | resource | +| [aws_s3_bucket_policy.s3](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_policy) | resource | +| [aws_s3_bucket_website_configuration.rapid_ui_website](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_website_configuration) | resource | +| [aws_wafv2_ip_set.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/wafv2_ip_set) | resource | +| [aws_wafv2_web_acl.rapid_acl](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/wafv2_web_acl) | resource | +| [null_resource.download_static_ui](https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource) | resource | +| [random_string.bucket_id](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/string) | resource | +| [random_string.random_cloudfront_header](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/string) | resource | +| [aws_cloudfront_cache_policy.optimised](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/cloudfront_cache_policy) | data source | +| [aws_iam_policy_document.s3](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | ## Inputs -| Name | Description | Type | Default | Required | -|------|-------------|------|---------|:--------:| -| [aws\_account](#input\_aws\_account) | AWS Account number to host the rAPId service | `string` | n/a | yes | -| [domain\_name](#input\_domain\_name) | Domain name for the rAPId instance | `string` | n/a | yes | -| [hosted\_zone\_id](#input\_hosted\_zone\_id) | Hosted Zone ID with the domain Name Servers, pass quotes to create a new one from scratch | `string` | n/a | yes | -| [ip\_whitelist](#input\_ip\_whitelist) | A list of IPs to whitelist for access to the service | `list(string)` | n/a | yes | -| [load\_balancer\_dns](#input\_load\_balancer\_dns) | The DNS name of the load balancer | `string` | n/a | yes | -| [log\_bucket\_name](#input\_log\_bucket\_name) | A bucket to send the Cloudfront logs | `string` | n/a | yes | -| [resource-name-prefix](#input\_resource-name-prefix) | The prefix to add to resources for easier identification | `string` | n/a | yes | -| [route\_53\_validation\_record\_fqdns](#input\_route\_53\_validation\_record\_fqdns) | The fqdns of the route53 validation records for the load balancer certificate | `list(string)` | `[]` | no | -| [tags](#input\_tags) | A common map of tags for all VPC resources that are created (for e.g. billing purposes) | `map(string)` | n/a | yes | -| [ui\_version](#input\_ui\_version) | Version number for the built ui static files (e.g. v5.0) | `string` | n/a | yes | -| [us\_east\_certificate\_validation\_arn](#input\_us\_east\_certificate\_validation\_arn) | Arn of the certificate used by Cloudfront. Please note this has to live in us-east-1. | `string` | n/a | yes | +| Name | Description | Type | Default | Required | +| --------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- | -------------- | ------- | :------: | +| [aws_account](#input_aws_account) | AWS Account number to host the rAPId service | `string` | n/a | yes | +| [domain_name](#input_domain_name) | Domain name for the rAPId instance | `string` | n/a | yes | +| [hosted_zone_id](#input_hosted_zone_id) | Hosted Zone ID with the domain Name Servers, pass quotes to create a new one from scratch | `string` | n/a | yes | +| [ip_whitelist](#input_ip_whitelist) | A list of IPs to whitelist for access to the service | `list(string)` | n/a | yes | +| [load_balancer_dns](#input_load_balancer_dns) | The DNS name of the load balancer | `string` | n/a | yes | +| [log_bucket_name](#input_log_bucket_name) | A bucket to send the Cloudfront logs | `string` | n/a | yes | +| [resource-name-prefix](#input_resource-name-prefix) | The prefix to add to resources for easier identification | `string` | n/a | yes | +| [route_53_validation_record_fqdns](#input_route_53_validation_record_fqdns) | The fqdns of the route53 validation records for the load balancer certificate | `list(string)` | `[]` | no | +| [tags](#input_tags) | A common map of tags for all VPC resources that are created (for e.g. billing purposes) | `map(string)` | n/a | yes | +| [ui_version](#input_ui_version) | Version number for the built ui static files (e.g. v5.0) | `string` | n/a | yes | +| [us_east_certificate_validation_arn](#input_us_east_certificate_validation_arn) | Arn of the certificate used by Cloudfront. Please note this has to live in us-east-1. | `string` | n/a | yes | ## Outputs -| Name | Description | -|------|-------------| -| [bucket\_public\_arn](#output\_bucket\_public\_arn) | The arn of the public S3 bucket | -| [bucket\_website\_domain](#output\_bucket\_website\_domain) | The domain of the website endpoint | -| [tags](#output\_tags) | The tags used in the project | +| Name | Description | +| -------------------------------------------------------------------------------------------------- | ---------------------------------- | +| [bucket_public_arn](#output_bucket_public_arn) | The arn of the public S3 bucket | +| [bucket_website_domain](#output_bucket_website_domain) | The domain of the website endpoint | +| [tags](#output_tags) | The tags used in the project | + diff --git a/infrastructure/modules/ui/scripts/ui.sh.tpl b/infrastructure/modules/ui/scripts/ui.sh.tpl index 7aeb118..d9e9568 100644 --- a/infrastructure/modules/ui/scripts/ui.sh.tpl +++ b/infrastructure/modules/ui/scripts/ui.sh.tpl @@ -13,4 +13,4 @@ aws s3 cp . s3://${BUCKET_ID} --recursive cd .. -rm -rf ./out \ No newline at end of file +rm -rf ./out diff --git a/mkdocs.yml b/mkdocs.yml index f80c240..c1b7129 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -3,9 +3,9 @@ site_name: rAPId theme: name: 'material' palette: - scheme: default - primary: pink - accent: pink + scheme: default + primary: pink + accent: pink logo: 'favicon.ico' favicon: 'favicon.ico' @@ -16,35 +16,35 @@ nav: - Welcome to rAPId: index.md - Getting Started: getting_started.md - API: - - api/usage.md - - api/schema.md - - api/data_access.md - - Routes: - - api/routes/schema.md - - api/routes/dataset.md - - api/routes/protected_domain.md - - api/routes/user.md - - api/routes/client.md - - api/routes/permissions.md - - api/routes/subject.md + - api/usage.md + - api/schema.md + - api/data_access.md + - Routes: + - api/routes/schema.md + - api/routes/dataset.md + - api/routes/protected_domain.md + - api/routes/user.md + - api/routes/client.md + - api/routes/permissions.md + - api/routes/subject.md - Infrastructure: - - infrastructure/deployment.md - - infrastructure/alerting_monitoring.md - - infrastructure/certificates.md - - infrastructure/domains_subdomains.md + - infrastructure/deployment.md + - infrastructure/alerting_monitoring.md + - infrastructure/certificates.md + - infrastructure/domains_subdomains.md - UI: - - ui/getting_started.md + - ui/getting_started.md - SDK: - - sdk/usage.md - - sdk/useful_patterns.md - - API Documentation: - - sdk/api/rapid.md - - sdk/api/auth.md - - Items: - - sdk/api/items/query.md - - sdk/api/items/schema.md - - Patterns: - - sdk/api/patterns/data.md + - sdk/usage.md + - sdk/useful_patterns.md + - API Documentation: + - sdk/api/rapid.md + - sdk/api/auth.md + - Items: + - sdk/api/items/query.md + - sdk/api/items/schema.md + - Patterns: + - sdk/api/patterns/data.md - Releases: releases.md - Contributing: contributing.md diff --git a/sdk/rapid/__init__.py b/sdk/rapid/__init__.py index bf9fce8..49c6003 100644 --- a/sdk/rapid/__init__.py +++ b/sdk/rapid/__init__.py @@ -1,2 +1,2 @@ -from rapid.auth import RapidAuth -from rapid.rapid import Rapid +from rapid.auth import RapidAuth # noqa: F401 +from rapid.rapid import Rapid # noqa: F401 diff --git a/ui/.storybook/preview-head.html b/ui/.storybook/preview-head.html index 43d3135..e9c6953 100644 --- a/ui/.storybook/preview-head.html +++ b/ui/.storybook/preview-head.html @@ -1,4 +1,6 @@ - + diff --git a/ui/playwright/test-data-flow.spec.ts b/ui/playwright/test-data-flow.spec.ts index d0926e3..f1fc294 100644 --- a/ui/playwright/test-data-flow.spec.ts +++ b/ui/playwright/test-data-flow.spec.ts @@ -45,7 +45,7 @@ test('test', async ({ page }) => { await page.getByTestId('submit').click() expect(await page.getByText('Data uploaded successfully').textContent()).toEqual( - 'Status: Data uploaded successfully', + 'Status: Data uploaded successfully' ) // Download the dataset @@ -82,10 +82,10 @@ test('test', async ({ page }) => { await page.getByTestId('submit').click() const datasetDeletedElement = await page.waitForSelector('.MuiAlertTitle-root', { - text: `Dataset deleted: default/ui_test_domain/${datasetName}`, + text: `Dataset deleted: default/ui_test_domain/${datasetName}` }) expect(await datasetDeletedElement.innerText()).toEqual( - `Dataset deleted: default/ui_test_domain/${datasetName}`, + `Dataset deleted: default/ui_test_domain/${datasetName}` ) }) diff --git a/ui/playwright/utils.ts b/ui/playwright/utils.ts index ef80c45..c421187 100644 --- a/ui/playwright/utils.ts +++ b/ui/playwright/utils.ts @@ -10,16 +10,16 @@ export async function makeAPIRequest( method: string, body?: any, authToken?: string, - optionalHeaders = {}, + optionalHeaders = {} ): Promise { const response = await fetch(`https://${baseDomain}/${path}`, { method, headers: { 'Content-Type': 'application/json', ...optionalHeaders, - ...(authToken ? { Authorization: authToken } : {}), + ...(authToken ? { Authorization: authToken } : {}) }, - body: JSON.stringify(body), + body: JSON.stringify(body) }) return response.json() } @@ -48,11 +48,11 @@ export async function generateRapidAuthToken(): Promise { 'POST', { grant_type: 'client_credentials', - client_id: clientId, + client_id: clientId }, `Basic ${credentialsSecret}`, { - 'Content-Type': 'application/x-www-form-urlencoded', - }, + 'Content-Type': 'application/x-www-form-urlencoded' + } ) } diff --git a/ui/src/__tests__/data/delete.test.tsx b/ui/src/__tests__/data/delete.test.tsx index ba9babb..16e59e0 100644 --- a/ui/src/__tests__/data/delete.test.tsx +++ b/ui/src/__tests__/data/delete.test.tsx @@ -1,12 +1,13 @@ -import { - screen, - waitFor, - waitForElementToBeRemoved, -} from '@testing-library/react' +import { screen, waitFor, waitForElementToBeRemoved } from '@testing-library/react' import userEvent from '@testing-library/user-event' import fetchMock from 'jest-fetch-mock' import DeletePage from '@/pages/data/delete' -import { mockDataset, mockDataSetsList, renderWithProviders, selectAutocompleteOption } from '@/utils/testing' +import { + mockDataset, + mockDataSetsList, + renderWithProviders, + selectAutocompleteOption +} from '@/utils/testing' import { DeleteDatasetResponse } from '@/service/types' describe('Page: Delete page', () => { @@ -25,8 +26,7 @@ describe('Page: Delete page', () => { expect(datasetDropdown).toBeVisible() expect(screen.getByTestId('submit')).toBeInTheDocument() - } - ) + }) it('error on fetch', async () => { fetchMock.mockReject(new Error('fake error message')) diff --git a/ui/src/__tests__/data/download.test.tsx b/ui/src/__tests__/data/download.test.tsx index 1163b22..e3cde78 100644 --- a/ui/src/__tests__/data/download.test.tsx +++ b/ui/src/__tests__/data/download.test.tsx @@ -1,8 +1,4 @@ -import { - screen, - waitFor, - waitForElementToBeRemoved, -} from '@testing-library/react' +import { screen, waitFor, waitForElementToBeRemoved } from '@testing-library/react' import userEvent from '@testing-library/user-event' import fetchMock from 'jest-fetch-mock' import { mockDataset, mockDataSetsList, renderWithProviders } from '@/utils/testing' @@ -32,8 +28,7 @@ describe('Page: Download page', () => { expect(datasetDropdown).toBeVisible() expect(screen.getByTestId('submit')).toBeInTheDocument() - } - ) + }) it('renders dataset-selector', async () => { fetchMock.mockResponseOnce(JSON.stringify(mockDataSetsList), { status: 200 }) diff --git a/ui/src/__tests__/data/upload.test.tsx b/ui/src/__tests__/data/upload.test.tsx index fc83e0b..92795a8 100644 --- a/ui/src/__tests__/data/upload.test.tsx +++ b/ui/src/__tests__/data/upload.test.tsx @@ -2,15 +2,19 @@ import { fireEvent, screen, waitFor, - waitForElementToBeRemoved, + waitForElementToBeRemoved } from '@testing-library/react' import userEvent from '@testing-library/user-event' import fetchMock from 'jest-fetch-mock' -import { mockDataset, mockDataSetsList, renderWithProviders, selectAutocompleteOption } from '@/utils/testing' +import { + mockDataset, + mockDataSetsList, + renderWithProviders, + selectAutocompleteOption +} from '@/utils/testing' import UploadPage from '@/pages/data/upload' import { UploadDatasetResponse } from '@/service/types' - const pushSpy = jest.fn() jest.mock('next/router', () => ({ ...jest.requireActual('next/router'), @@ -27,7 +31,6 @@ describe('Page: Upload page', () => { }) it('renders', async () => { - fetchMock.mockResponseOnce(JSON.stringify(mockDataSetsList), { status: 200 }) renderWithProviders() @@ -59,7 +62,6 @@ describe('Page: Upload page', () => { await waitForElementToBeRemoved(() => screen.queryByRole('progressbar')) - selectAutocompleteOption('select-layer', 'layer') selectAutocompleteOption('select-domain', 'Pizza') selectAutocompleteOption('select-dataset', 'bit_complicated') @@ -96,7 +98,7 @@ describe('Page: Upload page', () => { fetchMock.mockResponses( [JSON.stringify(mockDataSetsList), { status: 200 }], [JSON.stringify(mockSuccess), { status: 200 }], - [JSON.stringify({ status: "FAILED" }), { status: 200 }] + [JSON.stringify({ status: 'FAILED' }), { status: 200 }] ) renderWithProviders() await waitForElementToBeRemoved(() => screen.queryByRole('progressbar')) @@ -131,7 +133,7 @@ describe('Page: Upload page', () => { fetchMock.mockResponses( [JSON.stringify(mockDataSetsList), { status: 200 }], [JSON.stringify(mockSuccess), { status: 200 }], - [JSON.stringify({ status: "SUCCESS" }), { status: 200 }] + [JSON.stringify({ status: 'SUCCESS' }), { status: 200 }] ) renderWithProviders() await waitForElementToBeRemoved(() => screen.queryByRole('progressbar')) @@ -166,7 +168,7 @@ describe('Page: Upload page', () => { fetchMock.mockResponses( [JSON.stringify(mockDataSetsList), { status: 200 }], [JSON.stringify(mockSuccess), { status: 200 }], - [JSON.stringify({ status: "IN PROGRESS" }), { status: 200 }] + [JSON.stringify({ status: 'IN PROGRESS' }), { status: 200 }] ) renderWithProviders() await waitForElementToBeRemoved(() => screen.queryByRole('progressbar')) diff --git a/ui/src/__tests__/schema/create.test.tsx b/ui/src/__tests__/schema/create.test.tsx index c6975c7..9b28837 100644 --- a/ui/src/__tests__/schema/create.test.tsx +++ b/ui/src/__tests__/schema/create.test.tsx @@ -1,4 +1,9 @@ -import { fireEvent, screen, waitFor, waitForElementToBeRemoved } from '@testing-library/react' +import { + fireEvent, + screen, + waitFor, + waitForElementToBeRemoved +} from '@testing-library/react' import userEvent from '@testing-library/user-event' import fetchMock from 'jest-fetch-mock' import { renderWithProviders } from '@/utils/testing' @@ -58,7 +63,6 @@ describe('Page: Upload page', () => { }) describe('on submit', () => { - const file = new File(['test'], 'testfile.txt', { type: 'text/plain' }) const formData = new FormData() formData.append('file', file) diff --git a/ui/src/__tests__/subject/create.test.tsx b/ui/src/__tests__/subject/create.test.tsx index 7957b42..cce85e4 100644 --- a/ui/src/__tests__/subject/create.test.tsx +++ b/ui/src/__tests__/subject/create.test.tsx @@ -4,7 +4,6 @@ import fetchMock from 'jest-fetch-mock' import { renderWithProviders, mockPermissionUiResponse } from '@/utils/testing' import SubjectCreatePage from '@/pages/subject/create/index' - const pushSpy = jest.fn() jest.mock('next/router', () => ({ ...jest.requireActual('next/router'), @@ -43,9 +42,7 @@ describe('Page: Subject Create', () => { }) describe('on submit', () => { - it('client success', async () => { - const mockData = { client_name: 'James Bond', client_secret: 'secret-code-word', // pragma: allowlist secret @@ -53,7 +50,9 @@ describe('Page: Subject Create', () => { permissions: ['DATA_ADMIN', 'READ_PRIVATE'] } - fetchMock.mockResponseOnce(JSON.stringify(mockPermissionUiResponse), { status: 200 }) + fetchMock.mockResponseOnce(JSON.stringify(mockPermissionUiResponse), { + status: 200 + }) renderWithProviders() await waitForElementToBeRemoved(() => screen.queryByRole('progressbar')) @@ -96,7 +95,9 @@ describe('Page: Subject Create', () => { email: 'test@example.com' } - fetchMock.mockResponseOnce(JSON.stringify(mockPermissionUiResponse), { status: 200 }) + fetchMock.mockResponseOnce(JSON.stringify(mockPermissionUiResponse), { + status: 200 + }) renderWithProviders() await waitForElementToBeRemoved(() => screen.queryByRole('progressbar')) @@ -108,7 +109,7 @@ describe('Page: Subject Create', () => { userEvent.selectOptions(screen.getByTestId('select-layer'), 'ALL') userEvent.selectOptions(screen.getByTestId('select-sensitivity'), 'ALL') await userEvent.click(screen.getByTestId('AddIcon')) - await new Promise((r) => setTimeout(r, 2000)); + await new Promise((r) => setTimeout(r, 2000)) await userEvent.click(screen.getByTestId('submit')) fetchMock.mockResponseOnce(JSON.stringify(mockData), { status: 200 }) @@ -135,7 +136,9 @@ describe('Page: Subject Create', () => { it('server error', async () => { const error = 'server error message' - fetchMock.mockResponseOnce(JSON.stringify(mockPermissionUiResponse), { status: 200 }) + fetchMock.mockResponseOnce(JSON.stringify(mockPermissionUiResponse), { + status: 200 + }) renderWithProviders() await waitForElementToBeRemoved(() => screen.queryByRole('progressbar')) diff --git a/ui/src/components/Autocomplete/Autocomplete.tsx b/ui/src/components/Autocomplete/Autocomplete.tsx index 1c40523..87d8807 100644 --- a/ui/src/components/Autocomplete/Autocomplete.tsx +++ b/ui/src/components/Autocomplete/Autocomplete.tsx @@ -1,29 +1,27 @@ import { ComponentProps } from 'react' -import { - Autocomplete as BaseAutocomplete, -} from '@mui/material' +import { Autocomplete as BaseAutocomplete } from '@mui/material' -import { styled } from '@mui/system'; - - -export const Autocomplete = styled(BaseAutocomplete) >` - .MuiInputBase-input { - padding: 4px 15px 0px 15px; - height: 100%; - width: 100%; - font-size: 13px; - font-weight: 400 - } - ` +import { styled } from '@mui/system' +export const Autocomplete = styled(BaseAutocomplete)< + ComponentProps +>` + .MuiInputBase-input { + padding: 4px 15px 0px 15px; + height: 100%; + width: 100%; + font-size: 13px; + font-weight: 400; + } +` export const GroupHeader = styled('div')(() => ({ - position: 'sticky', - top: '-8px', - padding: '4px 10px', - backgroundColor: 'lightgrey' -})); + position: 'sticky', + top: '-8px', + padding: '4px 10px', + backgroundColor: 'lightgrey' +})) export const GroupItems = styled('ul')({ - padding: 0, -}); + padding: 0 +}) diff --git a/ui/src/components/DatasetSelector/DatasetSelector.tsx b/ui/src/components/DatasetSelector/DatasetSelector.tsx index 23233e4..26d44d4 100644 --- a/ui/src/components/DatasetSelector/DatasetSelector.tsx +++ b/ui/src/components/DatasetSelector/DatasetSelector.tsx @@ -1,17 +1,20 @@ - import { Row } from '@/components' import { TextField, Typography } from '@mui/material' import { useEffect, useState } from 'react' import { Autocomplete, GroupHeader, GroupItems } from '../Autocomplete/Autocomplete' import FormControl from '../FormControl/FormControl' -import { Dataset } from "@/service/types" - - -const DatasetSelector = ({ datasetsList, setParentDataset, enableVersionSelector = true }) => { +import { Dataset } from '@/service/types' +const DatasetSelector = ({ + datasetsList, + setParentDataset, + enableVersionSelector = true +}) => { const [maxVersion, setMaxVersion] = useState(0) const [filteredDatasetsList, setFilteredDatasetsList] = useState([]) - const [layerFilteredDatasetsList, setLayerFilteredDatasetsList] = useState([]) + const [layerFilteredDatasetsList, setLayerFilteredDatasetsList] = useState( + [] + ) const [layer, setLayer] = useState('') const [domain, setDomain] = useState('') const [dataset, setDataset] = useState(null) @@ -19,16 +22,16 @@ const DatasetSelector = ({ datasetsList, setParentDataset, enableVersionSelector useEffect(() => { if (datasetsList) { - let filteredList = datasetsList; + let filteredList = datasetsList if (layer) { - filteredList = filteredList.filter((dataset) => dataset.layer === layer); + filteredList = filteredList.filter((dataset) => dataset.layer === layer) if (domain) { - filteredList = filteredList.filter((dataset) => dataset.domain === domain); + filteredList = filteredList.filter((dataset) => dataset.domain === domain) } } - setFilteredDatasetsList(filteredList); - setLayerFilteredDatasetsList(filteredList); + setFilteredDatasetsList(filteredList) + setLayerFilteredDatasetsList(filteredList) } // eslint-disable-next-line react-hooks/exhaustive-deps }, [layer, domain]) @@ -47,16 +50,19 @@ const DatasetSelector = ({ datasetsList, setParentDataset, enableVersionSelector const domain = splits[1] setLayer(layer) setDomain(domain) - } - else { + } else { setDomain(null) } setDataset(null) } const handleLayerSelect = (value) => { - if (value) { setLayer(value); setDomain(null) } - else { setLayer(null), setDataset(null), setDataset(null) } + if (value) { + setLayer(value) + setDomain(null) + } else { + setLayer(null), setDataset(null), setDataset(null) + } } useEffect(() => { @@ -65,8 +71,7 @@ const DatasetSelector = ({ datasetsList, setParentDataset, enableVersionSelector version = dataset.version setLayer(dataset.layer) setDomain(dataset.domain) - } - else { + } else { setLayer(null) setDomain(null) } @@ -77,7 +82,6 @@ const DatasetSelector = ({ datasetsList, setParentDataset, enableVersionSelector // eslint-disable-next-line react-hooks/exhaustive-deps }, [dataset]) - useEffect(() => { if (dataset) { dataset.version = version @@ -87,7 +91,11 @@ const DatasetSelector = ({ datasetsList, setParentDataset, enableVersionSelector }, [version]) const getUniqueLayers = () => [...new Set(datasetsList.map((dataset) => dataset.layer))] - const getUniqueDomains = () => [...new Set(layerFilteredDatasetsList.map((dataset) => `${dataset.layer}/${dataset.domain}`))] + const getUniqueDomains = () => [ + ...new Set( + layerFilteredDatasetsList.map((dataset) => `${dataset.layer}/${dataset.domain}`) + ) + ] return ( <> @@ -97,13 +105,13 @@ const DatasetSelector = ({ datasetsList, setParentDataset, enableVersionSelector (option as string) || ""} + getOptionLabel={(option) => (option as string) || ''} renderInput={(params) => } value={getUniqueLayers().length === 1 ? datasetsList[0].layer : layer || null} onChange={(_, newValue) => { - handleLayerSelect(newValue); + handleLayerSelect(newValue) }} - data-testid='select-layer' + data-testid="select-layer" /> Domain @@ -111,13 +119,13 @@ const DatasetSelector = ({ datasetsList, setParentDataset, enableVersionSelector (option as string).split('/')[1] || ""} + getOptionLabel={(option) => (option as string).split('/')[1] || ''} renderInput={(params) => } value={layer && domain ? `${layer}/${domain}` : null} onChange={(_, newValue) => { - handleDomainSelect(newValue); + handleDomainSelect(newValue) }} - data-testid='select-domain' + data-testid="select-domain" /> Dataset @@ -125,8 +133,10 @@ const DatasetSelector = ({ datasetsList, setParentDataset, enableVersionSelector `${(dataset as Dataset).layer}-${(dataset as Dataset).domain}`} - getOptionLabel={(dataset) => (dataset as unknown as Dataset).dataset || ""} + groupBy={(dataset) => + `${(dataset as Dataset).layer}-${(dataset as Dataset).domain}` + } + getOptionLabel={(dataset) => (dataset as unknown as Dataset).dataset || ''} renderInput={(params) => } renderGroup={(params) => (
  • @@ -137,23 +147,25 @@ const DatasetSelector = ({ datasetsList, setParentDataset, enableVersionSelector defaultValue={undefined} value={dataset} onChange={(_, newValue) => { - setDataset(newValue as unknown as Dataset); + setDataset(newValue as unknown as Dataset) }} - data-testid='select-dataset' + data-testid="select-dataset" /> - {(enableVersionSelector && maxVersion != 0) && ( + {enableVersionSelector && maxVersion != 0 && ( Select version i + 1)} + options={Array(maxVersion) + .fill(0) + .map((_, i) => i + 1)} renderInput={(params) => } onChange={(_, newValue) => { - setVersion(newValue as unknown as number); + setVersion(newValue as unknown as number) }} value={version} - data-testid='select-version' + data-testid="select-version" /> )} @@ -162,5 +174,4 @@ const DatasetSelector = ({ datasetsList, setParentDataset, enableVersionSelector ) } - -export default DatasetSelector; +export default DatasetSelector diff --git a/ui/src/components/FormControl/FormControl.tsx b/ui/src/components/FormControl/FormControl.tsx index bb1f3b6..99a42b0 100644 --- a/ui/src/components/FormControl/FormControl.tsx +++ b/ui/src/components/FormControl/FormControl.tsx @@ -1,14 +1,13 @@ import { FormControl as BaseFormControl } from '@mui/material' import { ComponentProps } from 'react' -import { styled } from '@mui/system'; +import { styled } from '@mui/system' - -const FormControl = styled(BaseFormControl) >` - .MuiInputBase-root { - margin-bottom: 4px; - height: 32px !important; - padding: 0px; - } +const FormControl = styled(BaseFormControl)>` + .MuiInputBase-root { + margin-bottom: 4px; + height: 32px !important; + padding: 0px; + } ` -export default FormControl; \ No newline at end of file +export default FormControl diff --git a/ui/src/components/PermissionsTable/PermissionsTable.tsx b/ui/src/components/PermissionsTable/PermissionsTable.tsx index 3024151..bb6088c 100644 --- a/ui/src/components/PermissionsTable/PermissionsTable.tsx +++ b/ui/src/components/PermissionsTable/PermissionsTable.tsx @@ -25,7 +25,7 @@ type SensitivityType = z.infer const PermissionsTable = ({ permissionsListData, fieldArrayReturn, - isModifyPage = false, + isModifyPage = false }: { permissionsListData: PermissionUiResponse fieldArrayReturn: FieldValues @@ -36,7 +36,7 @@ const PermissionsTable = ({ const removePermissionAsAnOption = ( permission: PermissionType, - permissionsList: PermissionUiResponse, + permissionsList: PermissionUiResponse ) => { const { type, layer, sensitivity, domain } = permission const typeList = permissionsList[type] @@ -90,7 +90,7 @@ const PermissionsTable = ({ const { fields, append, remove } = fieldArrayReturn const { control, trigger, watch, reset, setError, setValue } = useForm({ - resolver: zodResolver(Permission), + resolver: zodResolver(Permission) }) // Remove any of the selected permissions from being an option @@ -190,7 +190,7 @@ const PermissionsTable = ({ type: undefined, layer: undefined, sensitivity: undefined, - domain: undefined, + domain: undefined }) } } @@ -211,7 +211,7 @@ const PermissionsTable = ({ helperText={error?.message} native inputProps={{ - 'data-testid': 'select-type', + 'data-testid': 'select-type' }} // Reset all other values when this is changed onChange={(event) => { @@ -240,14 +240,14 @@ const PermissionsTable = ({ helperText={error?.message} native inputProps={{ - 'data-testid': 'select-layer', + 'data-testid': 'select-layer' }} > {generateOptions( - Object.keys(filteredPermissionsListData[watch('type')]), + Object.keys(filteredPermissionsListData[watch('type')]) )} ) @@ -270,7 +270,7 @@ const PermissionsTable = ({ helperText={error?.message} native inputProps={{ - 'data-testid': 'select-sensitivity', + 'data-testid': 'select-sensitivity' }} // Reset domain if this is changed onChange={(event) => { @@ -281,8 +281,8 @@ const PermissionsTable = ({ {generateOptions( Object.keys( - filteredPermissionsListData[watch('type')][watch('layer')], - ), + filteredPermissionsListData[watch('type')][watch('layer')] + ) )} ) @@ -305,7 +305,7 @@ const PermissionsTable = ({ helperText={error?.message} native inputProps={{ - 'data-testid': 'domain', + 'data-testid': 'domain' }} > @@ -314,8 +314,8 @@ const PermissionsTable = ({ Object.keys( filteredPermissionsListData[watch('type')][watch('layer')][ watch('sensitivity') - ], - ), + ] + ) )} ) diff --git a/ui/src/components/SchemaCreate.tsx b/ui/src/components/SchemaCreate.tsx index 378da37..df6b1bc 100644 --- a/ui/src/components/SchemaCreate.tsx +++ b/ui/src/components/SchemaCreate.tsx @@ -1,4 +1,9 @@ -import { createSchema, schemaCreateSchema, GlobalSensitivities, ProtectedSensitivity } from '@/service' +import { + createSchema, + schemaCreateSchema, + GlobalSensitivities, + ProtectedSensitivity +} from '@/service' import { CreateSchemaResponse, GenerateSchemaResponse, @@ -18,25 +23,29 @@ import Select from './Select/Select' import SimpleTable from './SimpleTable/SimpleTable' import TextField from './TextField/TextField' - const dataTypes = [ - "bigint", - "boolean", - "char", - "date", - "decimal", - "double", - "float", - "int", - "smallint", - "string", - "timestamp", - "tinyint", - "varchar" + 'bigint', + 'boolean', + 'char', + 'date', + 'decimal', + 'double', + 'float', + 'int', + 'smallint', + 'string', + 'timestamp', + 'tinyint', + 'varchar' ] - -function CreateSchema({ schemaData, layersData }: { schemaData: GenerateSchemaResponse, layersData: string[] }) { +function CreateSchema({ + schemaData, + layersData +}: { + schemaData: GenerateSchemaResponse + layersData: string[] +}) { const [newSchemaData, setNewSchemaData] = useState(schemaData) const [keyValueTag, setKeyValueTag] = useState({ key: '', value: '' }) const [valueTag, setValueTag] = useState('') @@ -134,9 +143,7 @@ function CreateSchema({ schemaData, layersData }: { schemaData: GenerateSchemaRe ( <> Dataset Layer diff --git a/ui/src/components/Select/Select.tsx b/ui/src/components/Select/Select.tsx index 7baf3bb..5ff0d3d 100644 --- a/ui/src/components/Select/Select.tsx +++ b/ui/src/components/Select/Select.tsx @@ -10,8 +10,7 @@ import SelectCheckbox from './SelectCheckbox' import FormControl from '../FormControl/FormControl' import { Props } from './types' - -const StyledBasicSelect = styled(BasicSelect) >` +const StyledBasicSelect = styled(BasicSelect)>` .MuiInputBase-input { padding: 4px 15px 0px 15px; height: 100%; diff --git a/ui/src/components/UploadProgress/UploadProgress.tsx b/ui/src/components/UploadProgress/UploadProgress.tsx index 5f69cee..451df29 100644 --- a/ui/src/components/UploadProgress/UploadProgress.tsx +++ b/ui/src/components/UploadProgress/UploadProgress.tsx @@ -6,73 +6,77 @@ import { useState, Dispatch, SetStateAction } from 'react' import Row from '../Row' enum UploadStatus { - Failed = "FAILED", - Success = "SUCCESS", - InProgress = "IN PROGRESS", + Failed = 'FAILED', + Success = 'SUCCESS', + InProgress = 'IN PROGRESS' } const statusConverter = { - [UploadStatus.Failed]: { - severity: "error", - message: "Data upload error", - link: "See error details" - }, - [UploadStatus.Success]: { - severity: "success", - message: "Data uploaded successfully", - link: "See upload details" - }, - [UploadStatus.InProgress]: { - severity: "info", - message: "Data processing", - link: "See progress details" - }, + [UploadStatus.Failed]: { + severity: 'error', + message: 'Data upload error', + link: 'See error details' + }, + [UploadStatus.Success]: { + severity: 'success', + message: 'Data uploaded successfully', + link: 'See upload details' + }, + [UploadStatus.InProgress]: { + severity: 'info', + message: 'Data processing', + link: 'See progress details' + } } +const UploadProgress = ({ + uploadSuccessDetails, + setDisableUpload +}: { + uploadSuccessDetails: UploadDatasetResponseDetails + setDisableUpload: Dispatch> +}) => { + const [stop, setStop] = useState(false) + const [status, setStatus] = useState(UploadStatus.InProgress) -const UploadProgress = ({ uploadSuccessDetails, setDisableUpload }: { uploadSuccessDetails: UploadDatasetResponseDetails, setDisableUpload: Dispatch> }) => { - - const [stop, setStop] = useState(false); - const [status, setStatus] = useState(UploadStatus.InProgress); - - useQuery(['getJob', uploadSuccessDetails.job_id], getJob, { - onSuccess: data => { - switch (data.status) { - case UploadStatus.Success: - case UploadStatus.Failed: - setStop(true); - setStatus(data.status) - setDisableUpload(false) - break - default: - break; - } - }, - // Keep refetching every second - refetchInterval: stop ? false : 1000, - refetchIntervalInBackground: true, - refetchOnWindowFocus: false, - }); + useQuery(['getJob', uploadSuccessDetails.job_id], getJob, { + onSuccess: (data) => { + switch (data.status) { + case UploadStatus.Success: + case UploadStatus.Failed: + setStop(true) + setStatus(data.status) + setDisableUpload(false) + break + default: + break + } + }, + // Keep refetching every second + refetchInterval: stop ? false : 1000, + refetchIntervalInBackground: true, + refetchOnWindowFocus: false + }) - return ( - - Status: {statusConverter[status].message} - {!stop && -
    - -
    - } - - - {statusConverter[status].link} - - -
    - ) + return ( + + Status: {statusConverter[status].message} + {!stop && ( +
    + +
    + )} + + + {statusConverter[status].link} + + +
    + ) } -export default UploadProgress; \ No newline at end of file +export default UploadProgress diff --git a/ui/src/pages/data/delete/index.tsx b/ui/src/pages/data/delete/index.tsx index 75f6174..85fae15 100644 --- a/ui/src/pages/data/delete/index.tsx +++ b/ui/src/pages/data/delete/index.tsx @@ -61,7 +61,11 @@ function DeleteDataset({ datasetInput = null }: { datasetInput?: Dataset }) { dataset and the underlying crawlers and raw data. - + {deleteDatasetSuccessDetails ? ( (datasetInput) @@ -45,22 +43,29 @@ function DownloadData({ datasetInput = null }: { datasetInput?: Dataset }) { return ( - router.push(`/data/download/${dataset.layer}/${dataset.domain}/${dataset.dataset}?version=${dataset.version}`) - } - > - Next - } + action={ + + } > Download the contents of a datasource from rAPId. Select the relevant dataset you want to download and then the version to download from. Please note it might take some time to for the API to query the dataset especially if they are large. - + ) } diff --git a/ui/src/pages/data/upload/index.tsx b/ui/src/pages/data/upload/index.tsx index 4e31ea2..2f460ad 100644 --- a/ui/src/pages/data/upload/index.tsx +++ b/ui/src/pages/data/upload/index.tsx @@ -4,12 +4,15 @@ import AccountLayout from '@/components/Layout/AccountLayout' import UploadProgress from '@/components/UploadProgress/UploadProgress' import DatasetSelector from '@/components/DatasetSelector/DatasetSelector' import { getDatasetsUi, uploadDataset } from '@/service' -import { Dataset, UploadDatasetResponse, UploadDatasetResponseDetails } from '@/service/types' +import { + Dataset, + UploadDatasetResponse, + UploadDatasetResponseDetails +} from '@/service/types' import { Typography, LinearProgress } from '@mui/material' import { useMutation, useQuery } from '@tanstack/react-query' import { useState } from 'react' - function UploadDataset({ datasetInput = null }: { datasetInput?: Dataset }) { const [file, setFile] = useState() const [dataset, setDataset] = useState(datasetInput) @@ -53,14 +56,24 @@ function UploadDataset({ datasetInput = null }: { datasetInput?: Dataset }) { event.preventDefault() const formData = new FormData() formData.append('file', file) - await mutate({ path: `${dataset.layer}/${dataset.domain}/${dataset.dataset}?version=${dataset.version}`, data: formData }) + await mutate({ + path: `${dataset.layer}/${dataset.domain}/${dataset.dataset}?version=${dataset.version}`, + data: formData + }) }} > - Upload dataset - + action={ + !disable && ( + + ) } > @@ -68,10 +81,13 @@ function UploadDataset({ datasetInput = null }: { datasetInput?: Dataset }) { been uploaded for the data source and the data to upload matches this schema. - + - {!disable && + {!disable && ( setFile(event.target.files[0])} // This key changing resets the file so that after an upload event it is removed key={`file-upload-${disable.toString()}`} - />} + /> + )} {uploadSuccessDetails ? ( - + ) : null} {error && ( @@ -93,7 +113,7 @@ function UploadDataset({ datasetInput = null }: { datasetInput?: Dataset }) { )} - + ) } diff --git a/ui/src/pages/schema/create/index.tsx b/ui/src/pages/schema/create/index.tsx index dc74e83..0b5bd45 100644 --- a/ui/src/pages/schema/create/index.tsx +++ b/ui/src/pages/schema/create/index.tsx @@ -9,7 +9,12 @@ import { CreateSchema as CreateSchemaComponent } from '@/components' import ErrorCard from '@/components/ErrorCard/ErrorCard' -import { generateSchema, schemaGenerateSchema, GlobalSensitivities, ProtectedSensitivity } from '@/service' +import { + generateSchema, + schemaGenerateSchema, + GlobalSensitivities, + ProtectedSensitivity +} from '@/service' import { getLayers } from '@/service/fetch' import { GenerateSchemaResponse, SchemaGenerate } from '@/service/types' import { zodResolver } from '@hookform/resolvers/zod' @@ -22,10 +27,11 @@ import { useQuery } from '@tanstack/react-query' function CreateSchema() { const [file, setFile] = useState() - const { isLoading: isLayersLoading, data: layersData, error: layersError } = useQuery( - ['layers'], - getLayers, - ) + const { + isLoading: isLayersLoading, + data: layersData, + error: layersError + } = useQuery(['layers'], getLayers) const { control, handleSubmit } = useForm({ resolver: zodResolver(schemaGenerateSchema) @@ -52,7 +58,6 @@ function CreateSchema() { return } - return (
    { @@ -103,7 +108,7 @@ function CreateSchema() { ( <> Dataset Layer diff --git a/ui/src/pages/subject/create/index.tsx b/ui/src/pages/subject/create/index.tsx index 56df960..77d8b41 100644 --- a/ui/src/pages/subject/create/index.tsx +++ b/ui/src/pages/subject/create/index.tsx @@ -18,7 +18,6 @@ import { import ErrorCard from '@/components/ErrorCard/ErrorCard' import PermissionsTable from '@/components/PermissionsTable/PermissionsTable' - const userType = ['User', 'Client'] type UserCreate = z.infer @@ -39,7 +38,7 @@ function CreateUserPage() { const fieldArrayReturn = useFieldArray({ control, name: 'permissions' - }); + }) const { isLoading, mutate, error } = useMutation< ClientCreateResponse | UserCreateResponse, @@ -80,7 +79,9 @@ function CreateUserPage() { return ( { - const permissions = data.permissions.map((permission) => extractPermissionNames(permission, permissionsListData)) + const permissions = data.permissions.map((permission) => + extractPermissionNames(permission, permissionsListData) + ) if (data.type === 'User') { await mutate({ path: 'user', @@ -214,7 +215,10 @@ function CreateUserPage() { Select Permissions - + {error && ( diff --git a/ui/src/pages/subject/modify/[subjectId].tsx b/ui/src/pages/subject/modify/[subjectId].tsx index 5d64aef..5e1939d 100644 --- a/ui/src/pages/subject/modify/[subjectId].tsx +++ b/ui/src/pages/subject/modify/[subjectId].tsx @@ -4,12 +4,12 @@ import AccountLayout from '@/components/Layout/AccountLayout' import { getPermissionsListUi, getSubjectPermissions, - updateSubjectPermissions, + updateSubjectPermissions } from '@/service' import { extractPermissionNames } from '@/service/permissions' import { UpdateSubjectPermissionsBody, - UpdateSubjectPermissionsResponse, + UpdateSubjectPermissionsResponse } from '@/service/types' import { Alert, Typography, LinearProgress } from '@mui/material' import { useMutation, useQuery } from '@tanstack/react-query' @@ -26,7 +26,7 @@ function SubjectModifyPage() { const fieldArrayReturn = useFieldArray({ control, - name: 'permissions', + name: 'permissions' }) const { append } = fieldArrayReturn @@ -34,13 +34,13 @@ function SubjectModifyPage() { const { isLoading: isPermissionsListDataLoading, data: permissionsListData, - error: permissionsListDataError, + error: permissionsListDataError } = useQuery(['permissionsList'], getPermissionsListUi) const { isLoading: isSubjectPermissionsLoading, data: subjectPermissionsData, - error: subjectPermissionsError, + error: subjectPermissionsError } = useQuery(['subjectPermissions', subjectId], getSubjectPermissions) useEffect(() => { @@ -58,7 +58,7 @@ function SubjectModifyPage() { mutationFn: updateSubjectPermissions, onSuccess: () => { router.push({ pathname: `/subject/modify/success/${subjectId}`, query: { name } }) - }, + } }) if (isPermissionsListDataLoading || isSubjectPermissionsLoading) { @@ -77,7 +77,7 @@ function SubjectModifyPage() { { const permissions = data.permissions.map((permission) => - extractPermissionNames(permission, permissionsListData), + extractPermissionNames(permission, permissionsListData) ) await mutate({ subject_id: subjectId as string, permissions }) })} diff --git a/ui/src/service/fetch.ts b/ui/src/service/fetch.ts index 3828c40..c034064 100644 --- a/ui/src/service/fetch.ts +++ b/ui/src/service/fetch.ts @@ -61,9 +61,7 @@ export const getSubjectsListUi = async (): Promise< return res.json() } -export const getDatasetsUi = async ({ - queryKey -}): Promise => { +export const getDatasetsUi = async ({ queryKey }): Promise => { const [, action] = queryKey const res = await api(`/api/datasets_ui/${action}`, { method: 'GET' @@ -86,7 +84,9 @@ export const getJob = async ({ queryKey }): Promise => { return res.json() } -export const getSubjectPermissions = async ({ queryKey }): Promise => { +export const getSubjectPermissions = async ({ + queryKey +}): Promise => { const [, subjectId] = queryKey const res = await api(`/api/permissions/${subjectId}`, { method: 'GET' @@ -147,9 +147,12 @@ export const deleteDataset = async ({ path }: { path: string }) => { export const getDatasetInfo = async ({ queryKey }): Promise => { const [, layer, domain, dataset, version] = queryKey - const res = await api(`/api/datasets/${layer}/${domain}/${dataset}/info?version=${version}`, { - method: 'GET' - }) + const res = await api( + `/api/datasets/${layer}/${domain}/${dataset}/info?version=${version}`, + { + method: 'GET' + } + ) return res.json() } diff --git a/ui/src/service/permissions.ts b/ui/src/service/permissions.ts index b5eda29..2c86e22 100644 --- a/ui/src/service/permissions.ts +++ b/ui/src/service/permissions.ts @@ -6,24 +6,30 @@ type DataPermissionType = z.infer type PermissionType = z.infer export const isDataPermission = (permission: PermissionType): boolean => { - return permission.type === "READ" || permission.type === "WRITE"; + return permission.type === 'READ' || permission.type === 'WRITE' } export const isAdminPermission = (permission: PermissionType): boolean => { - return permission.type === "DATA_ADMIN" || permission.type === "USER_ADMIN"; + return permission.type === 'DATA_ADMIN' || permission.type === 'USER_ADMIN' } -export const extractPermissionNames = (permission: PermissionType, permissionsListData: PermissionUiResponse) => { - switch (true) { - case isDataPermission(permission): - permission = permission as DataPermissionType - if (permission.domain != undefined) { - return permissionsListData[permission.type][permission.layer][permission.sensitivity][permission.domain] - } - else if (permission.sensitivity != undefined) { - return permissionsListData[permission.type][permission.layer][permission.sensitivity] - } - case isAdminPermission(permission): - return permissionsListData[permission.type] - } -} \ No newline at end of file +export const extractPermissionNames = ( + permission: PermissionType, + permissionsListData: PermissionUiResponse +) => { + switch (true) { + case isDataPermission(permission): + permission = permission as DataPermissionType + if (permission.domain != undefined) { + return permissionsListData[permission.type][permission.layer][ + permission.sensitivity + ][permission.domain] + } else if (permission.sensitivity != undefined) { + return permissionsListData[permission.type][permission.layer][ + permission.sensitivity + ] + } + case isAdminPermission(permission): + return permissionsListData[permission.type] + } +} diff --git a/ui/src/service/schema.ts b/ui/src/service/schema.ts index 4276563..a3a027d 100644 --- a/ui/src/service/schema.ts +++ b/ui/src/service/schema.ts @@ -1,15 +1,17 @@ import { z } from 'zod' - -export const GlobalSensitivities = ['PUBLIC', 'PRIVATE'] as const; +export const GlobalSensitivities = ['PUBLIC', 'PRIVATE'] as const export const ProtectedSensitivity = 'PROTECTED' - -export const SensitivityEnum = z.enum([...GlobalSensitivities, ProtectedSensitivity, 'ALL']) +export const SensitivityEnum = z.enum([ + ...GlobalSensitivities, + ProtectedSensitivity, + 'ALL' +]) const UserTypeEnum = z.enum(['User', 'Client']) -export const DataActionValues = ['READ', 'WRITE'] as const; -export const AdminActionValues = ['DATA_ADMIN', 'USER_ADMIN'] as const; +export const DataActionValues = ['READ', 'WRITE'] as const +export const AdminActionValues = ['DATA_ADMIN', 'USER_ADMIN'] as const const DataActionEnum = z.enum(DataActionValues) const AdminActionEnum = z.enum(AdminActionValues) @@ -20,7 +22,7 @@ export const DataPermission = z.object({ type: DataActionEnum, layer: z.string(), sensitivity: SensitivityEnum, - domain: z.string().optional(), + domain: z.string().optional() }) export const AdminPermission = z.object({ @@ -30,11 +32,15 @@ export const AdminPermission = z.object({ domain: z.literal(undefined) }) -export const Permission = z.discriminatedUnion("type", [DataPermission, AdminPermission], { - errorMap: () => { - return { message: 'Required' }; +export const Permission = z.discriminatedUnion( + 'type', + [DataPermission, AdminPermission], + { + errorMap: () => { + return { message: 'Required' } + } } -}) +) export const SubjectCreate = z.object({ type: UserTypeEnum, diff --git a/ui/src/service/types.ts b/ui/src/service/types.ts index 825f25c..4f48798 100644 --- a/ui/src/service/types.ts +++ b/ui/src/service/types.ts @@ -170,5 +170,7 @@ export type SubjectPermission = { } export type PermissionUiResponse = { - [key: string]: string | { [key: string]: { [key: string]: string | { [key: string]: string } } } -} \ No newline at end of file + [key: string]: + | string + | { [key: string]: { [key: string]: string | { [key: string]: string } } } +} diff --git a/ui/src/utils/data.ts b/ui/src/utils/data.ts index d7e44e4..c1028bc 100644 --- a/ui/src/utils/data.ts +++ b/ui/src/utils/data.ts @@ -20,6 +20,6 @@ export const api = async ( try { const { details } = await res.json() detailMessage = details - } catch (e) { } + } catch (e) {} throw new Error(detailMessage || defaultError) } diff --git a/ui/src/utils/testing.tsx b/ui/src/utils/testing.tsx index 3356466..b34ab06 100644 --- a/ui/src/utils/testing.tsx +++ b/ui/src/utils/testing.tsx @@ -1,4 +1,11 @@ -import { fireEvent, render, renderHook, RenderOptions, screen, waitFor } from '@testing-library/react' +import { + fireEvent, + render, + renderHook, + RenderOptions, + screen, + waitFor +} from '@testing-library/react' import { ThemeProvider } from '@/components' import { ReactNode } from 'react' import { QueryClient, QueryClientProvider } from '@tanstack/react-query' @@ -102,35 +109,34 @@ export const mockDataSetsList: Dataset[] = [ ] export const mockPermissionUiResponse: PermissionUiResponse = { - "DATA_ADMIN": "DATA_ADMIN", - "USER_ADMIN": "USER_ADMIN", - "READ": { - "ALL": { - "ALL": "READ_ALL", - "PROTECTED": { - "TEST": "READ_ALL_PROTECTED_TEST", - }, - }, + DATA_ADMIN: 'DATA_ADMIN', + USER_ADMIN: 'USER_ADMIN', + READ: { + ALL: { + ALL: 'READ_ALL', + PROTECTED: { + TEST: 'READ_ALL_PROTECTED_TEST' + } + } }, - "WRITE": { - "ALL": { - "ALL": "WRITE_ALL", - "PROTECTED": { - "TEST": "WRITE_ALL_PROTECTED_TEST", - }, - }, - "DEFAULT": { - "ALL": "WRITE_DEFAULT_ALL", - "PROTECTED": { - "TEST": "WRITE_DEFAULT_PROTECTED_TEST", - }, + WRITE: { + ALL: { + ALL: 'WRITE_ALL', + PROTECTED: { + TEST: 'WRITE_ALL_PROTECTED_TEST' + } }, + DEFAULT: { + ALL: 'WRITE_DEFAULT_ALL', + PROTECTED: { + TEST: 'WRITE_DEFAULT_PROTECTED_TEST' + } + } } } - export const selectAutocompleteOption = (id, value) => { - const autocomplete = screen.getByTestId(id); + const autocomplete = screen.getByTestId(id) const input = autocomplete.querySelector('input') autocomplete.focus() fireEvent.change(input, { target: { value: value } })