refactor: simplify queries

This commit is contained in:
Vlad Stan
2026-02-03 18:10:41 +02:00
parent bf1ad185b9
commit 31a2d68285
4 changed files with 29 additions and 43 deletions
+23 -37
View File
@@ -121,27 +121,18 @@ async def get_account(
if len(user_id) == 0: if len(user_id) == 0:
return None return None
activate_clause = "" if activated is None else "AND activated = :activated"
return await (conn or db).fetchone( return await (conn or db).fetchone(
f""" f"""
SELECT * FROM accounts SELECT * FROM accounts
WHERE id = :id {_activated_clause(activated)} WHERE id = :id {activate_clause}
""", # noqa: S608 """, # noqa: S608
{"id": user_id, "activated": activated}, {"id": user_id, "activated": activated},
Account, Account,
) )
async def is_account_activated(
user_id: str, conn: Connection | None = None
) -> bool | None:
result = await (conn or db).execute(
"SELECT activated FROM accounts WHERE id = :id",
{"id": user_id},
)
row = result.mappings().first()
return row.get("activated", False) if row is not None else None
async def delete_accounts_no_wallets( async def delete_accounts_no_wallets(
time_delta: int, time_delta: int,
conn: Connection | None = None, conn: Connection | None = None,
@@ -163,16 +154,16 @@ async def delete_accounts_no_wallets(
async def get_account_by_username( async def get_account_by_username(
username: str, activated: bool | None = True, conn: Connection | None = None username: str, activated: bool = True, conn: Connection | None = None
) -> Account | None: ) -> Account | None:
if len(username) == 0: if len(username) == 0:
return None return None
return await (conn or db).fetchone( return await (conn or db).fetchone(
f""" """
SELECT * FROM accounts SELECT * FROM accounts
WHERE LOWER(username) = :username {_activated_clause(activated)} WHERE LOWER(username) = :username AND activated = :activated
""", # noqa: S608 """,
{"username": username.lower(), "activated": activated}, {"username": username.lower(), "activated": activated},
Account, Account,
) )
@@ -182,26 +173,26 @@ async def get_account_by_pubkey(
pubkey: str, activated: bool | None = True, conn: Connection | None = None pubkey: str, activated: bool | None = True, conn: Connection | None = None
) -> Account | None: ) -> Account | None:
return await (conn or db).fetchone( return await (conn or db).fetchone(
f""" """
SELECT * FROM accounts SELECT * FROM accounts
WHERE LOWER(pubkey) = :pubkey {_activated_clause(activated)} WHERE LOWER(pubkey) = :pubkey AND activated = :activated
""", # noqa: S608 """,
{"pubkey": pubkey.lower(), "activated": activated}, {"pubkey": pubkey.lower(), "activated": activated},
Account, Account,
) )
async def get_account_by_email( async def get_account_by_email(
email: str, activated: bool | None = True, conn: Connection | None = None email: str, activated: bool = True, conn: Connection | None = None
) -> Account | None: ) -> Account | None:
if len(email) == 0: if len(email) == 0:
return None return None
return await (conn or db).fetchone( return await (conn or db).fetchone(
f""" """
SELECT * FROM accounts SELECT * FROM accounts
WHERE LOWER(email) = :email {_activated_clause(activated)} WHERE LOWER(email) = :email AND activated = :activated
""", # noqa: S608 """,
{"email": email.lower(), "activated": activated}, {"email": email.lower(), "activated": activated},
Account, Account,
) )
@@ -209,16 +200,16 @@ async def get_account_by_email(
async def get_account_by_username_or_email( async def get_account_by_username_or_email(
username_or_email: str, username_or_email: str,
activated: bool | None = True, activated: bool = True,
conn: Connection | None = None, conn: Connection | None = None,
) -> Account | None: ) -> Account | None:
return await (conn or db).fetchone( return await (conn or db).fetchone(
f""" """
SELECT * FROM accounts SELECT * FROM accounts
WHERE (LOWER(email) = :value or LOWER(username) = :value) WHERE (LOWER(email) = :value or LOWER(username) = :value)
{_activated_clause(activated)} AND activated = :activated
""", # noqa: S608 """,
{"value": username_or_email.lower(), "activated": activated}, {"value": username_or_email.lower(), "activated": activated},
Account, Account,
) )
@@ -247,6 +238,7 @@ async def get_user_from_account(
return User( return User(
id=account.id, id=account.id,
activated=account.activated,
email=account.email, email=account.email,
username=account.username, username=account.username,
pubkey=account.pubkey, pubkey=account.pubkey,
@@ -272,13 +264,13 @@ async def update_user_access_control_list(
async def get_user_access_control_lists( async def get_user_access_control_lists(
user_id: str, activated: bool | None = True, conn: Connection | None = None user_id: str, activated: bool = True, conn: Connection | None = None
) -> UserAcls: ) -> UserAcls:
user_acls = await (conn or db).fetchone( user_acls = await (conn or db).fetchone(
f""" """
SELECT id, access_control_list FROM accounts SELECT id, access_control_list FROM accounts
WHERE id = :user_id {_activated_clause(activated)} WHERE id = :user_id AND activated = :activated
""", # noqa: S608 """,
{"user_id": user_id, "activated": activated}, {"user_id": user_id, "activated": activated},
UserAcls, UserAcls,
) )
@@ -300,9 +292,3 @@ def clear_user_cache(user: User):
cache.pop(user_cache_key) cache.pop(user_cache_key)
for wallet in user.wallets: for wallet in user.wallets:
clear_wallet_cache(wallet) clear_wallet_cache(wallet)
def _activated_clause(activated: bool | None) -> str:
if activated is None:
return ""
return "AND activated = :activated"
+1 -1
View File
@@ -83,7 +83,7 @@ async def login(data: LoginUsernamePassword) -> JSONResponse:
raise HTTPException( raise HTTPException(
HTTPStatus.FORBIDDEN, "Login by 'Username and Password' not allowed." HTTPStatus.FORBIDDEN, "Login by 'Username and Password' not allowed."
) )
account = await get_account_by_username_or_email(data.username, activated=None) account = await get_account_by_username_or_email(data.username)
if not account or not account.verify_password(data.password): if not account or not account.verify_password(data.password):
raise HTTPException(HTTPStatus.UNAUTHORIZED, "Invalid credentials.") raise HTTPException(HTTPStatus.UNAUTHORIZED, "Invalid credentials.")
+3 -3
View File
@@ -20,7 +20,7 @@ from lnbits.core.crud import (
update_admin_settings, update_admin_settings,
update_wallet, update_wallet,
) )
from lnbits.core.crud.users import get_account from lnbits.core.crud.users import get_account, update_account
from lnbits.core.crud.wallets import delete_wallet_by_id from lnbits.core.crud.wallets import delete_wallet_by_id
from lnbits.core.models import ( from lnbits.core.models import (
AccountFilters, AccountFilters,
@@ -242,14 +242,14 @@ async def api_users_toggle_activated(
if settings.is_admin_user(user_id): if settings.is_admin_user(user_id):
settings.lnbits_admin_users.remove(user_id) settings.lnbits_admin_users.remove(user_id)
user_account = await get_account(user_id) user_account = await get_account(user_id, activated=None)
if not user_account: if not user_account:
raise HTTPException( raise HTTPException(
status_code=HTTPStatus.NOT_FOUND, status_code=HTTPStatus.NOT_FOUND,
detail="User not found.", detail="User not found.",
) )
user_account.activated = not user_account.activated user_account.activated = not user_account.activated
await update_user_account(user_account) await update_account(user_account)
return SimpleStatus( return SimpleStatus(
success=True, success=True,
+2 -2
View File
@@ -658,8 +658,8 @@ async def test_user_activation(
response = await http_client.post( response = await http_client.post(
"/api/v1/auth", json={"username": username, "password": "secret1234"} "/api/v1/auth", json={"username": username, "password": "secret1234"}
) )
assert response.status_code == 403 assert response.status_code == 401
assert response.json().get("detail") == "Account is not activated." assert response.json().get("detail") == "Invalid credentials."
response = await http_client.get( response = await http_client.get(
"/api/v1/auth", "/api/v1/auth",