First web UI draft

This commit is contained in:
simonmicro 2022-12-11 17:17:39 +01:00
parent 767751c314
commit 03c3e1c116
No known key found for this signature in database
GPG key ID: 033A4D4CE4E063D6
6 changed files with 198 additions and 2 deletions

View file

@ -1,2 +1,5 @@
dnspython==2.2.1
tzlocal==4.2
Flask==2.1.2
gunicorn==20.1.0

View file

@ -1,5 +1,6 @@
#!/usr/bin/env python3
import datetime
import os
import logging
@ -23,7 +24,7 @@ def sql_initialize(dbName):
try:
con = sqlite3.connect(dbName)
cur = con.cursor()
cur.execute("CREATE TABLE clients(clientMachineId TEXT, machineName TEXT, applicationId TEXT, skuId TEXT, licenseStatus TEXT, lastRequestTime INTEGER, kmsEpid TEXT, requestCount INTEGER)")
cur.execute("CREATE TABLE clients(clientMachineId TEXT PRIMARY KEY, machineName TEXT, applicationId TEXT, skuId TEXT, licenseStatus TEXT, lastRequestTime INTEGER, kmsEpid TEXT, requestCount INTEGER)")
except sqlite3.Error as e:
pretty_printer(log_obj = loggersrv.error, to_exit = True, put_text = "{reverse}{red}{bold}Sqlite Error: %s. Exiting...{end}" %str(e))
@ -32,6 +33,26 @@ def sql_initialize(dbName):
con.commit()
con.close()
def sql_get_all(dbName):
if not os.path.isfile(dbName):
return None
with sqlite3.connect(dbName) as con:
cur = con.cursor()
cur.execute("SELECT * FROM clients")
clients = []
for row in cur.fetchall():
clients.append({
'clientMachineId': row[0],
'machineName': row[1],
'applicationId': row[2],
'skuId': row[3],
'licenseStatus': row[4],
'lastRequestTime': datetime.datetime.fromtimestamp(row[5]).isoformat(),
'kmsEpid': row[6],
'requestCount': row[7]
})
return clients
def sql_update(dbName, infoDict):
con = None
try:

45
py-kms/pykms_WebUI.py Normal file
View file

@ -0,0 +1,45 @@
import os, uuid, datetime
from flask import Flask, render_template
from pykms_Sql import sql_get_all
app = Flask('pykms_webui')
start_time = datetime.datetime.now()
serve_count = 0
def _random_uuid():
return str(uuid.uuid4()).replace('-', '_')
@app.route('/')
def root():
global serve_count
serve_count += 1
error = None
# Get the db name / path
dbPath = None
envVarName = 'PYKMS_SQLITE_DB_PATH'
if envVarName in os.environ:
dbPath = os.environ.get(envVarName)
else:
error = f'Environment variable is not set: {envVarName}'
# Fetch all clients from the database.
clients = None
try:
if dbPath:
clients = sql_get_all(dbPath)
except Exception as e:
error = f'Error while loading database: {e}'
countClients = len(clients) if clients else 0
countClientsWindows = len([c for c in clients if c['applicationId'] == 'Windows']) if clients else 0
countClientsOffice = countClients - countClientsWindows
return render_template(
'index.html',
start_time=start_time.isoformat(),
error=error,
clients=clients,
count_clients=countClients,
count_clients_windows=countClientsWindows,
count_clients_office=countClientsOffice,
serve_count=serve_count,
random_uuid=_random_uuid
)

1
py-kms/static/LICENSE Symbolic link
View file

@ -0,0 +1 @@
../../LICENSE

1
py-kms/static/css/bulma.min.css vendored Normal file

File diff suppressed because one or more lines are too long

125
py-kms/templates/index.html Normal file
View file

@ -0,0 +1,125 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>py-kms web ui</title>
<link rel="stylesheet" href="{{ url_for('static', filename= 'css/bulma.min.css') }}">
<style>
#content {
margin: 1em;
overflow-x: auto;
}
pre.clientMachineId {
overflow-x: auto;
padding: 0.5em;
}
th {
white-space: nowrap;
}
</style>
</head>
<body>
<div id="content">
{% if error %}
<article class="message is-danger">
<div class="message-header">
Whoops! Something went wrong...
</div>
<div class="message-body">
{{ error }}
</div>
</article>
{% else %}
{% if clients %}
<nav class="level">
<div class="level-item has-text-centered">
<div>
<p class="heading">Clients</p>
<p class="title">{{ count_clients }}</p>
</div>
</div>
<div class="level-item has-text-centered">
<div>
<p class="heading">Windows</p>
<p class="title">{{ count_clients_windows }}</p>
</div>
</div>
<div class="level-item has-text-centered">
<div>
<p class="heading">Office</p>
<p class="title">{{ count_clients_office }}</p>
</div>
</div>
</nav>
<hr>
<table class="table is-striped is-hoverable is-fullwidth">
<thead>
<tr>
<th>Client ID</th>
<th>Machine Name</th>
<th>Application ID</th>
<th><abbr title="Stock Keeping Unit">SKU</abbr> ID</th>
<th>License Status</th>
<th>Last Seen</th>
<th>KMS <abbr title="Enhanced Privacy ID">EPID</abbr></th>
<th>Seen Count</th>
</tr>
</thead>
<tbody>
{% for client in clients %}
<tr>
<th><pre class="clientMachineId">{{ client.clientMachineId }}</pre></th>
<td class="machineName">
{% if client.machineName | length > 16 %}
<abbr title="{{ client.machineName }}">{{ client.machineName | truncate(16, True, '...') }}</abbr>
{% else %}
{{ client.machineName }}
{% endif %}
</td>
<td>{{ client.applicationId }}</td>
<td>{{ client.skuId }}</td>
<td>{{ client.licenseStatus }}</td>
<td class="convert_timestamp">{{ client.lastRequestTime }}</td>
<td>
{% if client.kmsEpid | length > 16 %}
<abbr title="{{ client.kmsEpid }}">{{ client.kmsEpid | truncate(16, True, '...') }}</abbr>
{% else %}
{{ client.kmsEpid }}
{% endif %}
</td>
<td>{{ client.requestCount }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<article class="message is-warning">
<div class="message-header">
<p>Whoops?</p>
</div>
<div class="message-body">
This page seems to be empty, because no clients are available. Try to use the server with a compartible client to add it to the database.
</div>
</article>
{% endif %}
{% endif %}
</div>
<footer class="footer">
<div class="content has-text-centered">
<p>
<strong>py-kms</strong> is online since <span class="convert_timestamp">{{ start_time }}</span>.
This page was rendered {{ serve_count }} times. View this softwares license <a href="{{ url_for('static', filename= 'LICENSE') }}">here</a>.
</p>
</div>
</footer>
<script>
for(let element of document.getElementsByClassName('convert_timestamp')) {
element.innerText = new Date(element.innerText).toLocaleString();
}
</script>
</body>
</html>