Removed initial software_upgrade

This commit is contained in:
“VeLiTi”
2025-12-12 10:54:45 +01:00
parent c39a5ca648
commit 2b42013e23
19 changed files with 53 additions and 2132 deletions

View File

@@ -1,350 +0,0 @@
// Software Upgrade System - Frontend Functions
// Requires: jQuery or modern fetch API
class UpgradeManager {
constructor(apiBase = '/api.php') {
this.apiBase = apiBase;
this.serviceToken = '';
this.init();
}
init() {
// Get service token from DOM if available
const tokenElement = document.getElementById('servicetoken');
if (tokenElement) {
this.serviceToken = tokenElement.innerHTML || '';
}
}
async makeAPICall(endpoint, method = 'GET', data = null) {
const url = this.apiBase + endpoint;
const bearer = 'Bearer ' + this.serviceToken;
const options = {
method: method,
headers: {
'Authorization': bearer,
'Content-Type': 'application/json'
},
credentials: 'include'
};
if (data && (method === 'POST' || method === 'PUT')) {
options.body = JSON.stringify(data);
}
const response = await fetch(url, options);
if (!response.ok) {
const errorData = await response.json().catch(() => ({ error: 'Network error' }));
throw new Error(errorData.error || `HTTP ${response.status}`);
}
return await response.json();
}
async getAvailableVersions() {
try {
const data = await this.makeAPICall('/v2/get/software?available');
return data;
} catch (error) {
console.error('Error fetching available versions:', error);
throw error;
}
}
async downloadVersion(versionId, onProgress = null) {
try {
// Step 1: Request download token
const downloadRequest = await this.makeAPICall('/v2/post/software', 'POST', {
action: 'download',
version_id: parseInt(versionId)
});
if (!downloadRequest.download_url) {
throw new Error('No download URL received');
}
// Step 2: Download file using temporary URL
await this.downloadFile(downloadRequest.download_url, onProgress);
} catch (error) {
console.error('Download error:', error);
throw error;
}
}
async downloadFile(url, onProgress) {
const response = await fetch(url, {
credentials: 'include'
});
if (!response.ok) {
throw new Error('Download failed');
}
const contentLength = response.headers.get('Content-Length');
const total = parseInt(contentLength, 10);
let loaded = 0;
const reader = response.body.getReader();
const chunks = [];
while (true) {
const { done, value } = await reader.read();
if (done) break;
chunks.push(value);
loaded += value.length;
if (onProgress && total) {
onProgress(loaded, total);
}
}
// Create blob from chunks
const blob = new Blob(chunks);
// Trigger download
const downloadUrl = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = downloadUrl;
a.download = 'software_upgrade.zip'; // Filename will be set by server
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(downloadUrl);
document.body.removeChild(a);
}
async purchaseVersion(versionId, transactionId = null) {
try {
const purchaseData = {
action: 'purchase',
version_id: parseInt(versionId)
};
if (transactionId) {
purchaseData.transaction_id = transactionId;
}
const result = await this.makeAPICall('/v2/post/software', 'POST', purchaseData);
return result;
} catch (error) {
console.error('Purchase error:', error);
throw error;
}
}
formatBytes(bytes) {
if (bytes === 0) return '0 Bytes';
const k = 1024;
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return Math.round(bytes / Math.pow(k, i) * 100) / 100 + ' ' + sizes[i];
}
formatPrice(price, currency = 'USD') {
return new Intl.NumberFormat('en-US', {
style: 'currency',
currency: currency
}).format(price);
}
}
// Global upgrade manager instance
let upgradeManager;
// Initialize upgrade system
function initUpgradeSystem() {
upgradeManager = new UpgradeManager();
}
// Display upgrade options in UI
async function showUpgradeOptions(containerId = 'upgrade-container') {
const container = document.getElementById(containerId);
if (!container) {
console.error('Container element not found:', containerId);
return;
}
try {
const data = await upgradeManager.getAvailableVersions();
container.innerHTML = '';
// Show current version info
if (data.current_version) {
const currentDiv = document.createElement('div');
currentDiv.className = 'current-version-info';
currentDiv.innerHTML = `
<h3>Your Current Version: ${data.current_version}</h3>
<p>Owned versions: ${data.owned_versions.map(v => v.version).join(', ')}</p>
`;
container.appendChild(currentDiv);
}
// Show available versions
if (data.available_versions && data.available_versions.length > 0) {
const versionsDiv = document.createElement('div');
versionsDiv.className = 'available-versions';
data.available_versions.forEach(version => {
const versionCard = document.createElement('div');
versionCard.className = 'version-card';
versionCard.dataset.versionId = version.id;
let buttonHTML = '';
let priceHTML = '';
let statusHTML = '';
if (version.is_accessible) {
statusHTML = '<span class="badge owned">Owned</span>';
buttonHTML = `<button onclick="downloadVersion(${version.id})" class="download-btn">Download</button>`;
} else if (version.requires_payment) {
if (version.is_upgrade) {
priceHTML = `
<div class="price-info">
<span class="upgrade-price">${upgradeManager.formatPrice(version.price)}</span>
<span class="original-price">${upgradeManager.formatPrice(version.original_price)}</span>
<span class="upgrade-label">Upgrade from v${version.upgrade_from}</span>
</div>
`;
} else {
priceHTML = `<div class="price-info">${upgradeManager.formatPrice(version.price)}</div>`;
}
buttonHTML = `<button onclick="purchaseVersion(${version.id}, ${version.price})" class="purchase-btn">Purchase</button>`;
} else if (version.access_reason === 'requires_base_version') {
statusHTML = `<span class="badge locked">Requires v${version.required_version}</span>`;
buttonHTML = `<button disabled class="locked-btn">Requires v${version.required_version}</button>`;
}
versionCard.innerHTML = `
<div class="version-header">
<h4>${version.name} ${statusHTML}</h4>
<span class="version-number">v${version.version}</span>
</div>
<div class="version-description">${version.description}</div>
<div class="version-meta">
<span class="file-size">Size: ${upgradeManager.formatBytes(version.file_size)}</span>
<span class="release-date">Released: ${new Date(version.release_date).toLocaleDateString()}</span>
</div>
${priceHTML}
<div class="version-actions">
${buttonHTML}
</div>
`;
versionsDiv.appendChild(versionCard);
});
container.appendChild(versionsDiv);
} else {
container.innerHTML = '<p>No software versions available at this time.</p>';
}
} catch (error) {
container.innerHTML = `<div class="error-message">Error loading upgrades: ${error.message}</div>`;
console.error('Error showing upgrade options:', error);
}
}
// Download version with progress
async function downloadVersion(versionId) {
const button = event.target;
const originalText = button.innerHTML;
try {
button.disabled = true;
button.innerHTML = 'Preparing Download...';
// Create progress indicator
const progressContainer = document.createElement('div');
progressContainer.className = 'download-progress';
progressContainer.innerHTML = `
<div class="progress-bar">
<div class="progress-fill" style="width: 0%"></div>
</div>
<div class="progress-text">0%</div>
`;
button.parentNode.appendChild(progressContainer);
const progressFill = progressContainer.querySelector('.progress-fill');
const progressText = progressContainer.querySelector('.progress-text');
await upgradeManager.downloadVersion(versionId, (loaded, total) => {
const percent = Math.round((loaded / total) * 100);
progressFill.style.width = percent + '%';
progressText.textContent = percent + '%';
});
button.innerHTML = 'Download Complete!';
progressText.textContent = 'Complete';
// Remove progress after a delay
setTimeout(() => {
progressContainer.remove();
button.innerHTML = originalText;
button.disabled = false;
}, 3000);
} catch (error) {
button.innerHTML = 'Download Failed';
button.disabled = false;
alert('Download failed: ' + error.message);
// Remove progress on error
const progressContainer = button.parentNode.querySelector('.download-progress');
if (progressContainer) {
progressContainer.remove();
}
}
}
// Purchase version
async function purchaseVersion(versionId, price) {
const button = event.target;
const originalText = button.innerHTML;
const confirmed = confirm(`Purchase this software version for ${upgradeManager.formatPrice(price)}?`);
if (!confirmed) return;
try {
button.disabled = true;
button.innerHTML = 'Processing Purchase...';
// Here you would integrate with your payment processor
// For now, we'll simulate with a transaction ID
const transactionId = 'txn_' + Date.now();
const result = await upgradeManager.purchaseVersion(versionId, transactionId);
if (result.success) {
button.innerHTML = 'Purchase Successful!';
button.className = 'success-btn';
// Refresh the upgrade options
setTimeout(() => {
showUpgradeOptions();
}, 2000);
} else {
throw new Error(result.error || 'Purchase failed');
}
} catch (error) {
button.innerHTML = 'Purchase Failed';
button.disabled = false;
alert('Purchase failed: ' + error.message);
}
}
// Initialize when DOM is ready
document.addEventListener('DOMContentLoaded', function() {
initUpgradeSystem();
});
// Export for module usage (optional)
if (typeof module !== 'undefined' && module.exports) {
module.exports = { UpgradeManager, upgradeManager };
}

