feat: surface remnawave panel webhook settings
This commit is contained in:
@@ -30,6 +30,11 @@ class SettingField:
|
||||
i18n_label_key: Optional[str] = None
|
||||
i18n_description_key: Optional[str] = None
|
||||
i18n_subsection_key: Optional[str] = None
|
||||
webhook_path: Optional[str] = None
|
||||
webhook_requires_base_url: bool = False
|
||||
webhook_provider_id: Optional[str] = None
|
||||
webhook_hint_i18n_key: Optional[str] = None
|
||||
webhook_hint: str = ""
|
||||
|
||||
|
||||
SETTINGS_MANIFEST: List[SettingField] = [
|
||||
@@ -84,44 +89,44 @@ SETTINGS_MANIFEST: List[SettingField] = [
|
||||
SettingField(
|
||||
"PANEL_API_URL",
|
||||
"url",
|
||||
"general",
|
||||
"remnawave",
|
||||
"URL API Remnawave",
|
||||
"Например, https://panel.example.com/api.",
|
||||
subsection="Remnawave",
|
||||
),
|
||||
SettingField(
|
||||
"PANEL_API_KEY",
|
||||
"string",
|
||||
"general",
|
||||
"remnawave",
|
||||
"API-ключ Remnawave",
|
||||
"Секретный ключ API панели.",
|
||||
secret=True,
|
||||
subsection="Remnawave",
|
||||
),
|
||||
SettingField(
|
||||
"PANEL_WEBHOOK_SECRET",
|
||||
"string",
|
||||
"general",
|
||||
"remnawave",
|
||||
"Секрет вебхуков Remnawave",
|
||||
"Используется для проверки входящих вебхуков панели.",
|
||||
secret=True,
|
||||
subsection="Remnawave",
|
||||
webhook_path="/webhook/panel",
|
||||
webhook_requires_base_url=True,
|
||||
webhook_provider_id="remnawave",
|
||||
webhook_hint_i18n_key="admin_settings_panel_webhook_url_hint",
|
||||
webhook_hint="Use this URL as WEBHOOK_URL in Remnawave Panel.",
|
||||
),
|
||||
SettingField(
|
||||
"USER_SQUAD_UUIDS",
|
||||
"string",
|
||||
"general",
|
||||
"remnawave",
|
||||
"Internal Squads по умолчанию",
|
||||
"UUID через запятую для legacy-режима без JSON-каталога тарифов.",
|
||||
subsection="Remnawave",
|
||||
),
|
||||
SettingField(
|
||||
"USER_EXTERNAL_SQUAD_UUID",
|
||||
"string",
|
||||
"general",
|
||||
"remnawave",
|
||||
"External Squad по умолчанию",
|
||||
"Необязательный UUID External Squad для новых пользователей.",
|
||||
subsection="Remnawave",
|
||||
),
|
||||
# ─── Web app appearance ────────────────────────────────────────
|
||||
SettingField(
|
||||
@@ -707,6 +712,7 @@ def manifest_payload() -> List[dict]:
|
||||
sections_order = {
|
||||
"general": 1,
|
||||
"appearance": 2,
|
||||
"remnawave": 3,
|
||||
"pricing": 11,
|
||||
"payments": 4,
|
||||
"trial": 5,
|
||||
@@ -773,6 +779,15 @@ def manifest_payload() -> List[dict]:
|
||||
item["default"] = default_value
|
||||
if webhook_metadata:
|
||||
item.update(webhook_metadata)
|
||||
if field.webhook_path:
|
||||
item["webhook_path"] = field.webhook_path
|
||||
item["webhook_requires_base_url"] = field.webhook_requires_base_url
|
||||
if field.webhook_provider_id:
|
||||
item["provider_id"] = field.webhook_provider_id
|
||||
if field.webhook_hint_i18n_key:
|
||||
item["webhook_hint_i18n_key"] = field.webhook_hint_i18n_key
|
||||
if field.webhook_hint:
|
||||
item["webhook_hint"] = field.webhook_hint
|
||||
if field.choices:
|
||||
item["choices"] = [
|
||||
{
|
||||
|
||||
@@ -198,6 +198,8 @@
|
||||
url,
|
||||
requiresBaseUrl: Boolean(field.webhook_requires_base_url),
|
||||
baseConfigured: field.webhook_base_url_configured !== false,
|
||||
hintI18nKey: field.webhook_hint_i18n_key || "",
|
||||
hintFallback: field.webhook_hint || "",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -333,6 +335,7 @@
|
||||
function sectionTitle(id) {
|
||||
const map = {
|
||||
general: "Общие",
|
||||
remnawave: "Remnawave Panel",
|
||||
appearance: "Внешний вид",
|
||||
pricing: "Тарифы и цены",
|
||||
payments: "Платёжные системы",
|
||||
@@ -415,9 +418,9 @@
|
||||
<small>
|
||||
{webhook.url
|
||||
? at(
|
||||
"settings_provider_webhook_url_hint",
|
||||
adminLocaleKey(webhook.hintI18nKey || "settings_provider_webhook_url_hint"),
|
||||
{},
|
||||
"Use this URL in the provider webhook settings."
|
||||
webhook.hintFallback || "Use this URL in the provider webhook settings."
|
||||
)
|
||||
: at(
|
||||
"settings_provider_webhook_base_missing",
|
||||
|
||||
+3
-1
@@ -1017,6 +1017,7 @@
|
||||
"admin_content": "Content",
|
||||
"admin_logs_empty": "No entries",
|
||||
"admin_settings_section_general": "General",
|
||||
"admin_settings_section_remnawave": "Remnawave Panel",
|
||||
"admin_settings_section_appearance": "Appearance",
|
||||
"admin_settings_section_pricing": "Legacy tariff compatibility",
|
||||
"admin_settings_section_payments": "Payment systems",
|
||||
@@ -1039,6 +1040,7 @@
|
||||
"admin_settings_subsection_heleket": "Heleket",
|
||||
"admin_settings_provider_webhook_url": "Webhook URL",
|
||||
"admin_settings_provider_webhook_url_hint": "Use this URL in the provider webhook settings.",
|
||||
"admin_settings_panel_webhook_url_hint": "Use this URL as WEBHOOK_URL in Remnawave Panel.",
|
||||
"admin_settings_provider_webhook_base_missing": "Set WEBHOOK_BASE_URL in .env to show the full URL for {path}.",
|
||||
"admin_settings_provider_admin_only_label": "Only for admins",
|
||||
"admin_settings_provider_admin_only_description": "Shows this provider only to admins. Webhooks and payment status handling remain active for test payments.",
|
||||
@@ -1437,7 +1439,7 @@
|
||||
"admin_settings_field_panel_api_key_label": "Remnawave API key",
|
||||
"admin_settings_field_panel_api_key_description": "Secret API key for the panel.",
|
||||
"admin_settings_field_panel_webhook_secret_label": "Remnawave webhook secret",
|
||||
"admin_settings_field_panel_webhook_secret_description": "Used to verify incoming panel webhooks.",
|
||||
"admin_settings_field_panel_webhook_secret_description": "Set the secret in Remnawave Panel and paste the same value here to verify incoming panel webhooks.",
|
||||
"admin_settings_field_user_squad_uuids_label": "Default Internal Squads",
|
||||
"admin_settings_field_user_squad_uuids_description": "Comma-separated UUIDs for the legacy mode without a JSON tariff catalog.",
|
||||
"admin_settings_field_user_external_squad_uuid_label": "Default External Squad",
|
||||
|
||||
+3
-1
@@ -1017,6 +1017,7 @@
|
||||
"admin_content": "Контент",
|
||||
"admin_logs_empty": "Записей нет",
|
||||
"admin_settings_section_general": "Общие",
|
||||
"admin_settings_section_remnawave": "Remnawave Panel",
|
||||
"admin_settings_section_appearance": "Внешний вид",
|
||||
"admin_settings_section_pricing": "Совместимость с legacy-тарифами",
|
||||
"admin_settings_section_payments": "Платёжные системы",
|
||||
@@ -1039,6 +1040,7 @@
|
||||
"admin_settings_subsection_heleket": "Heleket",
|
||||
"admin_settings_provider_webhook_url": "Webhook URL",
|
||||
"admin_settings_provider_webhook_url_hint": "Укажите этот адрес в настройках вебхуков провайдера.",
|
||||
"admin_settings_panel_webhook_url_hint": "Укажите этот адрес как WEBHOOK_URL в Remnawave Panel.",
|
||||
"admin_settings_provider_webhook_base_missing": "Укажите WEBHOOK_BASE_URL в .env, чтобы увидеть полный адрес для {path}.",
|
||||
"admin_settings_provider_admin_only_label": "Только для админов",
|
||||
"admin_settings_provider_admin_only_description": "Показывает провайдер только администраторам. Вебхуки и обработка статусов остаются активными для тестовых платежей.",
|
||||
@@ -1437,7 +1439,7 @@
|
||||
"admin_settings_field_panel_api_key_label": "API-ключ Remnawave",
|
||||
"admin_settings_field_panel_api_key_description": "Секретный ключ API панели.",
|
||||
"admin_settings_field_panel_webhook_secret_label": "Секрет вебхуков Remnawave",
|
||||
"admin_settings_field_panel_webhook_secret_description": "Используется для проверки входящих вебхуков панели.",
|
||||
"admin_settings_field_panel_webhook_secret_description": "Задайте секрет в Remnawave Panel и вставьте то же значение здесь для проверки входящих вебхуков панели.",
|
||||
"admin_settings_field_user_squad_uuids_label": "Internal Squads по умолчанию",
|
||||
"admin_settings_field_user_squad_uuids_description": "UUID через запятую для legacy-режима без JSON-каталога тарифов.",
|
||||
"admin_settings_field_user_external_squad_uuid_label": "External Squad по умолчанию",
|
||||
|
||||
@@ -230,6 +230,32 @@ def test_payment_provider_settings_include_webhook_metadata():
|
||||
assert "webhook_path" not in manifest["PAYMENT_STARS_WEBAPP_LABEL_RU"]
|
||||
|
||||
|
||||
def test_remnawave_settings_include_panel_webhook_metadata():
|
||||
manifest = _manifest_by_key()
|
||||
field = manifest["PANEL_WEBHOOK_SECRET"]
|
||||
remnawave_keys = (
|
||||
"PANEL_API_URL",
|
||||
"PANEL_API_KEY",
|
||||
"PANEL_WEBHOOK_SECRET",
|
||||
"USER_SQUAD_UUIDS",
|
||||
"USER_EXTERNAL_SQUAD_UUID",
|
||||
)
|
||||
|
||||
assert field["webhook_path"] == "/webhook/panel"
|
||||
assert field["webhook_requires_base_url"] is True
|
||||
assert field["provider_id"] == "remnawave"
|
||||
assert field["webhook_hint_i18n_key"] == "admin_settings_panel_webhook_url_hint"
|
||||
for setting_key in remnawave_keys:
|
||||
assert manifest[setting_key]["section"] == "remnawave"
|
||||
assert manifest[setting_key]["section_order"] == 3
|
||||
assert manifest[setting_key]["subsection"] is None
|
||||
|
||||
for language in ("ru", "en"):
|
||||
messages = _locale(language)
|
||||
assert "admin_settings_section_remnawave" in messages
|
||||
assert field["webhook_hint_i18n_key"] in messages
|
||||
|
||||
|
||||
def test_payment_provider_admin_only_toggles_are_mutually_exclusive():
|
||||
manifest = _manifest_by_key()
|
||||
|
||||
|
||||
@@ -760,10 +760,13 @@ class AdminSettingsSecurityTests(unittest.IsolatedAsyncioTestCase):
|
||||
response = await admin_api.admin_settings_get_route(request)
|
||||
|
||||
payload = json.loads(response.text)
|
||||
section_ids = [section["id"] for section in payload["sections"]]
|
||||
fields = {
|
||||
field["key"]: field for section in payload["sections"] for field in section["fields"]
|
||||
}
|
||||
|
||||
self.assertLess(section_ids.index("general"), section_ids.index("remnawave"))
|
||||
self.assertLess(section_ids.index("remnawave"), section_ids.index("payments"))
|
||||
self.assertEqual(
|
||||
fields["FREEKASSA_ENABLED"]["webhook_url"],
|
||||
"https://web.tnnl.cc/webhook/freekassa",
|
||||
@@ -773,6 +776,11 @@ class AdminSettingsSecurityTests(unittest.IsolatedAsyncioTestCase):
|
||||
fields["PAYMENT_PLATEGA_CRYPTO_WEBAPP_LABEL_RU"]["webhook_url"],
|
||||
"https://web.tnnl.cc/webhook/platega",
|
||||
)
|
||||
self.assertEqual(
|
||||
fields["PANEL_WEBHOOK_SECRET"]["webhook_url"],
|
||||
"https://web.tnnl.cc/webhook/panel",
|
||||
)
|
||||
self.assertTrue(fields["PANEL_WEBHOOK_SECRET"]["webhook_requires_base_url"])
|
||||
self.assertNotIn("webhook_url", fields["PAYMENT_STARS_WEBAPP_LABEL_RU"])
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user