Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
119 changes: 119 additions & 0 deletions .github/workflows/pr.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
on: pull_request
name: PR Review
jobs:
test-composer-files:
name: Validate composer
runs-on: ubuntu-latest
strategy:
matrix:
php-versions: [ '7.4', '8.0', '8.1' ]
dependency-version: [ prefer-lowest, prefer-stable ]
steps:
- uses: actions/checkout@master
- name: Setup PHP, with composer and extensions
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-versions }}
extensions: json
coverage: none
tools: composer:v2
# https://github.com/shivammathur/setup-php#cache-composer-dependencies
- name: Get composer cache directory
id: composer-cache
run: echo "::set-output name=dir::$(composer config cache-files-dir)"
- name: Cache dependencies
uses: actions/cache@v2
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: ${{ runner.os }}-composer-
- name: Validate composer files
run: |
composer validate --strict composer.json
# Check that dependencies resolve.
composer update --${{ matrix.dependency-version }} --prefer-dist --no-interaction

php-check-coding-standards:
name: PHP - Check Coding Standards
runs-on: ubuntu-latest
strategy:
matrix:
php-versions: [ '7.4', '8.0', '8.1' ]
dependency-version: [ prefer-lowest, prefer-stable ]
steps:
- uses: actions/checkout@master
- name: Setup PHP, with composer and extensions
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-versions }}
extensions: json
coverage: none
tools: composer:v2
# https://github.com/shivammathur/setup-php#cache-composer-dependencies
- name: Get composer cache directory
id: composer-cache
run: echo "::set-output name=dir::$(composer config cache-files-dir)"
- name: Cache dependencies
uses: actions/cache@v2
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: ${{ runner.os }}-composer-
- name: Install Dependencies
run: |
composer install --no-interaction --no-progress
- name: PHPCS
run: |
composer coding-standards-check/phpcs

php-code-analysis:
name: PHP - Code analysis
runs-on: ubuntu-latest
strategy:
matrix:
php-versions: [ '7.4', '8.0', '8.1' ]
dependency-version: [ prefer-lowest, prefer-stable ]
steps:
- uses: actions/checkout@master
- name: Setup PHP, with composer and extensions
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-versions }}
extensions: json, gd
coverage: none
tools: composer:v2
# https://github.com/shivammathur/setup-php#cache-composer-dependencies
- name: Get composer cache directory
id: composer-cache
run: echo "::set-output name=dir::$(composer config cache-files-dir)"
- name: Cache dependencies
uses: actions/cache@v2
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: ${{ runner.os }}-composer-
- name: drupal-check
run: |
# We need a Drupal project to run drupal-check (cf. https://github.com/mglaman/drupal-check#usage)
# Install Drupal
composer --no-interaction create-project drupal/recommended-project:^9 --stability=dev drupal
# Copy our module source code into the Drupal module folder.
mkdir -p drupal/web/modules/contrib/os2forms_rest_api
cp -r os2forms_rest_api.* composer.json src drupal/web/modules/contrib/os2forms_rest_api
# Add our module as a composer repository.
composer --no-interaction --working-dir=drupal config repositories.os2forms/os2forms_rest_api path web/modules/contrib/os2forms_rest_api
# Restore Drupal composer repository.
composer --no-interaction --working-dir=drupal config repositories.drupal composer https://packages.drupal.org/8

# Require our module.
composer --no-interaction --working-dir=drupal require 'os2forms/os2forms_rest_api:*'

# Check code
composer --no-interaction --working-dir=drupal require --dev drupal/core-dev
cd drupal/web/modules/contrib/os2forms_rest_api
# Remove our non-dev dependencies to prevent duplicated Drupal installation
# PHP Fatal error: Cannot redeclare drupal_get_filename() (previously declared in /home/runner/work/os2forms_rest_api/os2forms_rest_api/drupal/web/modules/contrib/os2forms_rest_api/vendor/drupal/core/includes/bootstrap.inc:190) in /home/runner/work/os2forms_rest_api/os2forms_rest_api/drupal/web/core/includes/bootstrap.inc on line 190
# Use sed to remove the "require" property in composer.json
sed -i '/^\s*"require":/,/^\s*}/d' composer.json
composer --no-interaction install
composer code-analysis
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/vendor/
composer.lock
1 change: 1 addition & 0 deletions .php-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
7.4
144 changes: 144 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,146 @@
# OS2Forms REST API

