mirror of
https://github.com/yogeshojha/rengine.git
synced 2026-10-18 14:27:17 +02:00
Settings has six tabs: General, API keys, Proxies, Notifications, AI and Users. Each tab is one card whose controls save on change; list tabs are tables with a row menu and their Add action in the tab row. A non-admin sees General and AI, read-only. Out-of-band testing is the Callback server sheet on the Arsenal Nuclei tab, with a Need a callback count that filters the library to the same rows. Bounty Hub settings are a sheet on the Bounty Hub page. The old settings routes redirect to both. - API keys store the last test result on the row and clear it when the key changes. Providers report whether a test exists. The usage count is gone: only ViewDNS ever incremented it. - Notification channels store the last delivery, written by the notifier on its own connection. A channel offers the seven event types the product emits, program changes on by default, and levels named All events, Warning and critical, Critical only. - A default proxy applies to a scan launched without a context and is preselected for new contexts. A pool hands each scan one endpoint, proxy URLs bracket IPv6 hosts, and deleting a proxy clears it from its contexts. - Users can be added with a role, disabled and promoted. An account cannot change itself, and one that owns records answers 409. - Retention windows are validated and include keep forever. The instance name cannot be blank and names every page title. - The AI list drops the two switches nothing read; each feature states what it sends. The out-of-band Off help says the checks are skipped. Connectors, Bounty Hub and Remote control lose their extra page padding. Migration 5d2e9a8c1b47 adds the test and delivery columns and drops proxies.mode. Claude-Session: https://claude.ai/code/session_01RVAHQxZ7JAkoEiTCDiHYue
154 lines
5.1 KiB
Python
154 lines
5.1 KiB
Python
import uuid
|
|
from datetime import datetime
|
|
|
|
from pydantic import BaseModel
|
|
from sqlalchemy import Column
|
|
from sqlalchemy.types import JSON
|
|
from sqlmodel import Field, SQLModel, UniqueConstraint
|
|
|
|
from shared.enums.api_key import APIProvider, ProviderGroup
|
|
from shared.utils.datetime import utc_now
|
|
|
|
API_PROVIDER_META: dict[str, dict] = {
|
|
APIProvider.VIEWDNS: {
|
|
"group": ProviderGroup.LOOKUPS.value,
|
|
"name": "ViewDNS.info",
|
|
"description": "DNS intelligence, reverse lookups and DNS history",
|
|
"docs_url": "https://viewdns.info/api/?src=reNgine",
|
|
"requires_username": False,
|
|
"icon": "scan-search",
|
|
},
|
|
APIProvider.GITHUB: {
|
|
"group": ProviderGroup.SUBDOMAINS.value,
|
|
"name": "GitHub",
|
|
"description": "Subdomains found in public code, and subfinder's GitHub source",
|
|
"docs_url": "https://github.com/settings/tokens",
|
|
"requires_username": False,
|
|
"icon": "github",
|
|
},
|
|
APIProvider.CHAOS: {
|
|
"group": ProviderGroup.SUBDOMAINS.value,
|
|
"name": "Chaos",
|
|
"description": "ProjectDiscovery Chaos subdomain dataset",
|
|
"docs_url": "https://cloud.projectdiscovery.io",
|
|
"requires_username": False,
|
|
"icon": "radar",
|
|
},
|
|
APIProvider.NETLAS: {
|
|
"group": ProviderGroup.SUBDOMAINS.value,
|
|
"name": "Netlas",
|
|
"description": "Internet-wide asset and attack-surface intelligence",
|
|
"docs_url": "https://netlas.io",
|
|
"requires_username": False,
|
|
"icon": "globe",
|
|
},
|
|
APIProvider.SECURITYTRAILS: {
|
|
"group": ProviderGroup.SUBDOMAINS.value,
|
|
"name": "SecurityTrails",
|
|
"description": "DNS, domain and subdomain history intelligence",
|
|
"docs_url": "https://securitytrails.com",
|
|
"requires_username": False,
|
|
"icon": "route",
|
|
},
|
|
APIProvider.HACKERONE: {
|
|
"group": ProviderGroup.BOUNTY_PLATFORMS.value,
|
|
"name": "HackerOne",
|
|
"description": "Program scope and reports from HackerOne",
|
|
"docs_url": "https://api.hackerone.com",
|
|
"requires_username": True,
|
|
"icon": "shield",
|
|
},
|
|
APIProvider.INTIGRITI: {
|
|
"group": ProviderGroup.BOUNTY_PLATFORMS.value,
|
|
"name": "Intigriti",
|
|
"description": "Program scope from Intigriti, including invite-only programs",
|
|
"docs_url": "https://app.intigriti.com/researcher/personal-access-tokens",
|
|
"requires_username": False,
|
|
"icon": "shield",
|
|
},
|
|
APIProvider.VULNX: {
|
|
"group": ProviderGroup.EXPLOIT_INTEL.value,
|
|
"name": "vulnx",
|
|
"description": "ProjectDiscovery vulnerability intelligence: exploits, coverage and exposure",
|
|
"docs_url": "https://cloud.projectdiscovery.io",
|
|
"requires_username": False,
|
|
"icon": "biohazard",
|
|
},
|
|
APIProvider.INTERACTSH: {
|
|
"group": ProviderGroup.OAST.value,
|
|
"name": "Interactsh",
|
|
"description": "Auth token for a self-hosted out-of-band callback server",
|
|
"docs_url": "https://github.com/projectdiscovery/interactsh",
|
|
"requires_username": False,
|
|
"icon": "satellite-dish",
|
|
},
|
|
APIProvider.TELEGRAM: {
|
|
"group": ProviderGroup.CHAT.value,
|
|
"name": "Telegram",
|
|
"description": "Bot token for remote control and notifications",
|
|
"docs_url": "https://core.telegram.org/bots#how-do-i-create-a-bot",
|
|
"requires_username": False,
|
|
"icon": "send",
|
|
},
|
|
}
|
|
|
|
|
|
class APIKey(SQLModel, table=True):
|
|
__tablename__ = "api_keys"
|
|
__table_args__ = (UniqueConstraint("provider", name="uq_api_key_provider"),)
|
|
|
|
id: uuid.UUID = Field(default_factory=uuid.uuid4, primary_key=True)
|
|
provider: APIProvider = Field(index=True)
|
|
key_value: str = Field(max_length=1000)
|
|
key_meta: dict | None = Field(default=None, sa_column=Column(JSON, nullable=True))
|
|
is_enabled: bool = Field(default=True)
|
|
usage_counter: int = Field(default=0)
|
|
last_used_at: datetime | None = Field(default=None)
|
|
last_test_at: datetime | None = Field(default=None)
|
|
last_test_ok: bool | None = Field(default=None)
|
|
last_test_message: str | None = Field(default=None, max_length=500)
|
|
created_at: datetime = Field(default_factory=utc_now)
|
|
updated_at: datetime = Field(default_factory=utc_now)
|
|
|
|
|
|
class APIKeyCreate(BaseModel):
|
|
provider: APIProvider
|
|
key_value: str
|
|
key_meta: dict | None = None
|
|
|
|
|
|
class APIKeyUpdate(BaseModel):
|
|
key_value: str | None = None
|
|
is_enabled: bool | None = None
|
|
key_meta: dict | None = None
|
|
|
|
|
|
class APIKeyRead(BaseModel):
|
|
id: uuid.UUID
|
|
provider: APIProvider
|
|
key_value_masked: str
|
|
key_meta: dict | None = None
|
|
is_enabled: bool
|
|
usage_counter: int
|
|
last_used_at: datetime | None
|
|
last_test_at: datetime | None = None
|
|
last_test_ok: bool | None = None
|
|
last_test_message: str | None = None
|
|
created_at: datetime
|
|
updated_at: datetime
|
|
meta: dict
|
|
|
|
|
|
class ProviderInfo(BaseModel):
|
|
provider: APIProvider
|
|
name: str
|
|
description: str
|
|
docs_url: str
|
|
icon: str = "package"
|
|
requires_username: bool = False
|
|
group: str
|
|
group_label: str
|
|
configured: bool = False
|
|
is_enabled: bool = False
|
|
testable: bool = False
|