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>
118 lines
3.6 KiB
PHP
118 lines
3.6 KiB
PHP
<?php
|
|
/**
|
|
* OAuth authorization required template.
|
|
*
|
|
* Shown when user needs to authorize Astrolabe for semantic search.
|
|
* Implements OAuth 2.0 Authorization Code flow with PKCE.
|
|
*
|
|
* @var array $_ Template parameters
|
|
* @var string $_['oauth_url'] URL to initiate OAuth flow
|
|
* @var string $_['server_url'] Astrolabe service URL
|
|
* @var bool $_['has_expired'] Whether token exists but is expired
|
|
* @var string|null $_['error_message'] Optional error message to display
|
|
*/
|
|
|
|
use OCP\Util;
|
|
|
|
Util::addStyle('astrolabe', 'astrolabe-personalSettings');
|
|
?>
|
|
|
|
<div class="section">
|
|
<h2><?php p($l->t('Astrolabe')); ?></h2>
|
|
<p><?php p($l->t('AI-powered semantic search across your Nextcloud content.')); ?></p>
|
|
</div>
|
|
|
|
<?php if (isset($_['error_message'])): ?>
|
|
<div class="section">
|
|
<h2><?php p($l->t('Session Expired')); ?></h2>
|
|
<p><?php p($_['error_message']); ?></p>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<div class="section">
|
|
<h2><?php p($l->t('Enable Semantic Search')); ?></h2>
|
|
|
|
<?php if (isset($_['has_expired']) && $_['has_expired']): ?>
|
|
<p>
|
|
<?php p($l->t('Your authorization has expired. Please sign in again to continue using semantic search.')); ?>
|
|
</p>
|
|
<?php else: ?>
|
|
<p>
|
|
<?php p($l->t('To search your content by meaning, Astrolabe needs permission to index your Nextcloud data.')); ?>
|
|
</p>
|
|
<?php endif; ?>
|
|
|
|
<p>
|
|
<strong><?php p($l->t('What happens next?')); ?></strong>
|
|
</p>
|
|
|
|
<ol class="mcp-help-text">
|
|
<li><?php p($l->t('Sign in to confirm your identity')); ?></li>
|
|
<li><?php p($l->t('Grant permission to index your content')); ?></li>
|
|
<li><?php p($l->t('Your content will be indexed for semantic search')); ?></li>
|
|
<li><?php p($l->t('Start searching with natural language')); ?></li>
|
|
</ol>
|
|
|
|
<h4><?php p($l->t('Content to be Indexed')); ?></h4>
|
|
|
|
<ul class="mcp-feature-list">
|
|
<li>
|
|
<span class="icon icon-files"></span>
|
|
<div>
|
|
<strong><?php p($l->t('Notes & Files')); ?></strong>
|
|
<p><?php p($l->t('Your notes and documents will be searchable by meaning')); ?></p>
|
|
</div>
|
|
</li>
|
|
<li>
|
|
<span class="icon icon-calendar"></span>
|
|
<div>
|
|
<strong><?php p($l->t('Calendar & Tasks')); ?></strong>
|
|
<p><?php p($l->t('Find events and tasks with natural language queries')); ?></p>
|
|
</div>
|
|
</li>
|
|
<li>
|
|
<span class="icon icon-category-dashboard"></span>
|
|
<div>
|
|
<strong><?php p($l->t('Deck Cards')); ?></strong>
|
|
<p><?php p($l->t('Search across your Deck boards and cards')); ?></p>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
|
|
<div style="margin-top: 20px;">
|
|
<a href="<?php p($_['oauth_url']); ?>" class="button primary">
|
|
<span class="icon icon-play"></span>
|
|
<?php if (isset($_['has_expired']) && $_['has_expired']): ?>
|
|
<?php p($l->t('Sign In Again')); ?>
|
|
<?php else: ?>
|
|
<?php p($l->t('Enable Semantic Search')); ?>
|
|
<?php endif; ?>
|
|
</a>
|
|
</div>
|
|
|
|
<p>
|
|
<?php p($l->t('You can disable indexing at any time from this settings page.')); ?>
|
|
</p>
|
|
</div>
|
|
|
|
<div class="section">
|
|
<h2><?php p($l->t('About Astrolabe')); ?></h2>
|
|
|
|
<p>
|
|
<?php p($l->t('Astrolabe enables semantic search - finding content by meaning rather than exact keywords. Ask questions like "meeting notes from last week" or "recipes with chicken" to find relevant documents.')); ?>
|
|
</p>
|
|
|
|
<p class="mcp-help-text">
|
|
<?php p($l->t('Your content is processed to understand its meaning, enabling powerful natural language search across all your Nextcloud data.')); ?>
|
|
</p>
|
|
|
|
<ul class="mcp-links">
|
|
<li>
|
|
<a href="https://github.com/cbcoutinho/nextcloud-mcp-server" target="_blank" rel="noopener noreferrer">
|
|
<span class="icon icon-external"></span>
|
|
<?php p($l->t('Learn More')); ?>
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</div>
|