Skip to content

Commit 7175de0

Browse files
committed
Added support for os2web_key
1 parent 0f42320 commit 7175de0

10 files changed

+320
-72
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
composer.lock
2+
vendor/

composer.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,14 @@
66
"prefer-stable": true,
77
"license": "EUPL-1.2",
88
"require": {
9-
"ext-soap": "*"
9+
"ext-soap": "*",
10+
"os2web/os2web_key": "dev-os2web_key"
1011
},
1112
"repositories": {
13+
"os2web/os2web_key": {
14+
"type": "vcs",
15+
"url": "https://github.com/rimi-itk/os2web_key"
16+
},
1217
"drupal": {
1318
"type": "composer",
1419
"url": "https://packages.drupal.org/8"

src/Exception/RuntimeException.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php
2+
3+
namespace Drupal\os2web_datalookup\Exception;
4+
5+
class RuntimeException extends \RuntimeException
6+
{
7+
8+
}

src/Plugin/os2web/DataLookup/DataLookupBase.php

Lines changed: 90 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,13 @@
22

33
namespace Drupal\os2web_datalookup\Plugin\os2web\DataLookup;
44

5+
use Drupal\Core\File\FileSystem;
56
use Drupal\Core\Form\FormStateInterface;
7+
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
68
use Drupal\Core\Plugin\PluginBase;
9+
use Drupal\key\KeyRepositoryInterface;
10+
use Drupal\os2web_datalookup\Exception\RuntimeException;
11+
use Symfony\Component\DependencyInjection\ContainerInterface;
712

813
/**
914
* Provides a base class for image effects.
@@ -15,7 +20,19 @@
1520
* @see \Drupal\image\ImageEffectManager
1621
* @see plugin_api
1722
*/
18-
abstract class DataLookupBase extends PluginBase implements DataLookupInterface {
23+
abstract class DataLookupBase extends PluginBase implements ContainerFactoryPluginInterface, DataLookupInterface {
24+
protected const PROVIDER_TYPE_FORM = 'form';
25+
protected const PROVIDER_TYPE_KEY = 'key';
26+
27+
/**
28+
* Local certificate path.
29+
*
30+
* Used to temporarily store a certificate in a file just before calling a webservice.
31+
* For security purposes, the file will be removed right after the webservice calls completes.
32+
*
33+
* @var string
34+
*/
35+
private string $localCertPath;
1936

2037
/**
2138
* Plugin readiness flag.
@@ -27,12 +44,39 @@ abstract class DataLookupBase extends PluginBase implements DataLookupInterface
2744
/**
2845
* {@inheritdoc}
2946
*/
30-
public function __construct(array $configuration, $plugin_id, $plugin_definition) {
47+
public function __construct(array $configuration, $plugin_id, $plugin_definition,
48+
protected KeyRepositoryInterface $keyRepository,
49+
protected FileSystem $fileSystem
50+
) {
3151
parent::__construct($configuration, $plugin_id, $plugin_definition);
3252
$this->setConfiguration($configuration);
53+
$this->init();
54+
}
55+
56+
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition)
57+
{
58+
/** @var KeyRepositoryInterface $keyRepository */
59+
$keyRepository = $container->get('key.repository');
60+
/** @var FileSystem $fileSystem */
61+
$fileSystem = $container->get('file_system');
62+
63+
return new static(
64+
$configuration,
65+
$plugin_id,
66+
$plugin_definition,
67+
$keyRepository,
68+
$fileSystem
69+
);
3370
}
3471

3572
/**
73+
* Plugin init method.
74+
*/
75+
protected function init()
76+
{
77+
}
78+
79+
/**
3680
* {@inheritdoc}
3781
*/
3882
public function label() {
@@ -58,7 +102,10 @@ public function setConfiguration(array $configuration) {
58102
* {@inheritdoc}
59103
*/
60104
public function defaultConfiguration() {
61-
return [];
105+
return [
106+
'certificate_provider' => '',
107+
'certificate_key' => '',
108+
];
62109
}
63110

64111
/**
@@ -89,4 +136,44 @@ public function isReady() {
89136
return $this->isReady;
90137
}
91138

139+
/**
140+
* Get certificate.
141+
*/
142+
protected function getCertificate(): string {
143+
return '';
144+
}
145+
146+
/**
147+
* Create a temporary file path for a certificate.
148+
*
149+
* Note: We do not want the create a file. Just get a temporary file name.
150+
*
151+
* @return string
152+
* The local certificate path.
153+
*/
154+
protected function createLocalCertPath(): string {
155+
$this->localCertPath = $this->fileSystem->getTempDirectory().'/'.uniqid('os2web_datalookup_local_cert_');
156+
157+
return $this->localCertPath;
158+
}
159+
160+
/**
161+
* Write certificate to temporary certificate file.
162+
*
163+
* @return string
164+
* The local certificate path.
165+
*/
166+
protected function writeCertificateToFile(): string
167+
{
168+
// Write certificate to local_cert location.
169+
$certificate = $this->getCertificate();
170+
$localCertPath = $this->localCertPath;
171+
$result = $this->fileSystem->saveData($certificate, $localCertPath, FileSystem::EXISTS_REPLACE);
172+
if (!$result) {
173+
return new RuntimeException(sprintf('Error writing certificate to temporary file %s', $localCertPath));
174+
}
175+
176+
return $result;
177+
}
178+
92179
}

src/Plugin/os2web/DataLookup/DatafordelerBase.php

Lines changed: 93 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,33 +2,40 @@
22

33
namespace Drupal\os2web_datalookup\Plugin\os2web\DataLookup;
44

5+
use Drupal\Core\File\FileSystem;
56
use Drupal\Core\Form\FormStateInterface;
7+
use Drupal\os2web_datalookup\Exception\RuntimeException;
68
use GuzzleHttp\Client;
9+
use Psr\Http\Message\ResponseInterface;
710

811
/**
912
* Defines base plugin class for Datafordeler lookup plugins.
1013
*/
1114
abstract class DatafordelerBase extends DataLookupBase {
1215

1316
/**
14-
* Plugin readiness flag.
17+
* The client.
1518
*
16-
* @var bool
19+
* @var Client
1720
*/
18-
protected $httpClient;
21+
private $httpClient;
1922

2023
/**
2124
* {@inheritdoc}
2225
*/
23-
public function __construct(array $configuration, $plugin_id, $plugin_definition) {
24-
parent::__construct($configuration, $plugin_id, $plugin_definition);
25-
$this->init();
26+
public function defaultConfiguration()
27+
{
28+
return [
29+
'cert_path_live' => '',
30+
'cert_passphrase_live' => '',
31+
] + parent::defaultConfiguration();
2632
}
2733

2834
/**
29-
* Plugin init method.
35+
* {@inheritdoc}
3036
*/
31-
private function init() {
37+
protected function init() {
38+
parent::init();
3239
$this->isReady = FALSE;
3340

3441
$configuration = $this->getConfiguration();
@@ -40,8 +47,10 @@ private function init() {
4047
'accept' => 'application/json',
4148
],
4249
];
43-
if ($certPath = $configuration['cert_path_live']) {
44-
$options['cert'] = $certPath;
50+
51+
if (isset($configuration['cert_path_live']) || isset($configuration['key'])) {
52+
$options['cert'] = $this->createLocalCertPath();
53+
4554
$this->httpClient = new Client($options);
4655
$this->isReady = TRUE;
4756
}
@@ -71,18 +80,53 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta
7180
'#default_value' => $this->configuration['webserviceurl_live'],
7281
];
7382

74-
$form['cert_path_live'] = [
83+
$form['certificate'] = [
84+
'#type' => 'fieldset',
85+
'#title' => $this->t('Certificate'),
86+
87+
'certificate_provider' => [
88+
'#type' => 'select',
89+
'#title' => $this->t('Provider'),
90+
'#options' => [
91+
self::PROVIDER_TYPE_FORM => $this->t('Form'),
92+
self::PROVIDER_TYPE_KEY => $this->t('Key'),
93+
],
94+
'#default_value' => $this->configuration['certificate_provider'] ?? self::PROVIDER_TYPE_FORM,
95+
],
96+
97+
'certificate_key' => [
98+
'#type' => 'key_select',
99+
'#key_filters' => [
100+
'type' => 'os2web_certificate',
101+
],
102+
'#title' => $this->t('Key'),
103+
'#default_value' => $this->configuration['certificate_key'] ?? NULL,
104+
'#states' => [
105+
'required' => [':input[name="certificate_provider"]' => ['value' => self::PROVIDER_TYPE_KEY]],
106+
'visible' => [':input[name="certificate_provider"]' => ['value' => self::PROVIDER_TYPE_KEY]],
107+
],
108+
],
109+
110+
'cert_path_live' => [
75111
'#type' => 'textfield',
76112
'#title' => $this->t('Certificate (LIVE)'),
77113
'#description' => $this->t('Path to the certificate'),
78114
'#default_value' => $this->configuration['cert_path_live'],
79-
];
115+
'#states' => [
116+
'required' => [':input[name="certificate_provider"]' => ['value' => self::PROVIDER_TYPE_FORM]],
117+
'visible' => [':input[name="certificate_provider"]' => ['value' => self::PROVIDER_TYPE_FORM]],
118+
],
119+
],
80120

81-
$form['cert_passphrase_live'] = [
121+
'cert_passphrase_live' => [
82122
'#type' => 'password',
83123
'#title' => $this->t('Certificate passphrase (LIVE)'),
84124
'#description' => $this->t('leave empty if not used'),
85125
'#default_value' => $this->configuration['cert_passphrase_live'],
126+
'#states' => [
127+
'visible' => [':input[name="certificate_provider"]' => ['value' => self::PROVIDER_TYPE_FORM]],
128+
],
129+
],
86130
];
87131

88132
return $form;
@@ -104,4 +148,40 @@ public function submitConfigurationForm(array &$form, FormStateInterface $form_s
104148
$this->setConfiguration($configuration);
105149
}
106150

151+
/**
152+
* Get response.
153+
*/
154+
protected function getResponse(string $uri, array $options): ResponseInterface
155+
{
156+
try {
157+
$localCertPath = $this->writeCertificateToFile();
158+
159+
return $this->httpClient->get($uri, $options);
160+
} finally {
161+
// Remove temporary certificate file.
162+
if (file_exists($localCertPath)) {
163+
unlink($localCertPath);
164+
}
165+
}
166+
}
167+
168+
/**
169+
* Get certificate.
170+
*/
171+
protected function getCertificate(): string {
172+
$provider = $this->configuration['certificate_provider'] ?? NULL;
173+
if (self::PROVIDER_TYPE_KEY === $provider) {
174+
$keyId = $this->configuration['certificate_key'] ?? '';
175+
$key = $this->keyRepository->getKey($keyId);
176+
if (NULL === $key) {
177+
throw new RuntimeException(sprintf('Cannot get key %s', $keyId));
178+
}
179+
180+
return $key->getKeyValue();
181+
}
182+
183+
$filename = $this->configuration['cert_path_live'];
184+
185+
return file_get_contents($filename);
186+
}
107187
}

src/Plugin/os2web/DataLookup/DatafordelerCVR.php

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,8 @@ class DatafordelerCVR extends DatafordelerBase implements DataLookupInterfaceCom
2424
*/
2525
public function defaultConfiguration() {
2626
return [
27-
'webserviceurl_live' => 'https://s5-certservices.datafordeler.dk/CVR/HentCVRData/1/REST/',
28-
'cert_path_live' => '',
29-
'cert_passphrase_live' => '',
30-
];
27+
'webserviceurl_live' => 'https://s5-certservices.datafordeler.dk/CVR/HentCVRData/1/REST/',
28+
] + parent::defaultConfiguration();
3129
}
3230

3331
/**
@@ -66,7 +64,7 @@ public function submitConfigurationForm(array &$form, FormStateInterface $form_s
6664
*/
6765
public function lookup($cvr) {
6866
try {
69-
$response = $this->httpClient->get('hentVirksomhedMedCVRNummer', ['query' => ['pCVRNummer' => $cvr]]);
67+
$response = $this->getResponse('hentVirksomhedMedCVRNummer', ['query' => ['pCVRNummer' => $cvr]]);
7068
$result = json_decode((string) $response->getBody());
7169
}
7270
catch (ClientException $e) {

src/Plugin/os2web/DataLookup/DatafordelerPNumber.php

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,8 @@ class DatafordelerPNumber extends DatafordelerBase implements DataLookupInterfac
2424
*/
2525
public function defaultConfiguration() {
2626
return [
27-
'webserviceurl_live' => 'https://s5-certservices.datafordeler.dk/CVR/HentCVRData/1/REST/',
28-
'cert_path_live' => '',
29-
'cert_passphrase_live' => '',
30-
];
27+
'webserviceurl_live' => 'https://s5-certservices.datafordeler.dk/CVR/HentCVRData/1/REST/',
28+
] + parent::defaultConfiguration();
3129
}
3230

3331
/**
@@ -66,7 +64,7 @@ public function submitConfigurationForm(array &$form, FormStateInterface $form_s
6664
*/
6765
public function lookup($param) {
6866
try {
69-
$response = $this->httpClient->get('hentProduktionsenhedMedPNummer', ['query' => ['ppNummer' => $param]]);
67+
$response = $this->getResponse('hentProduktionsenhedMedPNummer', ['query' => ['ppNummer' => $param]]);
7068
$result = json_decode((string) $response->getBody());
7169
}
7270
catch (ClientException $e) {

0 commit comments

Comments
 (0)