modified: web/app.py
modified: web/templates/admin/base.html modified: web/templates/auth/admin_login.html modified: web/templates/auth/login.html modified: web/templates/base.html modified: web/templates/group_admin/base.html new file: web/templates/privacy_policy.html
This commit is contained in:
@@ -66,6 +66,15 @@ def create_app() -> Flask:
|
||||
resp.headers.setdefault("Content-Security-Policy", "default-src 'self'; script-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net; style-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net; img-src 'self' data:; font-src 'self' https://cdn.jsdelivr.net; connect-src 'self'; frame-ancestors 'none';")
|
||||
return resp
|
||||
|
||||
@app.route("/privacy-policy")
|
||||
def privacy_policy():
|
||||
from config import Config
|
||||
return render_template(
|
||||
"privacy_policy.html",
|
||||
last_updated="April 14, 2026",
|
||||
invite_expiry_hours=Config.INVITE_EXPIRY_HOURS,
|
||||
)
|
||||
|
||||
@app.errorhandler(400)
|
||||
def bad_request(_):
|
||||
return "Bad request", 400
|
||||
|
||||
@@ -40,6 +40,12 @@
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
{% block content %}{% endblock %}
|
||||
<footer class="text-center py-3 mt-4 border-top border-secondary">
|
||||
<small class="text-muted">
|
||||
<a href="{{ url_for('privacy_policy') }}" class="text-muted text-decoration-none">Privacy Policy</a>
|
||||
— MCLogger
|
||||
</small>
|
||||
</footer>
|
||||
</div>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||
{% block scripts %}{% endblock %}
|
||||
|
||||
@@ -58,6 +58,9 @@
|
||||
<i class="bi bi-arrow-left me-1"></i>Back to regular login
|
||||
</a>
|
||||
</div>
|
||||
<div class="text-center mt-3">
|
||||
<a href="{{ url_for('privacy_policy') }}" class="text-muted small">Privacy Policy</a>
|
||||
</div>
|
||||
</div>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||
</body>
|
||||
|
||||
@@ -58,6 +58,9 @@
|
||||
<i class="bi bi-shield-fill me-1"></i>Site Admin Login
|
||||
</a>
|
||||
</div>
|
||||
<div class="text-center mt-3">
|
||||
<a href="{{ url_for('privacy_policy') }}" class="text-muted small">Privacy Policy</a>
|
||||
</div>
|
||||
</div>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||
</body>
|
||||
|
||||
@@ -171,6 +171,12 @@
|
||||
{% endwith %}
|
||||
|
||||
<main class="px-4 py-3">{% block content %}{% endblock %}</main>
|
||||
<footer class="text-center py-2 border-top border-secondary">
|
||||
<small class="text-muted">
|
||||
<a href="{{ url_for('privacy_policy') }}" class="text-muted text-decoration-none">Privacy Policy</a>
|
||||
— MCLogger
|
||||
</small>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -42,6 +42,12 @@
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
{% block content %}{% endblock %}
|
||||
<footer class="text-center py-3 mt-4 border-top border-secondary">
|
||||
<small class="text-muted">
|
||||
<a href="{{ url_for('privacy_policy') }}" class="text-muted text-decoration-none">Privacy Policy</a>
|
||||
— MCLogger
|
||||
</small>
|
||||
</footer>
|
||||
</div>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<script src="{{ url_for('static', filename='js/main.js') }}"></script>
|
||||
|
||||
207
web/templates/privacy_policy.html
Normal file
207
web/templates/privacy_policy.html
Normal file
@@ -0,0 +1,207 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" data-bs-theme="dark">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Privacy Policy — MCLogger</title>
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
|
||||
<style>
|
||||
body { background: #0d1117; }
|
||||
.policy-card { max-width: 820px; margin: 0 auto; }
|
||||
h2 { font-size: 1.15rem; margin-top: 2rem; }
|
||||
h3 { font-size: 1rem; margin-top: 1.25rem; }
|
||||
p, li { color: #c9d1d9; }
|
||||
</style>
|
||||
</head>
|
||||
<body class="py-5 px-3">
|
||||
<div class="policy-card">
|
||||
<div class="text-center mb-5">
|
||||
<i class="bi bi-database-fill-gear fs-1 text-success"></i>
|
||||
<h1 class="fw-bold mt-2 h3">MCLogger — Privacy Policy</h1>
|
||||
<p class="text-muted small">Last updated: {{ last_updated }}</p>
|
||||
</div>
|
||||
|
||||
<div class="card border-secondary mb-4">
|
||||
<div class="card-body">
|
||||
|
||||
<h2 class="fw-semibold border-bottom border-secondary pb-2">1. Controller & Contact</h2>
|
||||
<p>
|
||||
The controller responsible for data processing within this service is:
|
||||
</p>
|
||||
<p>
|
||||
<strong>Simon</strong><br>
|
||||
E-Mail: <a href="mailto:simon@devanturas.net">simon@devanturas.net</a>
|
||||
</p>
|
||||
<p>
|
||||
For any questions, requests, or concerns regarding your personal data, please contact the
|
||||
address above.
|
||||
</p>
|
||||
|
||||
<h2 class="fw-semibold border-bottom border-secondary pb-2">2. What Is MCLogger?</h2>
|
||||
<p>
|
||||
MCLogger is a self-hosted logging and analytics panel for Minecraft server operators.
|
||||
It collects and displays in-game activity data (sessions, chat, commands, deaths, block
|
||||
events, proxy events) and provides a multi-tenant web interface for authorised server
|
||||
administrators and group members.
|
||||
</p>
|
||||
|
||||
<h2 class="fw-semibold border-bottom border-secondary pb-2">3. Data We Collect</h2>
|
||||
|
||||
<h3 class="fw-semibold">3.1 Minecraft Player Data</h3>
|
||||
<p>When players connect to a Minecraft server that uses the MCLogger plugin, the
|
||||
following data is automatically recorded:</p>
|
||||
<ul>
|
||||
<li><strong>Player identity:</strong> Minecraft username, UUID</li>
|
||||
<li><strong>Sessions:</strong> join time, leave time, session duration, server name</li>
|
||||
<li><strong>IP addresses:</strong> the IP address used at connection time</li>
|
||||
<li><strong>Chat messages:</strong> message content, timestamp, username</li>
|
||||
<li><strong>Commands:</strong> command text, timestamp, username</li>
|
||||
<li><strong>Deaths:</strong> death message/cause, timestamp, location, username</li>
|
||||
<li><strong>Block events:</strong> block type, action (place/break), coordinates, username, timestamp</li>
|
||||
<li><strong>Proxy events:</strong> connect/disconnect events on the proxy network, timestamp</li>
|
||||
</ul>
|
||||
<p>
|
||||
This data is stored in a MariaDB database operated by the server operator. Players should
|
||||
be informed about this logging by the Minecraft server's own rules or MOTD.
|
||||
</p>
|
||||
|
||||
<h3 class="fw-semibold">3.2 Panel User Accounts</h3>
|
||||
<p>When a user account is created for the web panel, the following data is stored:</p>
|
||||
<ul>
|
||||
<li><strong>Username</strong></li>
|
||||
<li><strong>Password</strong> (stored as a salted PBKDF2-HMAC-SHA256 hash; the plain-text password is never stored)</li>
|
||||
<li><strong>E-mail address</strong> (when provided via the invite flow)</li>
|
||||
<li><strong>Group membership and role</strong></li>
|
||||
<li><strong>Account creation date</strong></li>
|
||||
</ul>
|
||||
|
||||
<h3 class="fw-semibold">3.3 Invite Tokens</h3>
|
||||
<p>
|
||||
When a group administrator invites a user by e-mail, a time-limited invite token is
|
||||
generated and stored together with the recipient's e-mail address. The token expires
|
||||
after {{ invite_expiry_hours }} hours. Accepted and revoked tokens are retained in the database for
|
||||
audit purposes.
|
||||
</p>
|
||||
|
||||
<h3 class="fw-semibold">3.4 Session Data</h3>
|
||||
<p>
|
||||
MCLogger uses server-side sessions (Flask session cookie) to keep you logged in.
|
||||
The session cookie is HTTP-only, SameSite-protected, and expires when your browser
|
||||
session ends.
|
||||
</p>
|
||||
|
||||
<h3 class="fw-semibold">3.5 Server Log Files</h3>
|
||||
<p>
|
||||
The web server (gunicorn) may write standard HTTP access logs containing IP
|
||||
addresses, request paths, and timestamps. These logs are used for operational
|
||||
security monitoring and are not shared with third parties.
|
||||
</p>
|
||||
|
||||
<h2 class="fw-semibold border-bottom border-secondary pb-2">4. Purpose & Legal Basis of Processing</h2>
|
||||
<table class="table table-sm table-dark table-bordered">
|
||||
<thead class="table-secondary">
|
||||
<tr>
|
||||
<th>Data</th>
|
||||
<th>Purpose</th>
|
||||
<th>Legal Basis (GDPR)</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Minecraft player activity data</td>
|
||||
<td>Server administration, moderation, abuse prevention</td>
|
||||
<td>Art. 6(1)(f) — legitimate interest of the server operator</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Panel user accounts</td>
|
||||
<td>Authentication and authorisation for the web panel</td>
|
||||
<td>Art. 6(1)(b) — performance of a contract / access service</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>E-mail addresses (invites)</td>
|
||||
<td>Sending one-time panel invitation links</td>
|
||||
<td>Art. 6(1)(a) — consent (the invite was requested by a group admin)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Server access logs</td>
|
||||
<td>Security monitoring and error diagnosis</td>
|
||||
<td>Art. 6(1)(f) — legitimate interest</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h2 class="fw-semibold border-bottom border-secondary pb-2">5. Data Retention</h2>
|
||||
<ul>
|
||||
<li><strong>Minecraft logs</strong> are retained as long as the server operator deems necessary for moderation purposes.</li>
|
||||
<li><strong>Panel accounts</strong> are retained until manually deleted by a site administrator.</li>
|
||||
<li><strong>Invite tokens</strong> expire after {{ invite_expiry_hours }} hours and are never sent to third parties beyond the intended recipient.</li>
|
||||
<li><strong>Server access logs</strong> are typically rotated within 30 days.</li>
|
||||
</ul>
|
||||
|
||||
<h2 class="fw-semibold border-bottom border-secondary pb-2">6. Data Sharing & Third Parties</h2>
|
||||
<p>
|
||||
Data collected by MCLogger is <strong>not sold, rented, or shared</strong> with third
|
||||
parties. All data remains within the infrastructure controlled by the server operator.
|
||||
No third-party analytics services, advertising networks, or tracking pixels are used.
|
||||
</p>
|
||||
<p>
|
||||
External resources loaded by the web interface (Bootstrap CSS/JS and Bootstrap Icons)
|
||||
are served from the jsDelivr CDN (<code>cdn.jsdelivr.net</code>). jsDelivr may process
|
||||
your IP address as part of delivering these static files. Please consult
|
||||
<a href="https://www.jsdelivr.com/privacy-policy-jsdelivr-net" target="_blank" rel="noopener noreferrer">jsDelivr's privacy policy</a>
|
||||
for details.
|
||||
</p>
|
||||
|
||||
<h2 class="fw-semibold border-bottom border-secondary pb-2">7. Security</h2>
|
||||
<p>
|
||||
MCLogger applies the following technical safeguards:
|
||||
</p>
|
||||
<ul>
|
||||
<li>Passwords are hashed with PBKDF2-HMAC-SHA256 (per-user salt + server pepper).</li>
|
||||
<li>Stored database credentials and SMTP credentials are encrypted with Fernet symmetric encryption before being written to the database.</li>
|
||||
<li>CSRF tokens are enforced on all state-changing requests.</li>
|
||||
<li>Security response headers (X-Frame-Options, X-Content-Type-Options, Content-Security-Policy, Referrer-Policy) are set on every response.</li>
|
||||
<li>SMTP connections use STARTTLS.</li>
|
||||
</ul>
|
||||
|
||||
<h2 class="fw-semibold border-bottom border-secondary pb-2">8. Your Rights (GDPR)</h2>
|
||||
<p>If you are subject to the GDPR you have the following rights:</p>
|
||||
<ul>
|
||||
<li><strong>Right of access</strong> (Art. 15) — request a copy of your personal data.</li>
|
||||
<li><strong>Right to rectification</strong> (Art. 16) — request correction of inaccurate data.</li>
|
||||
<li><strong>Right to erasure</strong> (Art. 17) — request deletion of your data ("right to be forgotten").</li>
|
||||
<li><strong>Right to restriction of processing</strong> (Art. 18) — request that processing is restricted while a dispute is resolved.</li>
|
||||
<li><strong>Right to data portability</strong> (Art. 20) — receive your data in a structured, machine-readable format.</li>
|
||||
<li><strong>Right to object</strong> (Art. 21) — object to processing based on legitimate interest.</li>
|
||||
<li><strong>Right to withdraw consent</strong> (Art. 7(3)) — withdraw any consent you have given at any time.</li>
|
||||
</ul>
|
||||
<p>
|
||||
To exercise any of these rights, please contact:
|
||||
<a href="mailto:simon@devanturas.net">simon@devanturas.net</a>
|
||||
</p>
|
||||
<p>
|
||||
You also have the right to lodge a complaint with your national data protection
|
||||
supervisory authority.
|
||||
</p>
|
||||
|
||||
<h2 class="fw-semibold border-bottom border-secondary pb-2">9. Changes to This Policy</h2>
|
||||
<p>
|
||||
This privacy policy may be updated to reflect changes in the software or applicable law.
|
||||
The "Last updated" date at the top of this page indicates when the most recent revision
|
||||
was made.
|
||||
</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="text-center text-muted small pb-5">
|
||||
<a href="{{ url_for('auth.login') }}" class="text-muted me-3">
|
||||
<i class="bi bi-arrow-left me-1"></i>Back to Login
|
||||
</a>
|
||||
MCLogger — <a href="mailto:simon@devanturas.net" class="text-muted">simon@devanturas.net</a>
|
||||
</div>
|
||||
</div>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user