software packages and deploying
This commit is contained in:
Executable
+147
@@ -0,0 +1,147 @@
|
||||
{% extends 'base.html' %}
|
||||
{% block content %}
|
||||
<div class="toolbar setup-analyzer-toolbar">
|
||||
<div>
|
||||
<h1>{{ t('setup_analyzer.title') }}</h1>
|
||||
<p class="muted">{{ t('setup_analyzer.subtitle') }}</p>
|
||||
</div>
|
||||
<div class="setup-analyzer-actions">
|
||||
<a class="button button-secondary" href="/software/packages">{{ t('software_packages.title') }}</a>
|
||||
<a class="button button-secondary" href="/software">{{ t('setup_analyzer.back_to_software') }}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<section class="panel setup-analyzer-upload-panel">
|
||||
<h2>{{ t('setup_analyzer.upload_title') }}</h2>
|
||||
<p>{{ t('setup_analyzer.static_note') }}</p>
|
||||
<form class="setup-analyzer-form" method="post" action="/software/setup-analyzer/analyze" enctype="multipart/form-data">
|
||||
<label for="installer">{{ t('setup_analyzer.file') }}
|
||||
<input id="installer" name="installer" type="file" accept=".exe,.msi,.msp,.msix,.appx,.msu" required>
|
||||
</label>
|
||||
<p class="muted">{{ t('setup_analyzer.max_upload', size=max_upload_mb) }}</p>
|
||||
<button class="button" type="submit">{{ t('setup_analyzer.analyze') }}</button>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
{% if analysis %}
|
||||
<div class="setup-analyzer-grid">
|
||||
<section class="panel setup-analyzer-card">
|
||||
<h2>{{ t('setup_analyzer.file_info') }}</h2>
|
||||
<dl class="setup-analyzer-details">
|
||||
<dt>{{ t('setup_analyzer.file') }}</dt><dd>{{ analysis.filename }}</dd>
|
||||
<dt>{{ t('setup_analyzer.size') }}</dt><dd>{{ analysis.size_human }}</dd>
|
||||
<dt>SHA256</dt><dd><code>{{ analysis.sha256 }}</code></dd>
|
||||
<dt>{{ t('setup_analyzer.signature') }}</dt>
|
||||
<dd>{% if analysis.signature_present is sameas true %}{{ t('setup_analyzer.signature_present') }}{% elif analysis.signature_present is sameas false %}{{ t('setup_analyzer.signature_absent') }}{% else %}{{ t('setup_analyzer.not_available') }}{% endif %}</dd>
|
||||
</dl>
|
||||
</section>
|
||||
|
||||
<section class="panel setup-analyzer-card">
|
||||
<h2>{{ t('setup_analyzer.detection') }}</h2>
|
||||
<dl class="setup-analyzer-details">
|
||||
<dt>{{ t('setup_analyzer.technology') }}</dt><dd><strong>{{ analysis.installer_label }}</strong></dd>
|
||||
<dt>{{ t('setup_analyzer.confidence') }}</dt><dd>{{ analysis.confidence }} %</dd>
|
||||
<dt>{{ t('setup_analyzer.command_confidence') }}</dt><dd>{{ t('setup_analyzer.command_confidence.' ~ analysis.command_confidence) }}</dd>
|
||||
</dl>
|
||||
<div class="setup-analyzer-confidence" title="{{ analysis.confidence }} %"><span style="width:{{ analysis.confidence }}%"></span></div>
|
||||
<details>
|
||||
<summary>{{ t('setup_analyzer.detection_signals') }}</summary>
|
||||
<ul>{% for key in analysis.signal_keys %}<li>{{ t(key) }}</li>{% endfor %}</ul>
|
||||
</details>
|
||||
{% if analysis.candidates|length > 1 %}
|
||||
<details>
|
||||
<summary>{{ t('setup_analyzer.other_candidates') }}</summary>
|
||||
<ul>{% for candidate in analysis.candidates[1:] %}<li>{{ candidate.label }} - {{ candidate.confidence }} %</li>{% endfor %}</ul>
|
||||
</details>
|
||||
{% endif %}
|
||||
{% if analysis.embedded_switches %}
|
||||
<details>
|
||||
<summary>{{ t('setup_analyzer.embedded_switches') }}</summary>
|
||||
<code>{{ analysis.embedded_switches|join(' ') }}</code>
|
||||
</details>
|
||||
{% endif %}
|
||||
</section>
|
||||
</div>
|
||||
|
||||
{% if analysis.warning_keys %}
|
||||
<section class="panel">
|
||||
<h2>{{ t('setup_analyzer.notes') }}</h2>
|
||||
{% for key in analysis.warning_keys %}<div class="notice setup-analyzer-notice">{{ t(key) }}</div>{% endfor %}
|
||||
</section>
|
||||
{% endif %}
|
||||
|
||||
<form class="setup-analyzer-export-form" method="post">
|
||||
<input type="hidden" name="token" value="{{ analysis.token }}">
|
||||
<div class="setup-analyzer-grid">
|
||||
<section class="panel setup-analyzer-card">
|
||||
<h2>{{ t('setup_analyzer.product_info') }}</h2>
|
||||
<label for="product_name">{{ t('setup_analyzer.product_name') }}
|
||||
<input id="product_name" name="product_name" value="{{ analysis.product_name }}">
|
||||
</label>
|
||||
<label for="product_version">{{ t('setup_analyzer.version') }}
|
||||
<input id="product_version" name="product_version" value="{{ analysis.product_version }}">
|
||||
</label>
|
||||
<label for="manufacturer">{{ t('setup_analyzer.manufacturer') }}
|
||||
<input id="manufacturer" name="manufacturer" value="{{ analysis.manufacturer }}">
|
||||
</label>
|
||||
<label for="architecture">{{ t('setup_analyzer.architecture') }}
|
||||
<input id="architecture" name="architecture" value="{{ analysis.architecture }}">
|
||||
</label>
|
||||
{% if analysis.product_code %}<p><strong>ProductCode:</strong> <code>{{ analysis.product_code }}</code></p>{% endif %}
|
||||
{% if analysis.upgrade_code %}<p><strong>UpgradeCode:</strong> <code>{{ analysis.upgrade_code }}</code></p>{% endif %}
|
||||
</section>
|
||||
|
||||
<section class="panel setup-analyzer-card">
|
||||
<h2>{{ t('setup_analyzer.installation') }}</h2>
|
||||
<label for="install_arguments">{{ t('setup_analyzer.arguments') }}
|
||||
<input id="install_arguments" name="install_arguments" value="{{ analysis.install_arguments }}">
|
||||
</label>
|
||||
<p><strong>{{ t('setup_analyzer.recommended_command') }}:</strong><br><code>{{ analysis.install_command }}</code></p>
|
||||
<label for="timeout_seconds">{{ t('setup_analyzer.timeout') }}
|
||||
<input id="timeout_seconds" name="timeout_seconds" type="number" min="30" max="86400" value="600">
|
||||
</label>
|
||||
<input type="hidden" name="run_as" value="system">
|
||||
<p><strong>{{ t('setup_analyzer.run_as') }}:</strong> SYSTEM<br><small class="muted">{{ t('setup_analyzer.run_as_help') }}</small></p>
|
||||
<label for="success_codes">{{ t('setup_analyzer.success_codes') }}
|
||||
<input id="success_codes" name="success_codes" value="{{ analysis.success_codes|join(', ') }}">
|
||||
</label>
|
||||
<label for="reboot_codes">{{ t('setup_analyzer.reboot_codes') }}
|
||||
<input id="reboot_codes" name="reboot_codes" value="{{ analysis.reboot_codes|join(', ') }}">
|
||||
</label>
|
||||
<div class="setup-analyzer-checkboxes">
|
||||
<label class="checkbox-label" for="suppress_browser">
|
||||
<input id="suppress_browser" name="suppress_browser" type="checkbox" value="true" {% if analysis.suppress_browser_default %}checked{% endif %}>
|
||||
<span>{{ t('setup_analyzer.suppress_browser') }}</span>
|
||||
</label>
|
||||
<small class="muted">{{ t('setup_analyzer.suppress_browser_help') }}</small>
|
||||
</div>
|
||||
<label for="process_names">{{ t('setup_analyzer.process_names') }}
|
||||
<input id="process_names" name="process_names" value="{{ analysis.process_names_default }}" placeholder="Greenshot.exe">
|
||||
</label>
|
||||
<small class="muted">{{ t('setup_analyzer.process_names_help') }}</small>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<section class="panel">
|
||||
<h2>{{ t('setup_analyzer.generated_logic') }}</h2>
|
||||
<p><strong>{{ t('setup_analyzer.detection_method') }}:</strong> <code>{{ analysis.detect_method }}</code></p>
|
||||
{% if analysis.uninstall_command %}<p><strong>{{ t('setup_analyzer.uninstall_command') }}:</strong><br><code>{{ analysis.uninstall_command }}</code></p>{% endif %}
|
||||
<p class="muted">{{ t('setup_analyzer.export_note_v2') }}</p>
|
||||
<div class="setup-analyzer-actions">
|
||||
<button class="button button-secondary" type="submit" formaction="/software/setup-analyzer/export/powershell">{{ t('setup_analyzer.export_ps') }}</button>
|
||||
<button class="button button-secondary" type="submit" formaction="/software/setup-analyzer/export/package">{{ t('setup_analyzer.export_package') }}</button>
|
||||
<button class="button" type="submit" formaction="/software/setup-analyzer/create-package">{{ t('setup_analyzer.create_package') }}</button>
|
||||
</div>
|
||||
</section>
|
||||
</form>
|
||||
|
||||
<details class="panel setup-analyzer-technical">
|
||||
<summary>{{ t('setup_analyzer.technical_details') }}</summary>
|
||||
<dl class="setup-analyzer-details">
|
||||
<dt>{{ t('setup_analyzer.pefile') }}</dt><dd>{{ t('common.yes') if analysis.pefile_available else t('common.no') }}</dd>
|
||||
<dt>msiinfo</dt><dd>{{ t('common.yes') if analysis.msiinfo_available else t('common.no') }}</dd>
|
||||
{% if analysis.original_filename %}<dt>OriginalFilename</dt><dd>{{ analysis.original_filename }}</dd>{% endif %}
|
||||
</dl>
|
||||
</details>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
@@ -38,6 +38,16 @@
|
||||
<span>{{ t('software.aggregated_list_help') }}</span>
|
||||
<span class="button button-secondary">{{ t('software.open') }}</span>
|
||||
</a>
|
||||
<a href="/software/setup-analyzer" class="software-list-link">
|
||||
<strong>{{ t('setup_analyzer.card_title') }}</strong>
|
||||
<span>{{ t('setup_analyzer.card_help') }}</span>
|
||||
<span class="button button-secondary">{{ t('software.open') }}</span>
|
||||
</a>
|
||||
<a href="/software/packages" class="software-list-link">
|
||||
<strong>{{ t('software_packages.card_title') }}</strong>
|
||||
<span>{{ t('software_packages.card_help') }}</span>
|
||||
<span class="button button-secondary">{{ t('software.open') }}</span>
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
Executable
+134
@@ -0,0 +1,134 @@
|
||||
{% extends 'base.html' %}
|
||||
{% block content %}
|
||||
<div class="toolbar">
|
||||
<div>
|
||||
<h1>{{ package.name }}</h1>
|
||||
<p class="muted">{{ t('software_packages.detail_subtitle') }}</p>
|
||||
</div>
|
||||
<div class="setup-analyzer-actions">
|
||||
<a class="button button-secondary" href="/software/packages">{{ t('software_packages.back') }}</a>
|
||||
<a class="button button-secondary" href="/software">{{ t('setup_analyzer.back_to_software') }}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if request.query_params.get('created') %}
|
||||
<div class="notice success">{{ t('software_packages.created') }}</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="setup-analyzer-grid">
|
||||
<section class="panel setup-analyzer-card">
|
||||
<h2>{{ t('software_packages.package_info') }}</h2>
|
||||
<dl class="setup-analyzer-details">
|
||||
<dt>{{ t('software.package') }}</dt><dd>{{ package.name }}</dd>
|
||||
<dt>{{ t('setup_analyzer.product_name') }}</dt><dd>{{ manifest.name or '—' }}</dd>
|
||||
<dt>{{ t('setup_analyzer.version') }}</dt><dd>{{ manifest.version or '—' }}</dd>
|
||||
<dt>{{ t('setup_analyzer.manufacturer') }}</dt><dd>{{ manifest.vendor or '—' }}</dd>
|
||||
<dt>{{ t('setup_analyzer.architecture') }}</dt><dd>{{ manifest.architecture or '—' }}</dd>
|
||||
<dt>{{ t('software_packages.installer_type') }}</dt><dd>{{ manifest.installer_type or '—' }}</dd>
|
||||
<dt>{{ t('software_packages.installer_file') }}</dt><dd><code>{{ manifest.installer_file or '—' }}</code></dd>
|
||||
<dt>{{ t('software_packages.storage') }}</dt><dd>{{ human_size(storage_size) }}</dd>
|
||||
</dl>
|
||||
</section>
|
||||
|
||||
<section class="panel setup-analyzer-card">
|
||||
<h2>{{ t('software_packages.deployment_info') }}</h2>
|
||||
<dl class="setup-analyzer-details">
|
||||
<dt>{{ t('setup_analyzer.arguments') }}</dt><dd><code>{{ manifest.install.arguments or '—' }}</code></dd>
|
||||
<dt>{{ t('setup_analyzer.timeout') }}</dt><dd>{{ manifest.install.timeout_seconds }} s</dd>
|
||||
<dt>{{ t('setup_analyzer.success_codes') }}</dt><dd>{{ manifest.install.success_codes|join(', ') }}</dd>
|
||||
<dt>{{ t('setup_analyzer.reboot_codes') }}</dt><dd>{{ manifest.install.reboot_codes|join(', ') }}</dd>
|
||||
<dt>{{ t('setup_analyzer.suppress_browser') }}</dt><dd>{{ t('common.yes') if manifest.install.suppress_browser else t('common.no') }}</dd>
|
||||
<dt>{{ t('software_packages.process_names') }}</dt><dd>{% if manifest.process_control.process_names %}<code>{{ manifest.process_control.process_names|join(', ') }}</code>{% else %}—{% endif %}</dd>
|
||||
<dt>{{ t('setup_analyzer.detection_method') }}</dt><dd><code>{{ manifest.detection.method }}</code></dd>
|
||||
</dl>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<section class="panel software-package-process-panel">
|
||||
<h2>{{ t('software_packages.process_control') }}</h2>
|
||||
<p class="muted">{{ t('software_packages.process_control_help') }}</p>
|
||||
<form method="post" action="/software/packages/{{ package.id }}/process-control" class="software-package-process-form">
|
||||
<label for="package_process_names">{{ t('software_packages.process_names') }}
|
||||
<input id="package_process_names" name="process_names" value="{{ manifest.process_control.process_names|join(', ') }}" placeholder="Greenshot.exe">
|
||||
</label>
|
||||
<small class="muted">{{ t('software_packages.process_names_help') }}</small>
|
||||
<label for="package_process_grace_seconds">{{ t('software_packages.process_grace_seconds') }}
|
||||
<input id="package_process_grace_seconds" name="grace_seconds" type="number" min="0" max="30" value="{{ manifest.process_control.grace_seconds }}">
|
||||
</label>
|
||||
<label class="checkbox-label software-package-force-close" for="package_force_close">
|
||||
<input id="package_force_close" name="force_close" type="checkbox" value="true" {% if manifest.process_control.force_close %}checked{% endif %}>
|
||||
<span>{{ t('software_packages.force_close') }}</span>
|
||||
</label>
|
||||
<button class="button button-secondary" type="submit">{{ t('common.save') }}</button>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
<section class="panel">
|
||||
<h2>{{ t('software_packages.create_jobs') }}</h2>
|
||||
<p class="muted">{{ t('software_packages.create_jobs_help') }}</p>
|
||||
<form method="post" action="/software/packages/{{ package.id }}/run" class="software-package-job-form">
|
||||
<fieldset class="software-package-action-fieldset">
|
||||
<legend>{{ t('software_packages.action') }}</legend>
|
||||
<div class="software-package-action-options">
|
||||
<label class="checkbox-label"><input type="radio" name="action" value="install" checked><span>{{ t('jobs.action.install') }}</span></label>
|
||||
<label class="checkbox-label"><input type="radio" name="action" value="uninstall"><span>{{ t('jobs.action.uninstall') }}</span></label>
|
||||
<label class="checkbox-label"><input type="radio" name="action" value="reinstall"><span>{{ t('jobs.action.reinstall') }}</span></label>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<div class="table-scroll management-table-scroll">
|
||||
<table class="data-table" data-storage-key="software-package-assets">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="selection-column" data-no-sort="1" data-no-filter="1"><input id="software-package-select-all" type="checkbox" aria-label="{{ t('software_packages.select_all') }}"></th>
|
||||
<th>{{ t('common.assets') }}</th>
|
||||
<th>{{ t('field.hostname') }}</th>
|
||||
<th>{{ t('software.platform') }}</th>
|
||||
<th>{{ t('field.department') }}</th>
|
||||
<th>{{ t('field.location') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for asset in assets %}
|
||||
<tr>
|
||||
<td class="selection-column"><input class="software-package-asset" type="checkbox" name="asset_ids" value="{{ asset.id }}"></td>
|
||||
<td><a href="/assets/{{ asset.id }}">{{ asset.name }}</a></td>
|
||||
<td>{{ asset.hostname or '—' }}</td>
|
||||
<td>{{ detect_platform(asset) }}</td>
|
||||
<td>{{ asset.department or '—' }}</td>
|
||||
<td>{{ asset.location or '—' }}</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr><td colspan="6">{{ t('software_packages.no_compatible_assets') }}</td></tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="form-actions">
|
||||
<button class="button" type="submit">{{ t('software_packages.start_jobs') }}</button>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
<section class="panel software-package-delete-panel">
|
||||
<h2>{{ t('software_packages.delete_title') }}</h2>
|
||||
<p class="muted">{{ t('software_packages.delete_help') }}</p>
|
||||
<form method="post" action="/software/packages/{{ package.id }}/delete" class="software-package-delete-form" onsubmit="return confirm({{ t('software_packages.delete_confirm', package=package.name)|tojson }});">
|
||||
{% if job_count %}
|
||||
<label class="checkbox-label software-package-delete-jobs">
|
||||
<input type="checkbox" name="delete_jobs" value="1">
|
||||
<span>{{ t('software_packages.delete_jobs', count=job_count) }}</span>
|
||||
</label>
|
||||
{% endif %}
|
||||
<button class="button button-danger" type="submit">{{ t('software_packages.delete_button') }}</button>
|
||||
</form>
|
||||
</section>
|
||||
<script>
|
||||
(function(){
|
||||
const master=document.getElementById('software-package-select-all');
|
||||
if(!master){return;}
|
||||
const items=Array.from(document.querySelectorAll('.software-package-asset'));
|
||||
master.addEventListener('change',()=>{items.forEach(item=>{item.checked=master.checked;});});
|
||||
})();
|
||||
</script>
|
||||
{% endblock %}
|
||||
Executable
+50
@@ -0,0 +1,50 @@
|
||||
{% extends 'base.html' %}
|
||||
{% block content %}
|
||||
<div class="toolbar">
|
||||
<div>
|
||||
<h1>{{ t('software_packages.title') }}</h1>
|
||||
<p class="muted">{{ t('software_packages.subtitle') }}</p>
|
||||
</div>
|
||||
<div class="setup-analyzer-actions">
|
||||
<a class="button" href="/software/setup-analyzer">{{ t('software_packages.new_from_analyzer') }}</a>
|
||||
<a class="button button-secondary" href="/software">{{ t('setup_analyzer.back_to_software') }}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<section class="panel">
|
||||
<div class="table-scroll management-table-scroll">
|
||||
<table class="data-table" data-storage-key="software-packages">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{ t('software.package') }}</th>
|
||||
<th>{{ t('setup_analyzer.version') }}</th>
|
||||
<th>{{ t('setup_analyzer.manufacturer') }}</th>
|
||||
<th>{{ t('setup_analyzer.architecture') }}</th>
|
||||
<th>{{ t('software_packages.installer_type') }}</th>
|
||||
<th>{{ t('software_packages.storage') }}</th>
|
||||
<th>{{ t('software_packages.status') }}</th>
|
||||
<th>{{ t('jobs.actions') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for row in package_rows %}
|
||||
{% set package = row.package %}
|
||||
{% set manifest = row.manifest %}
|
||||
<tr>
|
||||
<td><a href="/software/packages/{{ package.id }}"><strong>{{ package.name }}</strong></a></td>
|
||||
<td>{{ manifest.version or '—' }}</td>
|
||||
<td>{{ manifest.vendor or '—' }}</td>
|
||||
<td>{{ manifest.architecture or '—' }}</td>
|
||||
<td>{{ manifest.installer_type or '—' }}</td>
|
||||
<td>{{ human_size(row.storage_size) }}</td>
|
||||
<td>{% if row.storage_error %}<span class="job-status job-status-failed">{{ t('software_packages.storage_error') }}</span>{% elif package.enabled %}<span class="job-status job-status-success">{{ t('software_packages.enabled') }}</span>{% else %}<span class="job-status">{{ t('software_packages.disabled') }}</span>{% endif %}</td>
|
||||
<td><a class="button button-secondary button-small" href="/software/packages/{{ package.id }}">{{ t('software.open') }}</a></td>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr><td colspan="8">{{ t('software_packages.none') }}</td></tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user