mj add another admin

This commit is contained in:
2026-04-26 22:39:52 +03:00
parent bfdfaa142c
commit 8ed964f3bb
5 changed files with 160 additions and 19 deletions

7
app.py
View File

@@ -21,17 +21,18 @@ login_manager.login_view = 'auth.login'
login_manager.login_message = 'Παρακαλώ συνδεθείτε για να συνεχίσετε.'
class User(UserMixin):
def __init__(self, id, username):
def __init__(self, id, username, clan_id):
self.id = id
self.username = username
self.clan_id = clan_id
@login_manager.user_loader
def load_user(user_id):
conn = get_db()
row = conn.execute('SELECT id, username FROM users WHERE id = ?', (user_id,)).fetchone()
row = conn.execute('SELECT id, username, clan_id FROM users WHERE id = ?', (user_id,)).fetchone()
conn.close()
if row:
return User(row['id'], row['username'])
return User(row['id'], row['username'], row['clan_id'])
return None
# Make current_user available in all templates

13
db.py
View File

@@ -77,6 +77,7 @@ def init_db():
'ALTER TABLE commands ADD COLUMN player_id TEXT',
'ALTER TABLE farm_settings ADD COLUMN bandit_camp_enabled INTEGER NOT NULL DEFAULT 0',
"ALTER TABLE clan_members ADD COLUMN features TEXT NOT NULL DEFAULT 'farm,admin'",
'ALTER TABLE users ADD COLUMN clan_id INTEGER REFERENCES clans(id)',
]:
try:
c.execute(_col)
@@ -89,6 +90,7 @@ def init_db():
id INTEGER PRIMARY KEY AUTOINCREMENT,
username TEXT NOT NULL UNIQUE,
password_hash TEXT NOT NULL,
clan_id INTEGER REFERENCES clans(id),
created_at TEXT NOT NULL DEFAULT (datetime('now'))
)
''')
@@ -111,11 +113,22 @@ def init_db():
clan_id INTEGER NOT NULL REFERENCES clans(id),
player_id TEXT NOT NULL,
player_name TEXT,
features TEXT NOT NULL DEFAULT 'farm,admin',
joined_at TEXT NOT NULL DEFAULT (datetime('now')),
UNIQUE(clan_id, player_id)
)
''')
# Migration: Auto-assign existing users to their clan_id if they are the owner
try:
c.execute('''
UPDATE users
SET clan_id = (SELECT id FROM clans WHERE owner_id = users.id)
WHERE clan_id IS NULL AND EXISTS (SELECT 1 FROM clans WHERE owner_id = users.id)
''')
except Exception:
pass
conn.commit()
conn.close()

View File

