pc responsive issues
Browse files- app/main.py +63 -14
app/main.py
CHANGED
|
@@ -62,21 +62,37 @@ class UserManager:
|
|
| 62 |
with open(self.filename, "w") as f:
|
| 63 |
json.dump(self.users, f, indent=4)
|
| 64 |
|
| 65 |
-
def add_user(self, username, password):
|
| 66 |
-
"""Registra un nuevo usuario con contraseña hasheada."""
|
| 67 |
if self.get_by_username(username):
|
| 68 |
return False
|
| 69 |
|
| 70 |
-
user_id = str(
|
| 71 |
hashed_pw = generate_password_hash(password)
|
| 72 |
self.users.append({
|
| 73 |
"id": user_id,
|
| 74 |
"username": username,
|
| 75 |
-
"password": hashed_pw
|
|
|
|
| 76 |
})
|
| 77 |
self.save()
|
| 78 |
return True
|
| 79 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 80 |
def get_by_username(self, username):
|
| 81 |
"""Busca un usuario por su nombre."""
|
| 82 |
for user in self.users:
|
|
@@ -97,7 +113,7 @@ user_mgr = UserManager()
|
|
| 97 |
def load_user(user_id):
|
| 98 |
"""Cargador de usuario para Flask-Login desde el JSON."""
|
| 99 |
user_data = user_mgr.get_by_id(user_id)
|
| 100 |
-
if user_data:
|
| 101 |
return User(user_data['id'], user_data['username'])
|
| 102 |
return None
|
| 103 |
|
|
@@ -223,6 +239,21 @@ if bot:
|
|
| 223 |
bot.edit_message_text(nuevo_texto, call.message.chat.id, call.message.message_id, parse_mode="Markdown")
|
| 224 |
else:
|
| 225 |
bot.answer_callback_query(call.id, "Error: El préstamo no está aceptado o no existe", show_alert=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 226 |
|
| 227 |
except Exception as e:
|
| 228 |
print(f"Callback Error: {e}")
|
|
@@ -282,13 +313,18 @@ def login():
|
|
| 282 |
|
| 283 |
user_data = user_mgr.get_by_username(username)
|
| 284 |
|
| 285 |
-
if user_data
|
| 286 |
-
|
| 287 |
-
|
| 288 |
-
|
| 289 |
-
|
| 290 |
-
|
| 291 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 292 |
|
| 293 |
return render_template('login.html', title="Login")
|
| 294 |
|
|
@@ -306,8 +342,21 @@ def register():
|
|
| 306 |
flash("Las contraseñas no coinciden", "red")
|
| 307 |
return render_template('register.html')
|
| 308 |
|
| 309 |
-
if user_mgr.add_user(username, password):
|
| 310 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 311 |
return redirect(url_for('login'))
|
| 312 |
else:
|
| 313 |
flash("El nombre de usuario ya existe.", "red")
|
|
|
|
| 62 |
with open(self.filename, "w") as f:
|
| 63 |
json.dump(self.users, f, indent=4)
|
| 64 |
|
| 65 |
+
def add_user(self, username, password, status="PENDING"):
|
| 66 |
+
"""Registra un nuevo usuario con contraseña hasheada y estado pendiente."""
|
| 67 |
if self.get_by_username(username):
|
| 68 |
return False
|
| 69 |
|
| 70 |
+
user_id = str(uuid.uuid4())
|
| 71 |
hashed_pw = generate_password_hash(password)
|
| 72 |
self.users.append({
|
| 73 |
"id": user_id,
|
| 74 |
"username": username,
|
| 75 |
+
"password": hashed_pw,
|
| 76 |
+
"status": status
|
| 77 |
})
|
| 78 |
self.save()
|
| 79 |
return True
|
| 80 |
|
| 81 |
+
def activate_user(self, username):
|
| 82 |
+
"""Activa un usuario pendiente."""
|
| 83 |
+
for user in self.users:
|
| 84 |
+
if user["username"] == username:
|
| 85 |
+
user["status"] = "ACTIVE"
|
| 86 |
+
self.save()
|
| 87 |
+
return True
|
| 88 |
+
return False
|
| 89 |
+
|
| 90 |
+
def delete_user(self, username):
|
| 91 |
+
"""Elimina un usuario (para rechazar registros)."""
|
| 92 |
+
self.users = [u for u in self.users if u["username"] != username]
|
| 93 |
+
self.save()
|
| 94 |
+
return True
|
| 95 |
+
|
| 96 |
def get_by_username(self, username):
|
| 97 |
"""Busca un usuario por su nombre."""
|
| 98 |
for user in self.users:
|
|
|
|
| 113 |
def load_user(user_id):
|
| 114 |
"""Cargador de usuario para Flask-Login desde el JSON."""
|
| 115 |
user_data = user_mgr.get_by_id(user_id)
|
| 116 |
+
if user_data and user_data.get('status') == "ACTIVE":
|
| 117 |
return User(user_data['id'], user_data['username'])
|
| 118 |
return None
|
| 119 |
|
|
|
|
| 239 |
bot.edit_message_text(nuevo_texto, call.message.chat.id, call.message.message_id, parse_mode="Markdown")
|
| 240 |
else:
|
| 241 |
bot.answer_callback_query(call.id, "Error: El préstamo no está aceptado o no existe", show_alert=True)
|
| 242 |
+
|
| 243 |
+
elif call.data.startswith("approve_user_"):
|
| 244 |
+
username = call.data.replace("approve_user_", "")
|
| 245 |
+
if user_mgr.activate_user(username):
|
| 246 |
+
bot.answer_callback_query(call.id, "Usuario aprobado")
|
| 247 |
+
bot.edit_message_text(f"✅ *APROBADO:* El usuario `{username}` ya puede iniciar sesión.",
|
| 248 |
+
call.message.chat.id, call.message.message_id, parse_mode="Markdown")
|
| 249 |
+
socketio.emit('notification', {"text": f"Usuario {username} APROBADO", "color": "green"})
|
| 250 |
+
|
| 251 |
+
elif call.data.startswith("decline_user_"):
|
| 252 |
+
username = call.data.replace("decline_user_", "")
|
| 253 |
+
if user_mgr.delete_user(username):
|
| 254 |
+
bot.answer_callback_query(call.id, "Usuario rechazado")
|
| 255 |
+
bot.edit_message_text(f"❌ *RECHAZADO:* El registro de `{username}` ha sido eliminado.",
|
| 256 |
+
call.message.chat.id, call.message.message_id, parse_mode="Markdown")
|
| 257 |
|
| 258 |
except Exception as e:
|
| 259 |
print(f"Callback Error: {e}")
|
|
|
|
| 313 |
|
| 314 |
user_data = user_mgr.get_by_username(username)
|
| 315 |
|
| 316 |
+
if user_data:
|
| 317 |
+
if user_data.get('status') != "ACTIVE":
|
| 318 |
+
flash("Tu cuenta está pendiente de aprobación por un administrador.", "orange")
|
| 319 |
+
return render_template('login.html')
|
| 320 |
+
|
| 321 |
+
if check_password_hash(user_data['password'], password):
|
| 322 |
+
user = User(user_data['id'], user_data['username'])
|
| 323 |
+
login_user(user)
|
| 324 |
+
flash(f"¡Bienvenido de nuevo, {username}!", "green")
|
| 325 |
+
return redirect(url_for('repos'))
|
| 326 |
+
|
| 327 |
+
flash("Usuario o contraseña incorrectos", "red")
|
| 328 |
|
| 329 |
return render_template('login.html', title="Login")
|
| 330 |
|
|
|
|
| 342 |
flash("Las contraseñas no coinciden", "red")
|
| 343 |
return render_template('register.html')
|
| 344 |
|
| 345 |
+
if user_mgr.add_user(username, password, status="PENDING"):
|
| 346 |
+
# Notificar a Telegram sobre el nuevo registro
|
| 347 |
+
if bot and TG_CHAT_ID:
|
| 348 |
+
try:
|
| 349 |
+
markup = types.InlineKeyboardMarkup()
|
| 350 |
+
markup.add(
|
| 351 |
+
types.InlineKeyboardButton("✅ Aprobar", callback_data=f"approve_user_{username}"),
|
| 352 |
+
types.InlineKeyboardButton("❌ Rechazar", callback_data=f"decline_user_{username}")
|
| 353 |
+
)
|
| 354 |
+
bot.send_message(TG_CHAT_ID, f"👤 *NUEVO REGISTRO:* `{username}` solicita acceso.",
|
| 355 |
+
reply_markup=markup, parse_mode="Markdown")
|
| 356 |
+
except Exception as e:
|
| 357 |
+
print(f"Error TG Register: {e}")
|
| 358 |
+
|
| 359 |
+
flash("Registro enviado. Un administrador debe aprobar tu cuenta.", "blue")
|
| 360 |
return redirect(url_for('login'))
|
| 361 |
else:
|
| 362 |
flash("El nombre de usuario ya existe.", "red")
|