Regalamiunsorriso/www/faceai_config.php
MaddoScientisto af8647f3aa
All checks were successful
Publish FaceAI Container / publish (push) Successful in 2m56s
Updated configurations for deployment
2026-04-12 15:21:33 +02:00

265 lines
7.8 KiB
PHP

<?php
function faceai_env($key, $default = null)
{
$value = getenv($key);
return $value === false ? $default : $value;
}
function faceai_env_flag($key, $default = false)
{
$value = strtolower(trim((string) faceai_env($key, $default ? '1' : '0')));
return in_array($value, array('1', 'true', 'yes', 'on'), true);
}
function faceai_request_host()
{
if (empty($_SERVER['HTTP_HOST'])) {
return '';
}
return strtolower(trim((string) $_SERVER['HTTP_HOST']));
}
function faceai_is_local_host($host)
{
$normalized = strtolower(trim((string) $host));
if ($normalized === '') {
return false;
}
$withoutPort = preg_replace('/:\d+$/', '', $normalized);
return in_array($withoutPort, array('localhost', '127.0.0.1', '::1'), true);
}
function faceai_request_targets_local_frontend()
{
if (faceai_is_local_host(faceai_request_host())) {
return true;
}
$returnUrl = faceai_request_value('returnUrl');
if ($returnUrl === '') {
return false;
}
$host = parse_url($returnUrl, PHP_URL_HOST);
if (!is_string($host) || $host === '') {
return false;
}
return faceai_is_local_host($host);
}
function faceai_default_frontend_url()
{
if (faceai_request_targets_local_frontend()) {
return 'http://localhost:3001';
}
return 'https://ai.regalamiunsorriso.it';
}
function faceai_default_backend_internal_url()
{
if (faceai_is_local_host(faceai_request_host())) {
return 'http://localhost:3001';
}
return 'https://ai.regalamiunsorriso.it';
}
function faceai_config()
{
static $config = null;
if ($config !== null) {
return $config;
}
$config = array(
'feature_enabled' => faceai_env_flag('FACEAI_FEATURE_ENABLED', false),
'frontend_url' => rtrim(faceai_env('FACEAI_FRONTEND_URL', faceai_default_frontend_url()), '/'),
'backend_internal_url' => rtrim(faceai_env('FACEAI_BACKEND_INTERNAL_URL', faceai_default_backend_internal_url()), '/'),
'shared_secret' => (string) faceai_env('FACEAI_SHARED_SECRET', 'change-me'),
'allow_dev_handoff' => faceai_env_flag('FACEAI_ALLOW_DEV_HANDOFF', true),
'identity_cookie' => (string) faceai_env('FACEAI_IDENTITY_COOKIE', 'rus_faceai_identity'),
'return_forward_url' => rtrim((string) faceai_env('FACEAI_RETURN_FORWARD_URL', ''), '/')
);
return $config;
}
function faceai_base64url_encode($value)
{
return rtrim(strtr(base64_encode($value), '+/', '-_'), '=');
}
function faceai_base64url_decode($value)
{
$padding = strlen($value) % 4;
if ($padding > 0) {
$value .= str_repeat('=', 4 - $padding);
}
return base64_decode(strtr($value, '-_', '+/'));
}
function faceai_sign_payload(array $payload, $secret)
{
$body = faceai_base64url_encode(json_encode($payload));
$signature = hash_hmac('sha256', $body, $secret, true);
return $body . '.' . faceai_base64url_encode($signature);
}
function faceai_verify_payload($token, $secret)
{
if (!is_string($token) || strpos($token, '.') === false) {
throw new RuntimeException('Invalid token format.');
}
list($body, $signature) = explode('.', $token, 2);
$expected = faceai_base64url_encode(hash_hmac('sha256', $body, $secret, true));
if (!hash_equals($expected, $signature)) {
throw new RuntimeException('Invalid token signature.');
}
$decoded = faceai_base64url_decode($body);
$payload = json_decode($decoded, true);
if (!is_array($payload)) {
throw new RuntimeException('Invalid token payload.');
}
if (isset($payload['expiresAt']) && (int) $payload['expiresAt'] < (int) round(microtime(true) * 1000)) {
throw new RuntimeException('Token expired.');
}
return $payload;
}
function faceai_build_url($baseUrl, array $params)
{
return $baseUrl . (strpos($baseUrl, '?') === false ? '?' : '&') . http_build_query($params);
}
function faceai_redirect_with_error($returnUrl, $message, $title = 'Face ID non disponibile')
{
if (is_string($returnUrl) && trim($returnUrl) !== '') {
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
header('Pragma: no-cache');
header('Location: ' . faceai_build_url($returnUrl, array(
'faceaiError' => '1',
'faceaiErrorTitle' => $title,
'faceaiErrorMessage' => $message
)), true, 302);
exit;
}
faceai_render_message_page($title, $message, array(), 503);
}
function faceai_request_value($key, $default = '')
{
if (!isset($_GET[$key])) {
return $default;
}
if (is_array($_GET[$key])) {
return $default;
}
return trim((string) $_GET[$key]);
}
function faceai_html($value)
{
return htmlspecialchars((string) $value, ENT_QUOTES, 'UTF-8');
}
function faceai_resolve_identity(array $config)
{
if (!empty($_COOKIE[$config['identity_cookie']])) {
$payload = faceai_verify_payload($_COOKIE[$config['identity_cookie']], $config['shared_secret']);
if (($payload['type'] ?? '') !== 'legacy-identity') {
throw new RuntimeException('Unexpected identity cookie payload.');
}
return array(
'id' => (string) ($payload['userId'] ?? ''),
'displayName' => (string) ($payload['displayName'] ?? ''),
'email' => (string) ($payload['email'] ?? ''),
'membershipStatus' => (string) ($payload['membershipStatus'] ?? 'inactive')
);
}
if ($config['allow_dev_handoff']) {
$userId = faceai_request_value('devUserId');
if ($userId !== '') {
return array(
'id' => $userId,
'displayName' => faceai_request_value('devDisplayName', 'Local Test User'),
'email' => faceai_request_value('devEmail', 'local.test@example.invalid'),
'membershipStatus' => faceai_request_value('devMembershipStatus', 'active')
);
}
}
return null;
}
function faceai_render_message_page($title, $message, array $details = array(), $statusCode = 400)
{
http_response_code($statusCode);
header('Content-Type: text/html; charset=UTF-8');
echo '<!doctype html><html lang="it"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1">';
echo '<title>' . faceai_html($title) . '</title>';
echo '<style>body{font-family:Georgia,serif;background:#f7f1e8;color:#2a231b;margin:0;padding:32px}main{max-width:900px;margin:0 auto;background:#fff;border:1px solid #ddcbb5;padding:24px}h1{margin-top:0}code{background:#f2ece2;padding:2px 5px}ul{padding-left:20px}li{margin:8px 0}</style>';
echo '</head><body><main>';
echo '<h1>' . faceai_html($title) . '</h1>';
echo '<p>' . faceai_html($message) . '</p>';
if (!empty($details)) {
echo '<ul>';
foreach ($details as $detail) {
echo '<li>' . faceai_html($detail) . '</li>';
}
echo '</ul>';
}
echo '</main></body></html>';
exit;
}
function faceai_fetch_json($url)
{
$context = stream_context_create(array(
'http' => array(
'ignore_errors' => true,
'timeout' => 10
)
));
$response = @file_get_contents($url, false, $context);
if ($response === false) {
throw new RuntimeException('Unable to fetch remote FaceAI data.');
}
$statusCode = 0;
if (!empty($http_response_header[0]) && preg_match('/\s(\d{3})\s/', $http_response_header[0], $matches)) {
$statusCode = (int) $matches[1];
}
$payload = json_decode($response, true);
if (!is_array($payload)) {
throw new RuntimeException('FaceAI returned invalid JSON.');
}
if ($statusCode >= 400) {
throw new RuntimeException($payload['error'] ?? ('FaceAI bridge request failed with status ' . $statusCode . '.'));
}
return $payload;
}