View File

@@ -1016,21 +1016,64 @@ function getProfile($profile, $permission){
//Include settingsa
include dirname(__FILE__,2).'/settings/settings_redirector.php';
// Always allowed collections: [collection => allowed_actions_string]
$always_allowed = [
'com_log' => 'U'
];
// Group permissions: [granting_page => [collection => allowed_actions_string]]
$group_permissions = [
'upgrades' => [
'software_downloads' => 'RU',
'software' => 'RU',
'upgrade_paths' => 'RU',
'user_licenses' => 'RU',
'version_access_rules' => 'RU',
'download_logs' => 'RU',
'download_tokens' => 'RU'
]
];
// Debug log
debuglog("isAllowed called: page=$page, profile=$profile, permission=$permission, action=$action");
// 1. Check always allowed
if (isset($always_allowed[$page]) && str_contains($always_allowed[$page], $action)) {
debuglog("Allowed by always_allowed");
return 1;
}
//GET ALLOWED ACTIONS
$user_permission = ${'permission_'.$permission};
//CHECK ALLOWED
$page_action = str_contains($user_permission,$action) > 0 ? 1 : 0; //CHECK IF USER IS ALLOWED TODO THE ACTION
$page_action = str_contains($user_permission,$action) > 0 ? 1 : 0; //CHECK IF USER IS ALLOWED TO DO THE ACTION
$page_access = str_contains($profile,$page) > 0 ? 1 : 0; //CHECK USER IS ALLOWED TO ACCESS PAGE
//RETURN CODE
debuglog("user_permission=$user_permission, page_action=$page_action, page_access=$page_access");
// 2. Check user permissions (standard)
if ($page_access == 1 && $page_action == 1){
$user_access = 1;
} else {
//Not Allowed
$user_access = 0;
debuglog("Allowed by user permissions");
return 1;
}
return $user_access;
// 3. If not allowed by user, check group permissions
if ($page_access == 0) {
foreach ($group_permissions as $granting_page => $grants) {
if (str_contains($profile, $granting_page)) {
debuglog("Found granting_page: $granting_page");
if (isset($grants[$page]) && str_contains($grants[$page], $action)) {
debuglog("Allowed by group permissions");
return 1;
}
}
}
}
debuglog("Not allowed");
// Not allowed
return 0;
}