@@ -12,7 +12,7 @@ auth = Blueprint('auth', __name__)
# ------------------------------------------------------------------
def _make_user(row):
from app import User
return User(row['id'], row['username'])
return User(row['id'], row['username'], row['clan_id'])
# ------------------------------------------------------------------
@@ -30,7 +30,7 @@ def login():
conn = get_db()
row = conn.execute(
'SELECT id, username, password_hash FROM users WHERE username = ?', (username,)
'SELECT id, username, password_hash, clan_id FROM users WHERE username = ?', (username,)
).fetchone()
conn.close()
@@ -80,7 +80,7 @@ def register():
)
conn.commit()
row = conn.execute(
'SELECT id, username, password_hash FROM users WHERE username = ?', (username,)
'SELECT id, username, password_hash, clan_id FROM users WHERE username = ?', (username,)
).fetchone()
conn.close()
user = _make_user(row)
@@ -108,10 +108,21 @@ def logout():
def options():
conn = get_db()
# Load clan based on current user's clan_id
clan = None
if current_user.clan_id:
clan = conn.execute(
'SELECT * FROM clans WHERE owner_id = ?', (current_user.id,)
'SELECT * FROM clans WHERE id = ?', (current_user.clan_id,)
).fetchone()
# Fetch website admins (users belonging to this clan other than current user)
admins = []
if clan and clan['owner_id'] == current_user.id:
admins = conn.execute(
'SELECT id, username, created_at FROM users WHERE clan_id = ? AND id != ? ORDER BY created_at ASC',
(clan['id'], current_user.id)
).fetchall()
members = []
if clan:
rows = conn.execute(
@@ -146,7 +157,7 @@ def options():
})
conn.close()
return render_template('options.html', clan=clan, members=members)
return render_template('options.html', clan=clan, members=members, admins=admins)
# ------------------------------------------------------------------
@@ -166,12 +177,17 @@ def create_clan():
if not existing:
key = generate_clan_key()
conn.execute(
cursor = conn.execute(
'INSERT INTO clans (owner_id, name, clan_key) VALUES (?, ?, ?)',
(current_user.id, clan_name, key)
)
clan_id = cursor.lastrowid
conn.execute('UPDATE users SET clan_id = ? WHERE id = ?', (clan_id, current_user.id))
conn.commit()
# Update the current_user object dynamically to reflect the new clan_id without re-login
current_user.clan_id = clan_id
conn.close()
return redirect(url_for('auth.options'))
@@ -233,3 +249,55 @@ def update_member_features(player_id):
conn.close()
return redirect(url_for('auth.options'))
# ------------------------------------------------------------------
# POST /auth/clan/add-admin
# ------------------------------------------------------------------
@auth.route('/auth/clan/add-admin', methods=['POST'])
@login_required
def add_admin():
username = request.form.get('admin_username', '').strip()
if not username:
return redirect(url_for('auth.options'))
conn = get_db()
clan = conn.execute(
'SELECT id FROM clans WHERE owner_id = ?', (current_user.id,)
).fetchone()
if clan:
# Check if user exists
user = conn.execute('SELECT id, clan_id FROM users WHERE username = ?', (username,)).fetchone()
if user:
# If user already belongs to a clan, we could show an error, but let's just overwrite for now
# or maybe only if clan_id is NULL
conn.execute('UPDATE users SET clan_id = ? WHERE id = ?', (clan['id'], user['id']))
conn.commit()
flash(f"Ο χρήστης {username} προστέθηκε ως διαχειριστής.", "success")
else:
flash(f"Ο χρήστης {username} δεν βρέθηκε.", "error")
conn.close()
return redirect(url_for('auth.options'))
# ------------------------------------------------------------------
# POST /auth/clan/remove-admin/<admin_id>
# ------------------------------------------------------------------
@auth.route('/auth/clan/remove-admin/<int:admin_id>', methods=['POST'])
@login_required
def remove_admin(admin_id):
conn = get_db()
clan = conn.execute(
'SELECT id FROM clans WHERE owner_id = ?', (current_user.id,)
).fetchone()
if clan:
conn.execute('UPDATE users SET clan_id = NULL WHERE id = ? AND clan_id = ?', (admin_id, clan['id']))
conn.commit()
flash("Ο διαχειριστής αφαιρέθηκε.", "success")
conn.close()
return redirect(url_for('auth.options'))

View File

@@ -16,18 +16,14 @@ dashboard = Blueprint('dashboard', __name__)
def index():
conn = get_db()
# Get the logged-in user's clan
clan = conn.execute(
'SELECT id FROM clans WHERE owner_id = ?', (current_user.id,)
).fetchone()
# Get the clan the logged-in user belongs to
clan_id = current_user.clan_id
if not clan:
# User has no clan yet — send them to options to create one
if not clan_id:
# User has no clan yet — send them to options to create/join one
conn.close()
return render_template('index.html', players=[], no_clan=True)
clan_id = clan['id']
# Only fetch players that are members of this clan
rows = conn.execute('''
SELECT ts.player, ts.player_id, MAX(ts.updated_at) as last_seen, MAX(ts.world_id) as world_id

View File

@@ -175,7 +175,18 @@
<div class="page-title">Ρυθμίσεις Clan</div>
<div class="page-subtitle">Διαχείριση της ομάδας σας και του κλειδιού πρόσβασης</div>
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
{% for category, message in messages %}
<div class="warn-box" style="margin-bottom: 20px; color: {% if category == 'error' %}#f85149{% else %}#3fb950{% endif %}; border-color: {% if category == 'error' %}rgba(248,81,73,0.3){% else %}rgba(63,185,80,0.3){% endif %}; background: {% if category == 'error' %}rgba(248,81,73,0.1){% else %}rgba(63,185,80,0.1){% endif %};">
{{ message }}
</div>
{% endfor %}
{% endif %}
{% endwith %}
{% if clan %}
{% if clan.owner_id == current_user.id %}
<!-- ===================== Clan Key Section ===================== -->
<div class="card">
<div class="card-title">🔑 Clan Key</div>
@@ -195,6 +206,49 @@
</form>
</div>
<!-- ===================== Website Admins Section ===================== -->
<div class="card">
<div class="card-title">👨‍💻 Website Admins</div>
<p style="color:#8b949e; font-size:0.875rem; margin-bottom:14px;">
Προσθέστε το username άλλων παικτών που έχουν ήδη εγγραφεί στο site για να τους δώσετε πρόσβαση στο dashboard σας.
</p>
<form method="POST" action="/auth/clan/add-admin" class="inline-form" style="margin-bottom: 20px;">
<input type="text" name="admin_username" placeholder="π.χ. player123" required>
<button type="submit" class="btn-primary">Προσθήκη Admin</button>
</form>
{% if admins %}
<table class="members-table">
<thead>
<tr>
<th>Admin Username</th>
<th>Ημερομηνία Προσθήκης</th>
<th></th>
</tr>
</thead>
<tbody>
{% for a in admins %}
<tr>
<td><div class="player-name">{{ a.username }}</div></td>
<td style="color:#8b949e; font-size:0.8rem;">{{ a.created_at[:10] }}</td>
<td style="text-align:right;">
<form method="POST" action="/auth/clan/remove-admin/{{ a.id }}" onsubmit="return confirm('Αφαίρεση του admin {{ a.username }}?');">
<button type="submit" class="btn-danger">Αφαίρεση</button>
</form>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<div class="empty-state" style="padding: 16px 0;">
Δεν έχετε προσθέσει κανέναν website admin ακόμη.
</div>
{% endif %}
</div>
{% endif %}
<!-- ===================== Members Section ===================== -->
<div class="card">
<div class="card-title">👥 Μέλη Clan — {{ clan.name }}</div>
@@ -224,6 +278,7 @@
{% endif %}
</td>
<td>
{% if clan.owner_id == current_user.id %}
<form method="POST" action="/auth/clan/update-features/{{ m.player_id }}" style="display:inline;">
<div class="toggle-group">
<label class="toggle-label">
@@ -234,13 +289,21 @@
</label>
</div>
</form>
{% else %}
<div class="toggle-group" style="opacity: 0.8;">
<span class="toggle-label" style="cursor:default; border-color: {{ '#3fb950' if m.feat_farm else '#30363d' }}; color: {{ '#3fb950' if m.feat_farm else '#8b949e' }};">🌾 Farm</span>
<span class="toggle-label" style="cursor:default; border-color: {{ '#3fb950' if m.feat_admin else '#30363d' }}; color: {{ '#3fb950' if m.feat_admin else '#8b949e' }};">🏛 Admin</span>
</div>
{% endif %}
</td>
<td style="color:#8b949e; font-size:0.8rem;">{{ m.joined_at }}</td>
<td style="text-align:right;">
{% if clan.owner_id == current_user.id %}
<form method="POST" action="/auth/clan/remove-member/{{ m.player_id }}"
onsubmit="return confirm('Αφαίρεση παίκτη {{ m.player_name }}?');">
<button type="submit" class="btn-danger">Αφαίρεση</button>
</form>
{% endif %}
</td>
</tr>
{% endfor %}