docs: add project documentation and update README

- Add `agent.md`: Complete maintenance reference covering project structure, API interactions, data flow, configuration, security, and operational procedures.
- Add `architecture.md`: High-level architecture overview including component map, data flow, design decisions, and security model.
- Update `README.md`: Add Apprise support documentation, manual deployment instructions, updated installation steps (bot admin requirement), and expanded payload mapping and troubleshooting sections.
- Improve `lib/Controller/WebhookController.php`: Enhance `saveBotPassword` validation to check for missing fields and validate the password content.
- Improve `lib/Service/TalkService.php`: Add `validateBotPassword` method for round-trip encryption testing and integrate it into `saveConfig`.
- Update `css/adminSettings.css`: Add styles for the new `.nc-app-frame` wrapper.
- Update `templates/adminSettings.php`: Refactor UI structure to use `.nc-app-frame` and improve layout of settings sections.
This commit is contained in:
kyle
2026-06-12 19:44:42 -07:00
parent 19241c842d
commit 18084d0f69
7 changed files with 1853 additions and 112 deletions
+10 -2
View File
@@ -319,9 +319,17 @@ class WebhookController extends Controller {
public function saveBotPassword(): DataResponse {
$body = file_get_contents('php://input');
$data = @json_decode($body, true);
if (!is_array($data) || empty($data['bot_password'])) {
if (!is_array($data) || !isset($data['bot_password'])) {
return new DataResponse(
['error' => 'Invalid data'],
['error' => 'Missing bot_password field'],
Http::STATUS_BAD_REQUEST,
);
}
$validation = $this->talkService->validateBotPassword($data['bot_password']);
if (!$validation['valid']) {
return new DataResponse(
['error' => $validation['error']],
Http::STATUS_BAD_REQUEST,
);
}
+25
View File
@@ -79,6 +79,27 @@ class TalkService {
}
}
/**
* Validate a bot password by encrypting and decrypting it (round-trip test).
* Returns ['valid' => true] on success, or ['valid' => false, 'error' => '...'] on failure.
*/
public function validateBotPassword(string $password): array {
if ($password === '') {
return ['valid' => false, 'error' => 'Bot password cannot be empty.'];
}
try {
$encrypted = $this->crypto->encrypt($password);
$decrypted = $this->crypto->decrypt($encrypted);
if ($decrypted !== $password) {
return ['valid' => false, 'error' => 'Password encryption/decryption failed. The password may contain unsupported characters.'];
}
return ['valid' => true];
} catch (\Exception $e) {
return ['valid' => false, 'error' => 'Password encryption failed: ' . $e->getMessage()];
}
}
public function setBotPassword(string $password): void {
$this->config->setAppValue(self::APP_ID, 'bot_password', $this->crypto->encrypt($password));
}
@@ -1078,6 +1099,10 @@ class TalkService {
*/
public function saveConfig(array $config): void {
if (isset($config['bot_password']) && $config['bot_password'] !== '') {
$validation = $this->validateBotPassword($config['bot_password']);
if (!$validation['valid']) {
throw new \Exception($validation['error']);
}
$this->setBotPassword($config['bot_password']);
}