Finalize env api endpoint to better reflect the types instead of returning everything as string.

This commit is contained in:
abdulmohsen
2024-05-16 18:46:06 +03:00
parent 8f8840a3db
commit 53de7bfd76

View File

@@ -33,7 +33,7 @@ final class Env
continue; continue;
} }
$info['value'] = $this->envFile->get($info['key']); $info['value'] = $this->setType($info, $this->envFile->get($info['key']));
} }
$this->envSpec = $spec; $this->envSpec = $spec;
@@ -42,6 +42,8 @@ final class Env
#[Get(self::URL . '[/]', name: 'system.env')] #[Get(self::URL . '[/]', name: 'system.env')]
public function envList(iRequest $request): iResponse public function envList(iRequest $request): iResponse
{ {
$params = DataUtil::fromRequest($request, true);
$list = []; $list = [];
foreach ($this->envSpec as $info) { foreach ($this->envSpec as $info) {
@@ -51,8 +53,12 @@ final class Env
$list[] = $info; $list[] = $info;
} }
if (true === (bool)$params->get('set', false)) {
$list = array_filter($list, fn($info) => $this->envFile->has($info['key']));
}
return api_response(HTTP_STATUS::HTTP_OK, [ return api_response(HTTP_STATUS::HTTP_OK, [
'data' => $list, 'data' => array_values($list),
'file' => Config::get('path') . '/config/.env', 'file' => Config::get('path') . '/config/.env',
]); ]);
} }
@@ -77,7 +83,7 @@ final class Env
return api_response(HTTP_STATUS::HTTP_OK, [ return api_response(HTTP_STATUS::HTTP_OK, [
'key' => $key, 'key' => $key,
'value' => $this->envFile->get($key), 'value' => $this->settype($spec, ag($spec, 'value', fn() => $this->envFile->get($key))),
'description' => ag($spec, 'description'), 'description' => ag($spec, 'description'),
'type' => ag($spec, 'type'), 'type' => ag($spec, 'type'),
]); ]);
@@ -102,7 +108,7 @@ final class Env
return api_response(HTTP_STATUS::HTTP_OK, [ return api_response(HTTP_STATUS::HTTP_OK, [
'key' => $key, 'key' => $key,
'value' => $this->envFile->get($key, fn() => env($key)), 'value' => $this->setType($spec, ag($spec, 'value', fn() => $this->envFile->get($key))),
'description' => ag($spec, 'description'), 'description' => ag($spec, 'description'),
'type' => ag($spec, 'type'), 'type' => ag($spec, 'type'),
]); ]);
@@ -111,26 +117,17 @@ final class Env
$params = DataUtil::fromRequest($request); $params = DataUtil::fromRequest($request);
if (null === ($value = $params->get('value', null))) { if (null === ($value = $params->get('value', null))) {
return api_error(r("No value was provided for '{key}'.", [ return api_error(r("No value was provided for '{key}'.", ['key' => $key]), HTTP_STATUS::HTTP_BAD_REQUEST);
'key' => $key,
]), HTTP_STATUS::HTTP_BAD_REQUEST);
} }
if ($value === $this->envFile->get($key)) { if ($value === ag($spec, 'value')) {
return api_response(HTTP_STATUS::HTTP_NOT_MODIFIED); return api_response(HTTP_STATUS::HTTP_NOT_MODIFIED);
} }
$value = (string)$value;
// -- check if the string contains space but not quoted.
// symfony/dotenv throws an exception if the value contains a space but not quoted.
if (str_contains($value, ' ') && (!str_starts_with($value, '"') || !str_ends_with($value, '"'))) {
return api_error(r("The value for '{key}' must be \"quoted\", as it contains a space.", [
'key' => $key,
]), HTTP_STATUS::HTTP_BAD_REQUEST);
}
try { try {
$value = $this->setType($spec, $value);
if (false === $this->checkValue($spec, $value)) { if (false === $this->checkValue($spec, $value)) {
throw new InvalidArgumentException(r("Invalid value for '{key}'.", ['key' => $key])); throw new InvalidArgumentException(r("Invalid value for '{key}'.", ['key' => $key]));
} }
@@ -141,26 +138,11 @@ final class Env
]), HTTP_STATUS::HTTP_BAD_REQUEST); ]), HTTP_STATUS::HTTP_BAD_REQUEST);
} }
switch (ag($spec, 'type', 'string')) {
case 'bool':
settype($value, 'bool');
break;
case 'int':
settype($value, 'int');
break;
case 'float':
settype($value, 'float');
break;
default:
settype($value, 'string');
break;
}
$this->envFile->set($key, $value)->persist(); $this->envFile->set($key, $value)->persist();
return api_response(HTTP_STATUS::HTTP_OK, [ return api_response(HTTP_STATUS::HTTP_OK, [
'key' => $key, 'key' => $key,
'value' => $this->envFile->get($key, fn() => env($key)), 'value' => $value,
'description' => ag($spec, 'description'), 'description' => ag($spec, 'description'),
'type' => ag($spec, 'type'), 'type' => ag($spec, 'type'),
]); ]);
@@ -176,6 +158,14 @@ final class Env
*/ */
private function checkValue(array $spec, mixed $value): bool private function checkValue(array $spec, mixed $value): bool
{ {
if (true === is_string($value)) {
// -- check if the string contains space but not quoted.
// symfony/dotenv throws an exception if the value contains a space but not quoted.
if (str_contains($value, ' ') && (!str_starts_with($value, '"') || !str_ends_with($value, '"'))) {
throw new InvalidArgumentException('The value must be "quoted string", as it contains a space.');
}
}
if (ag_exists($spec, 'validate')) { if (ag_exists($spec, 'validate')) {
return (bool)$spec['validate']($value); return (bool)$spec['validate']($value);
} }
@@ -201,4 +191,14 @@ final class Env
return []; return [];
} }
private function setType($spec, mixed $value): mixed
{
return match (ag($spec, 'type', 'string')) {
'bool' => (bool)$value,
'int' => (int)$value,
'float' => (float)$value,
default => (string)$value,
};
}
} }