65c3f099fa
Adds complete app password provisioning workflow for multi-user BasicAuth
deployments, allowing users to independently enable background sync by
generating and storing Nextcloud app passwords.
**New Components:**
Backend (PHP):
- CredentialsController: Validates and stores app passwords
* Validates app password format and authenticity via OCS API
* Stores encrypted passwords in oc_preferences
* Provides status and credential management endpoints
- AstrolabeAdminSettings: Admin configuration page for MCP server URL
- AstrolabeAdminSettingsListener: Event listener for admin section
- Updated McpTokenStorage: Added background sync credential methods
Frontend:
- personalSettings.js: Form handling for app password entry
* AJAX submission with error handling
* Shows success/error notifications
* Triggers page reload after successful save
- settings.css: Styling for settings pages
- Updated personal.php template: Two-option UI
* Option 1: OAuth refresh token (future, not yet available)
* Option 2: App password (works today, recommended)
* Shows "Active" badge when provisioned
* Displays credential type and provisioned timestamp
Routes:
- POST /api/v1/background-sync/credentials - Store app password
- GET /api/v1/background-sync/status - Get provisioning status
- DELETE /api/v1/background-sync/credentials - Revoke credentials
- GET /api/v1/background-sync/credentials/{userId} - Admin only
**Testing:**
- test_astrolabe_settings_buttons.py: Integration test for UI buttons
**Workflow:**
1. User generates app password in Nextcloud Security settings
2. User navigates to Astrolabe personal settings
3. User enters app password in "Option 2: App Password" form
4. Backend validates password via OCS API call
5. Password stored encrypted in oc_preferences
6. Page reloads showing "Active" badge with credential details
7. MCP server can now use stored password for background operations
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
65 lines
2.1 KiB
PHP
65 lines
2.1 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace OCA\Astrolabe\Settings;
|
|
|
|
use OCP\IL10N;
|
|
use OCP\Settings\DeclarativeSettingsTypes;
|
|
use OCP\Settings\IDeclarativeSettingsForm;
|
|
|
|
class AstrolabeAdminSettings implements IDeclarativeSettingsForm {
|
|
public function __construct(
|
|
private IL10N $l,
|
|
) {
|
|
}
|
|
|
|
public function getSchema(): array {
|
|
return [
|
|
'id' => 'astrolabe-admin-settings',
|
|
'priority' => 10,
|
|
'section_type' => DeclarativeSettingsTypes::SECTION_TYPE_ADMIN,
|
|
'section_id' => 'astrolabe',
|
|
'storage_type' => DeclarativeSettingsTypes::STORAGE_TYPE_EXTERNAL,
|
|
'title' => $this->l->t('MCP Server Configuration'),
|
|
'description' => $this->l->t('Configure the connection to your Nextcloud MCP Server'),
|
|
'doc_url' => 'https://github.com/cbcoutinho/nextcloud-mcp-server',
|
|
|
|
'fields' => [
|
|
[
|
|
'id' => 'mcp_server_url',
|
|
'title' => $this->l->t('MCP Server URL'),
|
|
'description' => $this->l->t('The base URL of your Nextcloud MCP Server instance (e.g., http://localhost:8000)'),
|
|
'type' => DeclarativeSettingsTypes::URL,
|
|
'placeholder' => 'http://localhost:8000',
|
|
'default' => '',
|
|
],
|
|
[
|
|
'id' => 'mcp_server_api_key',
|
|
'title' => $this->l->t('API Key'),
|
|
'description' => $this->l->t('Authentication key for the MCP server (leave empty if not required)'),
|
|
'type' => DeclarativeSettingsTypes::PASSWORD,
|
|
'placeholder' => $this->l->t('Enter API key'),
|
|
'default' => '',
|
|
],
|
|
[
|
|
'id' => 'astrolabe_client_id',
|
|
'title' => $this->l->t('OAuth Client ID'),
|
|
'description' => $this->l->t('The OAuth client ID for Astrolabe (required for multi-user deployments)'),
|
|
'type' => DeclarativeSettingsTypes::TEXT,
|
|
'placeholder' => $this->l->t('Enter OAuth client ID'),
|
|
'default' => '',
|
|
],
|
|
[
|
|
'id' => 'astrolabe_client_secret',
|
|
'title' => $this->l->t('OAuth Client Secret'),
|
|
'description' => $this->l->t('Optional: Client secret for OAuth. If not set, PKCE will be used as fallback.'),
|
|
'type' => DeclarativeSettingsTypes::PASSWORD,
|
|
'placeholder' => $this->l->t('Enter client secret (optional)'),
|
|
'default' => '',
|
|
],
|
|
],
|
|
];
|
|
}
|
|
}
|