202 lines
6.4 KiB
Python
202 lines
6.4 KiB
Python
import sqlite3
|
|||
|
|
import os
|
||
|
|
|
||
|
|
DB_PATH = os.path.join(os.path.dirname(__file__), 'app_data.db')
|
||
|
|
|
||
|
|
def init_db():
|
||
|
|
conn = sqlite3.connect(DB_PATH)
|
||
|
|
cursor = conn.cursor()
|
||
|
|
cursor.execute('''
|
||
|
|
CREATE TABLE IF NOT EXISTS address_list_items (
|
||
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||
|
|
ip TEXT UNIQUE NOT NULL,
|
||
|
|
list_name TEXT NOT NULL,
|
||
|
|
comment TEXT,
|
||
|
|
mikrotik_id TEXT,
|
||
|
|
enabled BOOLEAN DEFAULT TRUE,
|
||
|
|
last_sync DATETIME DEFAULT CURRENT_TIMESTAMP
|
||
|
|
)
|
||
|
|
''')
|
||
|
|
cursor.execute('''
|
||
|
|
CREATE TABLE IF NOT EXISTS admins (
|
||
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||
|
|
username TEXT UNIQUE NOT NULL,
|
||
|
|
password_hash TEXT NOT NULL,
|
||
|
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||
|
|
)
|
||
|
|
''')
|
||
|
|
cursor.execute('''
|
||
|
|
CREATE TABLE IF NOT EXISTS named_lists (
|
||
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||
|
|
name TEXT UNIQUE NOT NULL
|
||
|
|
)
|
||
|
|
''')
|
||
|
|
|
||
|
|
# Миграция: добавляем существующие уникальные имена списков в новую таблицу
|
||
|
|
cursor.execute('SELECT DISTINCT list_name FROM address_list_items')
|
||
|
|
existing_lists = cursor.fetchall()
|
||
|
|
for row in existing_lists:
|
||
|
|
cursor.execute('INSERT OR IGNORE INTO named_lists (name) VALUES (?)', (row[0],))
|
||
|
|
|
||
|
|
# Если список пуст, создаем дефолтный
|
||
|
|
cursor.execute('SELECT COUNT(*) FROM named_lists')
|
||
|
|
if cursor.fetchone()[0] == 0:
|
||
|
|
cursor.execute('INSERT INTO named_lists (name) VALUES (?)', ('trusted',))
|
||
|
|
|
||
|
|
conn.commit()
|
||
|
|
conn.close()
|
||
|
|
|
||
|
|
def get_db_connection():
|
||
|
|
conn = sqlite3.connect(DB_PATH)
|
||
|
|
conn.row_factory = sqlite3.Row
|
||
|
|
return conn
|
||
|
|
|
||
|
|
def get_item_by_ip(ip):
|
||
|
|
conn = get_db_connection()
|
||
|
|
item = conn.execute('SELECT * FROM address_list_items WHERE ip = ?', (ip,)).fetchone()
|
||
|
|
conn.close()
|
||
|
|
return item
|
||
|
|
|
||
|
|
def get_all_items(list_name=None):
|
||
|
|
conn = get_db_connection()
|
||
|
|
if list_name:
|
||
|
|
items = conn.execute('SELECT * FROM address_list_items WHERE list_name = ?', (list_name,)).fetchall()
|
||
|
|
else:
|
||
|
|
items = conn.execute('SELECT * FROM address_list_items').fetchall()
|
||
|
|
conn.close()
|
||
|
|
return [dict(i) for i in items]
|
||
|
|
|
||
|
|
def add_item(ip, list_name, comment, mikrotik_id, enabled=True):
|
||
|
|
conn = get_db_connection()
|
||
|
|
try:
|
||
|
|
cursor = conn.cursor()
|
||
|
|
cursor.execute(
|
||
|
|
'INSERT INTO address_list_items (ip, list_name, comment, mikrotik_id, enabled) VALUES (?, ?, ?, ?, ?)',
|
||
|
|
(ip, list_name, comment, mikrotik_id, enabled)
|
||
|
|
)
|
||
|
|
conn.commit()
|
||
|
|
return True, cursor.lastrowid
|
||
|
|
except sqlite3.IntegrityError:
|
||
|
|
return False, "IP already exists"
|
||
|
|
finally:
|
||
|
|
conn.close()
|
||
|
|
|
||
|
|
def update_item_status(ip, enabled):
|
||
|
|
conn = get_db_connection()
|
||
|
|
conn.execute(
|
||
|
|
'UPDATE address_list_items SET enabled = ?, last_sync = CURRENT_TIMESTAMP WHERE ip = ?',
|
||
|
|
(enabled, ip)
|
||
|
|
)
|
||
|
|
conn.commit()
|
||
|
|
conn.close()
|
||
|
|
|
||
|
|
def update_mikrotik_id(ip, mikrotik_id):
|
||
|
|
conn = get_db_connection()
|
||
|
|
conn.execute(
|
||
|
|
'UPDATE address_list_items SET mikrotik_id = ? WHERE ip = ?',
|
||
|
|
(mikrotik_id, ip)
|
||
|
|
)
|
||
|
|
conn.commit()
|
||
|
|
conn.close()
|
||
|
|
|
||
|
|
def delete_item_by_ip(ip):
|
||
|
|
conn = get_db_connection()
|
||
|
|
conn.execute('DELETE FROM address_list_items WHERE ip = ?', (ip,))
|
||
|
|
conn.commit()
|
||
|
|
conn.close()
|
||
|
|
|
||
|
|
def delete_item_by_id(db_id):
|
||
|
|
conn = get_db_connection()
|
||
|
|
cursor = conn.cursor()
|
||
|
|
item = conn.execute('SELECT ip, mikrotik_id FROM address_list_items WHERE id = ?', (db_id,)).fetchone()
|
||
|
|
if item:
|
||
|
|
conn.execute('DELETE FROM address_list_items WHERE id = ?', (db_id,))
|
||
|
|
conn.commit()
|
||
|
|
conn.close()
|
||
|
|
return dict(item)
|
||
|
|
conn.close()
|
||
|
|
return None
|
||
|
|
|
||
|
|
def get_item_by_id(db_id):
|
||
|
|
conn = get_db_connection()
|
||
|
|
item = conn.execute('SELECT * FROM address_list_items WHERE id = ?', (db_id,)).fetchone()
|
||
|
|
conn.close()
|
||
|
|
return item
|
||
|
|
|
||
|
|
def get_unique_lists():
|
||
|
|
conn = get_db_connection()
|
||
|
|
lists = conn.execute('SELECT name FROM named_lists ORDER BY name').fetchall()
|
||
|
|
conn.close()
|
||
|
|
return [row['name'] for row in lists]
|
||
|
|
|
||
|
|
def get_named_lists_detailed():
|
||
|
|
conn = get_db_connection()
|
||
|
|
lists = conn.execute('SELECT * FROM named_lists ORDER BY name').fetchall()
|
||
|
|
conn.close()
|
||
|
|
return [dict(row) for row in lists]
|
||
|
|
|
||
|
|
def add_named_list(name):
|
||
|
|
conn = get_db_connection()
|
||
|
|
try:
|
||
|
|
conn.execute('INSERT INTO named_lists (name) VALUES (?)', (name,))
|
||
|
|
conn.commit()
|
||
|
|
return True, ""
|
||
|
|
except sqlite3.IntegrityError:
|
||
|
|
return False, "List already exists"
|
||
|
|
finally:
|
||
|
|
conn.close()
|
||
|
|
|
||
|
|
def delete_named_list(list_id):
|
||
|
|
conn = get_db_connection()
|
||
|
|
try:
|
||
|
|
# Проверяем, используются ли записи из этого списка
|
||
|
|
list_name_row = conn.execute('SELECT name FROM named_lists WHERE id = ?', (list_id,)).fetchone()
|
||
|
|
if not list_name_row:
|
||
|
|
return False, "Not found"
|
||
|
|
|
||
|
|
usage_count = conn.execute('SELECT COUNT(*) FROM address_list_items WHERE list_name = ?', (list_name_row['name'],)).fetchone()[0]
|
||
|
|
if usage_count > 0:
|
||
|
|
return False, f"Cannot delete: {usage_count} addresses are still in this list"
|
||
|
|
|
||
|
|
conn.execute('DELETE FROM named_lists WHERE id = ?', (list_id,))
|
||
|
|
conn.commit()
|
||
|
|
return True, ""
|
||
|
|
finally:
|
||
|
|
conn.close()
|
||
|
|
|
||
|
|
# --- Admin Operations ---
|
||
|
|
|
||
|
|
def get_admin(username):
|
||
|
|
conn = get_db_connection()
|
||
|
|
admin = conn.execute('SELECT * FROM admins WHERE username = ?', (username,)).fetchone()
|
||
|
|
conn.close()
|
||
|
|
return admin
|
||
|
|
|
||
|
|
def add_admin(username, password_hash):
|
||
|
|
conn = get_db_connection()
|
||
|
|
try:
|
||
|
|
conn.execute('INSERT INTO admins (username, password_hash) VALUES (?, ?)', (username, password_hash))
|
||
|
|
conn.commit()
|
||
|
|
return True
|
||
|
|
except sqlite3.IntegrityError:
|
||
|
|
return False
|
||
|
|
finally:
|
||
|
|
conn.close()
|
||
|
|
|
||
|
|
def update_admin(old_username, new_username, new_password_hash):
|
||
|
|
conn = get_db_connection()
|
||
|
|
try:
|
||
|
|
conn.execute(
|
||
|
|
'UPDATE admins SET username = ?, password_hash = ? WHERE username = ?',
|
||
|
|
(new_username, new_password_hash, old_username)
|
||
|
|
)
|
||
|
|
conn.commit()
|
||
|
|
return True
|
||
|
|
except Exception:
|
||
|
|
return False
|
||
|
|
finally:
|
||
|
|
conn.close()
|
||
|
|
|
||
|
|
if __name__ == '__main__':
|
||
|
|
init_db()
|
||
|
|
print("Database initialized.")
|