feat: accept form submissions from the websites over an API endpoint
This commit is contained in:
1 parent
f48e53fdd0
commit
30ad5e8488
17 files changed
+1350
-4
No files matched your search
@@ -3,6 +3,7 @@ monolog:
|
||||
- deprecation
|
||||
- bpn
|
||||
- audit
|
||||
- api
|
||||
|
||||
handlers:
|
||||
main:
|
||||
@@ -11,7 +12,7 @@ monolog:
|
||||
handler: exceptions
|
||||
excluded_http_codes: [404, 405]
|
||||
buffer_size: 50
|
||||
channels: ["!bpn", "!audit"]
|
||||
channels: ["!bpn", "!audit", "!api"]
|
||||
exceptions:
|
||||
type: rotating_file
|
||||
path: "%kernel.logs_dir%/framework.%kernel.environment%.log"
|
||||
@@ -29,6 +30,14 @@ monolog:
|
||||
path: '%kernel.logs_dir%/audit.%kernel.environment%.log'
|
||||
max_files: 5
|
||||
level: info
|
||||
# Form submissions posted by the sibling websites. Own file because it is machine
|
||||
# traffic nobody watches between incidents, and it must stay out of the audit table.
|
||||
api:
|
||||
channels: [ "api" ]
|
||||
type: rotating_file
|
||||
path: '%kernel.logs_dir%/api.%kernel.environment%.log'
|
||||
max_files: 30
|
||||
level: info
|
||||
database:
|
||||
channels: ["audit"]
|
||||
type: service
|
||||
@@ -36,7 +45,7 @@ monolog:
|
||||
console:
|
||||
type: console
|
||||
process_psr_3_messages: false
|
||||
channels: ["!event", "!bpn", "!doctrine", "!console"]
|
||||
channels: ["!event", "!bpn", "!api", "!doctrine", "!console"]
|
||||
|
||||
when@dev:
|
||||
monolog:
|
||||
@@ -73,7 +82,7 @@ when@prod:
|
||||
handler: exceptions
|
||||
excluded_http_codes: [404, 405]
|
||||
buffer_size: 50
|
||||
channels: ["!bpn", "!audit"]
|
||||
channels: ["!bpn", "!audit", "!api"]
|
||||
exceptions:
|
||||
type: rotating_file
|
||||
path: "%kernel.logs_dir%/framework.%kernel.environment%.log"
|
||||
@@ -91,6 +100,12 @@ when@prod:
|
||||
path: '%kernel.logs_dir%/audit.%kernel.environment%.log'
|
||||
max_files: 5
|
||||
level: info
|
||||
api:
|
||||
channels: [ "api" ]
|
||||
type: rotating_file
|
||||
path: '%kernel.logs_dir%/api.%kernel.environment%.log'
|
||||
max_files: 30
|
||||
level: info
|
||||
database:
|
||||
channels: ["audit"]
|
||||
type: service
|
||||
@@ -98,4 +113,4 @@ when@prod:
|
||||
console:
|
||||
type: console
|
||||
process_psr_3_messages: false
|
||||
channels: ["!event", "!doctrine", "!bpn", "!audit"]
|
||||
channels: ["!event", "!doctrine", "!bpn", "!audit", "!api"]
|
||||
@@ -7,6 +7,12 @@ security:
|
||||
entity:
|
||||
class: App\Entity\User
|
||||
property: email
|
||||
# The sibling websites post as this one; it exists in configuration only. An API caller
|
||||
# must never be a row in the user table, where it would be a login to the UI as well.
|
||||
api_user_provider:
|
||||
memory:
|
||||
users:
|
||||
api: { roles: [ ROLE_API ] }
|
||||
|
||||
role_hierarchy:
|
||||
ROLE_TEAM_ADMIN: [ ROLE_ADMINISTRATIVE ]
|
||||
@@ -16,6 +22,17 @@ security:
|
||||
dev:
|
||||
pattern: ^/(_(profiler|wdt)|css|images|js)/
|
||||
security: false
|
||||
# Stateless and key-authenticated: a machine posts here inside a visitor's form
|
||||
# submission on another site, so there is no session, no login form and no redirect.
|
||||
# Must stay above "main", whose pattern is ^/.
|
||||
api:
|
||||
pattern: ^/api
|
||||
stateless: true
|
||||
provider: api_user_provider
|
||||
access_token:
|
||||
token_handler: App\Security\AccessToken\ApiKeyTokenHandler
|
||||
token_extractors:
|
||||
- App\Security\AccessToken\ApiKeyExtractor
|
||||
main:
|
||||
lazy: true
|
||||
provider: bpn_user_provider
|
||||
@@ -29,6 +46,8 @@ security:
|
||||
path: app_security_logout
|
||||
target: app_security_login
|
||||
access_control:
|
||||
# The firewall authenticates, the controller requires ROLE_API
|
||||
- { path: '^/api', roles: PUBLIC_ACCESS, requires_channel: https }
|
||||
- { path: '^/_uploader', roles: ROLE_USER, requires_channel: https }
|
||||
- { path: '^/', roles: PUBLIC_ACCESS, requires_channel: https }
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
# Enabled for #[MapRequestPayload] on the api controllers - nothing else in this application
|
||||
# serializes. ALLOW_EXTRA_ATTRIBUTES stays at its default (true) on purpose: the TYPO3 form
|
||||
# payload grows keys without a release here, and rejecting an unknown one would turn every
|
||||
# later mapping change into a 400 (see .ddev/plans/application-form-endpoint.md).
|
||||
framework:
|
||||
serializer:
|
||||
name_converter: ~
|
||||
@@ -35,6 +35,11 @@ parameters:
|
||||
1461: 'SHM'
|
||||
1462: 'AGR'
|
||||
|
||||
# Shared key the sibling websites authenticate their form submissions with. Empty here on
|
||||
# purpose - the real value belongs in the environment of each stage, and an empty key
|
||||
# rejects every request instead of letting them through.
|
||||
application_form_api_key: '%env(string:APPLICATION_FORM_API_KEY)%'
|
||||
|
||||
default_email_from: '%env(APP_DEFAULT_EMAIL_FROM)%'
|
||||
default_email_to: '%env(APP_DEFAULT_EMAIL_TO)%'
|
||||
|
||||
@@ -318,6 +323,18 @@ services:
|
||||
from: '%default_email_from%'
|
||||
to: '%default_email_to%'
|
||||
|
||||
# Its own log channel, not the audit one bound by default: the audit channel writes a row
|
||||
# to the log table through App\Logging\DatabaseHandler, which records what staff did here.
|
||||
App\Security\AccessToken\ApiKeyTokenHandler:
|
||||
arguments:
|
||||
$apiKey: '%application_form_api_key%'
|
||||
$logger: '@monolog.logger.api'
|
||||
|
||||
App\Controller\Api\ApplicationFormController:
|
||||
arguments:
|
||||
$logger: '@monolog.logger.api'
|
||||
tags: [ 'controller.service_arguments' ]
|
||||
|
||||
App\Security\OAuth2\MyEpClient:
|
||||
arguments:
|
||||
$options:
|
||||
|
||||
Reference in new issue
Block a user