mirror of
https://github.com/usmannasir/cyberpanel.git
synced 2026-05-07 03:57:14 +02:00
pluginHolder: auto-persist activation keys from plugin settings pages.
Inject a lightweight fetch hook into settings pages to call store-activation after successful plugin activation responses, reducing premium relock risk after upgrades.
This commit is contained in:
@@ -2106,7 +2106,8 @@ def plugin_settings_proxy(request, plugin_name):
|
||||
for candidate in ('settings', 'settings_view', 'settings_simple', 'unified_settings'):
|
||||
settings_view = getattr(views_mod, candidate, None)
|
||||
if callable(settings_view):
|
||||
return settings_view(request)
|
||||
response = settings_view(request)
|
||||
return _inject_activation_store_hook(response, plugin_name)
|
||||
except ModuleNotFoundError as e:
|
||||
last_err = str(e)
|
||||
continue
|
||||
@@ -2123,6 +2124,84 @@ def plugin_settings_proxy(request, plugin_name):
|
||||
return HttpResponseNotFound('Plugin not found.')
|
||||
|
||||
|
||||
def _inject_activation_store_hook(response, plugin_name):
|
||||
"""
|
||||
Tiny safety hook for plugin settings pages:
|
||||
if a plugin activation request succeeds client-side, persist the key in
|
||||
CyberPanel DB via /plugins/api/store-activation/<plugin>/.
|
||||
"""
|
||||
try:
|
||||
content_type = (response.get('Content-Type', '') or '').lower()
|
||||
if 'text/html' not in content_type:
|
||||
return response
|
||||
body = response.content.decode('utf-8', errors='ignore')
|
||||
hook_script = """
|
||||
<script>
|
||||
(function () {
|
||||
if (window.__cpActivationStoreHookInstalled) return;
|
||||
window.__cpActivationStoreHookInstalled = true;
|
||||
var pluginName = %s;
|
||||
function getCsrfToken() {
|
||||
var m = document.cookie.match(/(?:^|; )csrftoken=([^;]+)/);
|
||||
return m ? decodeURIComponent(m[1]) : '';
|
||||
}
|
||||
function tryParseBody(body) {
|
||||
if (!body || typeof body !== 'string') return '';
|
||||
try {
|
||||
var obj = JSON.parse(body);
|
||||
if (obj && typeof obj.activation_key === 'string') return obj.activation_key.trim();
|
||||
} catch (e) {}
|
||||
var rx = /activation_key\\s*[:=]\\s*["']?([A-Za-z0-9\\-_.]{6,})/i;
|
||||
var m = body.match(rx);
|
||||
return m ? m[1] : '';
|
||||
}
|
||||
async function persistActivationKey(activationKey) {
|
||||
if (!activationKey) return;
|
||||
try {
|
||||
await window.__cpOriginalFetch('/plugins/api/store-activation/' + encodeURIComponent(pluginName) + '/', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-CSRFToken': getCsrfToken()
|
||||
},
|
||||
body: JSON.stringify({ activation_key: activationKey })
|
||||
});
|
||||
} catch (e) {}
|
||||
}
|
||||
if (!window.fetch) return;
|
||||
window.__cpOriginalFetch = window.fetch.bind(window);
|
||||
window.fetch = async function(input, init) {
|
||||
var url = (typeof input === 'string') ? input : ((input && input.url) || '');
|
||||
var body = init && init.body ? String(init.body) : '';
|
||||
var activationKey = tryParseBody(body);
|
||||
var resp = await window.__cpOriginalFetch(input, init);
|
||||
try {
|
||||
var looksLikeActivation = /activate|activation|activate_key/i.test(url || '');
|
||||
if (!looksLikeActivation) return resp;
|
||||
var clone = resp.clone();
|
||||
var ct = (clone.headers.get('content-type') || '').toLowerCase();
|
||||
if (ct.indexOf('application/json') === -1) return resp;
|
||||
var data = await clone.json();
|
||||
var ok = !!(data && (data.has_access === true || data.status === 1 || data.success === true));
|
||||
if (ok && activationKey) {
|
||||
persistActivationKey(activationKey);
|
||||
}
|
||||
} catch (e) {}
|
||||
return resp;
|
||||
};
|
||||
})();
|
||||
</script>
|
||||
""" % json.dumps(plugin_name)
|
||||
if '</body>' in body:
|
||||
body = body.replace('</body>', hook_script + '</body>')
|
||||
else:
|
||||
body += hook_script
|
||||
response.content = body.encode('utf-8')
|
||||
return response
|
||||
except Exception:
|
||||
return response
|
||||
|
||||
|
||||
def plugin_help(request, plugin_name):
|
||||
"""Plugin-specific help page - shows plugin information, version history, and help content"""
|
||||
mailUtilities.checkHome()
|
||||
|
||||
Reference in New Issue
Block a user