We use [Webform REST](https://www.drupal.org/project/webform_rest) to expose a
number of API endpoints.

## Installation

```sh
composer require os2forms/os2forms_rest_api
vendor/bin/drush pm:enable os2forms_rest_api
```

## Authentication

We use [Key auth](https://www.drupal.org/project/key_auth) for authenticating
api users.

A user can access the Webforrm REST API if

1. it has the “OS2Form REST API user” (`os2forms_rest_api_user`) role and
2. has a generated key (User > Edit > Key authentication; `/user/«user
id»/key-auth`).

The “OS2Form REST API user” role gives read-only access to the API. To get read
access, a user must also have the “OS2Form REST API user (write)”
(`os2forms_rest_api_user_write`) role.

## Endpoints

| Name | Path | Methods |
|--------------------|------------------------------------------------|---------|
| Webform Elements | `/webform_rest/{webform_id}/elements` | GET |
| Webform Fields | `/webform_rest/{webform_id}/fields` | GET |
| Webform Submission | `/webform_rest/{webform_id}/submission/{uuid}` | GET |
| Webform Submit | `/webform_rest/submit` | POST |
| File | `/entity/file/{file_id}` | GET |

## Examples

### Get file content from webform submission

Example uses `some_webform_id` as webform id, `some_submission_id` as submission
id and `dokumenter` as the webform file element key.

Request:

```sh
> curl --silent --header 'api-key: …' https://127.0.0.1:8000/webform_rest/some_webform_id/submission/some_submission_uuid
```

Response:

```json
{
…,
"data": {
"navn": "Jack",
"telefon": "12345678"
"dokumenter": {
"some_document_id",
"some_other_docuent_id"
}
}
}
```

Use the file endpoint from above to get information on a file, substituting
`{file_id}` with the actual file id (`some_document_id`) from the previous
request.

Request:

```sh
> curl --silent --header 'api-key: …' https://127.0.0.1:8000/webform_rest/entity/file/some_document_id
```

Response:

```json
{
…,
"uri": [
{
"value": "private:…",
"url": "/system/files/webform/some_webform_id/…"
}
],
}
```

Finally, you can get the actual file by combining the base url
with the url from above response:

```sh
> curl --silent --header 'api-key: …' http://127.0.0.1:8000/system/files/webform/some_webform_id/…
```

Response:

The actual document content.

### Submit webform

Request:

```sh
> curl --silent --location --header 'api-key: …' --header 'content-type: application/json' https://127.0.0.1:8000/webform_rest/submit --data @- <<'JSON'
{
"webform_id": "{webform_id}",
"//": "Webform field values (cf. /webform_rest/{webform_id}/fields)",
"navn_": "Mikkel",
"adresse": "Livets landevej",
"mail_": "[email protected]",
"telefonnummer_": "12345678"
}
JSON
```

Response:

```json
{"sid":"6d95afe9-18d1-4a7d-a1bf-fd38c58c7733"}
```

(the `sid` value is a webform submission uuid).

## Custom access control

To limit access to webforms, you can specify a list of API users that are
allowed to access a webform's data via the API.

Go to Settings > General > Third party settings > OS2Forms > REST API to specify
which users can access a webform's data. **If no users are specified, all API
users can access the data.**

### Technical details

The custom access check is implemented in an event subscriber listening on the
`KernelEvents::REQUEST` event. See
[EventSubscriber::onRequest](src/EventSubscriber/EventSubscriber.php) for
details.

In order to make documents accessible for api users the Key auth
`authentication_provider` service has been overwritten to be global. See
[os2forms_rest_api.services](os2forms_rest_api.services.yml).
55 changes: 55 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
{
"name": "os2forms/os2forms_rest_api",
"description": "OS2Forms REST API",
"type": "drupal-module",
"license": "MIT",
"authors": [
{
"name": "Mikkel Ricky",
"email": "[email protected]"
}
],
"minimum-stability": "dev",
"prefer-stable": true,
"repositories": [
{
"type": "composer",
"url": "https://packages.drupal.org/8"
}
],
"require": {
"drupal/key_auth": "^2.0",
"drupal/webform_rest": "^4.0"
},
"require-dev": {
"dealerdirect/phpcodesniffer-composer-installer": "^0.7.2",
"drupal/coder": "^8.3",
"mglaman/drupal-check": "^1.4"
},
"scripts": {
"code-analysis/drupal-check": [
"vendor/bin/drupal-check --deprecations --analysis --exclude-dir=vendor *.* src"
],
"code-analysis": [
"@code-analysis/drupal-check"
],
"coding-standards-check/phpcs": [
"vendor/bin/phpcs --standard=phpcs.xml.dist"
],
"coding-standards-check": [
"@coding-standards-check/phpcs"
],
"coding-standards-apply/phpcs": [
"vendor/bin/phpcbf --standard=phpcs.xml.dist"
],
"coding-standards-apply": [
"@coding-standards-apply/phpcs"
]
},
"config": {
"sort-packages": true,
"allow-plugins": {
"dealerdirect/phpcodesniffer-composer-installer": true
}
}
}
20 changes: 20 additions & 0 deletions config/install/rest.resource.entity.file.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
langcode: en
status: true
dependencies:
module:
- file
- os2forms_rest_api
- serialization
enforced:
module:
- os2forms_rest_api
id: entity.file
plugin_id: 'entity:file'
granularity: resource
configuration:
methods:
- GET
formats:
- json
authentication:
- key_auth
21 changes: 21 additions & 0 deletions config/install/rest.resource.webform_rest_elements.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
langcode: da
status: true
dependencies:
module:
- key_auth
- os2forms_rest_api
- serialization
- webform_rest
enforced:
module:
- os2forms_rest_api
id: webform_rest_elements
plugin_id: webform_rest_elements
granularity: resource
configuration:
methods:
- GET
formats:
- json
authentication:
- key_auth
21 changes: 21 additions & 0 deletions config/install/rest.resource.webform_rest_fields.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
langcode: da
status: true
dependencies:
module:
- key_auth
- os2forms_rest_api
- serialization
- webform_rest
enforced:
module:
- os2forms_rest_api
id: webform_rest_fields
plugin_id: webform_rest_fields
granularity: resource
configuration:
methods:
- GET
formats:
- json
authentication:
- key_auth
Loading