feat(p2p): Auto-create mesh repository without modal parameters
Add autoCreateMeshRepo() function that automatically:
- Generates repo name from hostname: secubox-mesh-{hostname}
- Detects local Gitea server (gitea.local, git.local, etc.)
- Only prompts for access token on first use (one-time setup)
- Creates private repository with README
- Pushes initial mesh state immediately
Replace manual "➕ Create" button with "🚀 Auto Setup" for seamless
mesh repository initialization.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
5287a7b807
commit
f4c8f40b3e
@ -1197,9 +1197,9 @@ return view.extend({
|
||||
)
|
||||
]),
|
||||
E('div', { 'class': 'backup-card-actions' }, [
|
||||
E('button', { 'class': 'btn small primary', 'click': function() { self.createGiteaRepo(); } }, '➕ Create'),
|
||||
E('button', { 'class': 'btn small primary', 'click': function() { self.autoCreateMeshRepo(); } }, '🚀 Auto Setup'),
|
||||
E('button', { 'class': 'btn small', 'click': function() { self.fetchGiteaCommits(); } }, '🔄 Fetch'),
|
||||
E('button', { 'class': 'btn small', 'click': function() { self.showGiteaConfigModal(); } }, '⚙️ Setup'),
|
||||
E('button', { 'class': 'btn small', 'click': function() { self.showGiteaConfigModal(); } }, '⚙️ Config'),
|
||||
E('button', { 'class': 'btn small', 'click': function() { self.pushToGitea(); } }, '📤 Push')
|
||||
])
|
||||
])
|
||||
@ -1605,6 +1605,148 @@ return view.extend({
|
||||
ui.addNotification(null, E('p', 'Gitea History Feed ' + (enabled ? 'enabled' : 'disabled')), 'info');
|
||||
},
|
||||
|
||||
autoCreateMeshRepo: function() {
|
||||
var self = this;
|
||||
|
||||
// Get hostname for repo name
|
||||
var hostname = this.settings.node_name || 'secubox';
|
||||
var repoName = 'secubox-mesh-' + hostname.toLowerCase().replace(/[^a-z0-9-]/g, '-');
|
||||
var repoDesc = 'SecuBox P2P Mesh configuration and state backups for ' + hostname;
|
||||
|
||||
// Default Gitea servers to try (local first)
|
||||
var giteaServers = [
|
||||
'http://gitea.local:3000',
|
||||
'http://git.local:3000',
|
||||
'http://192.168.255.1:3000',
|
||||
'http://localhost:3000'
|
||||
];
|
||||
|
||||
// Use configured server if available, otherwise detect
|
||||
var serverUrl = this.giteaConfig.serverUrl;
|
||||
|
||||
if (!serverUrl) {
|
||||
ui.addNotification(null, E('p', '🔍 Detecting local Gitea server...'), 'info');
|
||||
|
||||
// Try to detect Gitea server
|
||||
var detectServer = function(servers, index) {
|
||||
if (index >= servers.length) {
|
||||
// No server found, prompt for manual config
|
||||
ui.addNotification(null, E('p', '⚠️ No Gitea server detected. Please configure manually.'), 'warning');
|
||||
self.showGiteaConfigModal();
|
||||
return;
|
||||
}
|
||||
|
||||
var testUrl = servers[index];
|
||||
// Simple detection - try to access Gitea API
|
||||
fetch(testUrl + '/api/v1/version', { method: 'GET', mode: 'no-cors' })
|
||||
.then(function() {
|
||||
// Server might be reachable, use it
|
||||
serverUrl = testUrl;
|
||||
self.proceedAutoCreate(serverUrl, repoName, repoDesc);
|
||||
})
|
||||
.catch(function() {
|
||||
detectServer(servers, index + 1);
|
||||
});
|
||||
};
|
||||
|
||||
detectServer(giteaServers, 0);
|
||||
} else {
|
||||
this.proceedAutoCreate(serverUrl, repoName, repoDesc);
|
||||
}
|
||||
},
|
||||
|
||||
proceedAutoCreate: function(serverUrl, repoName, repoDesc) {
|
||||
var self = this;
|
||||
|
||||
// Check if we have a token
|
||||
if (!this.giteaConfig.hasToken && !this.giteaConfig.token) {
|
||||
// Need token - show minimal prompt
|
||||
ui.showModal('Gitea Access Token Required', [
|
||||
E('div', { 'class': 'modal-form' }, [
|
||||
E('div', { 'class': 'deploy-modal-header' }, [
|
||||
E('span', { 'class': 'deploy-modal-icon' }, '🔑'),
|
||||
E('div', {}, [
|
||||
E('div', { 'class': 'deploy-modal-title' }, 'One-time Setup'),
|
||||
E('div', { 'class': 'deploy-modal-subtitle' }, 'Enter your Gitea access token to enable auto-backup')
|
||||
])
|
||||
]),
|
||||
E('div', { 'class': 'form-group' }, [
|
||||
E('label', {}, 'Gitea Server'),
|
||||
E('input', { 'type': 'text', 'id': 'auto-gitea-url', 'class': 'form-input', 'value': serverUrl })
|
||||
]),
|
||||
E('div', { 'class': 'form-group' }, [
|
||||
E('label', {}, 'Access Token'),
|
||||
E('input', { 'type': 'password', 'id': 'auto-gitea-token', 'class': 'form-input', 'placeholder': 'Paste your Gitea personal access token' }),
|
||||
E('small', { 'style': 'color: #666; margin-top: 4px; display: block;' }, 'Generate at: ' + serverUrl + '/user/settings/applications')
|
||||
])
|
||||
]),
|
||||
E('div', { 'class': 'modal-actions' }, [
|
||||
E('button', { 'class': 'cbi-button', 'click': ui.hideModal }, 'Cancel'),
|
||||
E('button', { 'class': 'cbi-button cbi-button-positive', 'click': function() {
|
||||
var finalUrl = document.getElementById('auto-gitea-url').value;
|
||||
var token = document.getElementById('auto-gitea-token').value;
|
||||
|
||||
if (!token) {
|
||||
ui.addNotification(null, E('p', 'Access token is required'), 'warning');
|
||||
return;
|
||||
}
|
||||
|
||||
ui.hideModal();
|
||||
self.executeAutoCreate(finalUrl, repoName, repoDesc, token);
|
||||
} }, '🚀 Create Repository')
|
||||
])
|
||||
]);
|
||||
} else {
|
||||
// Already have token, proceed
|
||||
this.executeAutoCreate(serverUrl, repoName, repoDesc, this.giteaConfig.token);
|
||||
}
|
||||
},
|
||||
|
||||
executeAutoCreate: function(serverUrl, repoName, repoDesc, token) {
|
||||
var self = this;
|
||||
|
||||
ui.addNotification(null, E('p', '🚀 Auto-creating mesh repository...'), 'info');
|
||||
|
||||
// Step 1: Save Gitea config
|
||||
P2PAPI.setGiteaConfig({
|
||||
server_url: serverUrl,
|
||||
repo_name: repoName,
|
||||
access_token: token,
|
||||
enabled: 1,
|
||||
auto_backup: 1,
|
||||
backup_on_change: 1
|
||||
}).then(function() {
|
||||
// Step 2: Create repository
|
||||
ui.addNotification(null, E('p', '📦 Creating repository: ' + repoName), 'info');
|
||||
return P2PAPI.createGiteaRepo(repoName, repoDesc, true, true);
|
||||
}).then(function(result) {
|
||||
if (result.success) {
|
||||
// Update local state
|
||||
self.giteaConfig.serverUrl = serverUrl;
|
||||
self.giteaConfig.repoName = result.repo_name || repoName;
|
||||
self.giteaConfig.repoOwner = result.owner || '';
|
||||
self.giteaConfig.enabled = true;
|
||||
self.giteaConfig.hasToken = true;
|
||||
self.giteaConfig.lastFetch = Date.now();
|
||||
|
||||
ui.addNotification(null, E('p', '✅ Repository created: ' + self.giteaConfig.repoOwner + '/' + self.giteaConfig.repoName), 'success');
|
||||
|
||||
// Step 3: Push initial state
|
||||
ui.addNotification(null, E('p', '📤 Pushing initial mesh state...'), 'info');
|
||||
return P2PAPI.pushGiteaBackup('Initial SecuBox mesh configuration', {});
|
||||
} else {
|
||||
throw new Error(result.error || 'Failed to create repository');
|
||||
}
|
||||
}).then(function(pushResult) {
|
||||
if (pushResult && pushResult.success) {
|
||||
ui.addNotification(null, E('p', '🎉 Mesh repository ready! ' + pushResult.files_pushed + ' files uploaded'), 'success');
|
||||
self.refreshGiteaCommits();
|
||||
}
|
||||
}).catch(function(err) {
|
||||
ui.addNotification(null, E('p', '❌ Auto-setup failed: ' + err.message), 'error');
|
||||
});
|
||||
},
|
||||
|
||||
fetchGiteaCommits: function() {
|
||||
var self = this;
|
||||
if (!this.giteaConfig.enabled) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user