Gate cross-user admin endpoints behind require_super_user
Twenty-six endpoints documented "(admin only)" were using require_admin_key, which only checks the caller owns a wallet with its admin key — not LNbits-instance admin. Any logged-in user could fabricate receivables against any other user_id, grant themselves MANAGE permission on any account, create + self-assign privileged roles, etc. Swaps Depends(require_admin_key) -> Depends(require_super_user) on: receivable/revenue creation, equity-eligibility grant/revoke/list, permission grant/list/revoke/bulk/bulk-grant, account-sync admin, role + role-permission + user-role CRUD, cross-user contributions and unsettled-entries reports. Also deletes the unsafe duplicate /api/v1/pay-user — both function defs shared the name api_pay_user, the second shadowed the first at module scope but FastAPI registered both routes. /api/v1/payables/pay already provides the super-user-gated equivalent. Two pre-existing orphan wallet.wallet.user references inside api_settle_receivable and api_approve_manual_payment_request (both already used the auth parameter) would have raised NameError at runtime; fixed in passing. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
0a7c39adcb
commit
1201557f0c
1 changed files with 37 additions and 97 deletions
134
views_api.py
134
views_api.py
|
|
@ -9,7 +9,6 @@ from lnbits.core.models import User, WalletTypeInfo
|
||||||
from lnbits.decorators import (
|
from lnbits.decorators import (
|
||||||
check_super_user,
|
check_super_user,
|
||||||
check_user_exists,
|
check_user_exists,
|
||||||
require_admin_key,
|
|
||||||
require_invoice_key,
|
require_invoice_key,
|
||||||
)
|
)
|
||||||
from lnbits.utils.exchange_rates import allowed_currencies, fiat_amount_as_satoshis
|
from lnbits.utils.exchange_rates import allowed_currencies, fiat_amount_as_satoshis
|
||||||
|
|
@ -1334,7 +1333,7 @@ async def api_create_income_entry(
|
||||||
@libra_api_router.post("/api/v1/entries/receivable", status_code=HTTPStatus.CREATED)
|
@libra_api_router.post("/api/v1/entries/receivable", status_code=HTTPStatus.CREATED)
|
||||||
async def api_create_receivable_entry(
|
async def api_create_receivable_entry(
|
||||||
data: ReceivableEntry,
|
data: ReceivableEntry,
|
||||||
wallet: WalletTypeInfo = Depends(require_admin_key),
|
auth: AuthContext = Depends(require_super_user),
|
||||||
) -> JournalEntry:
|
) -> JournalEntry:
|
||||||
"""
|
"""
|
||||||
Create an accounts receivable entry (user owes libra).
|
Create an accounts receivable entry (user owes libra).
|
||||||
|
|
@ -1433,7 +1432,7 @@ async def api_create_receivable_entry(
|
||||||
id=entry_id, # Use the generated libra entry ID
|
id=entry_id, # Use the generated libra entry ID
|
||||||
description=data.description + description_suffix,
|
description=data.description + description_suffix,
|
||||||
entry_date=datetime.now(),
|
entry_date=datetime.now(),
|
||||||
created_by=wallet.wallet.user, # Use user_id, not wallet_id
|
created_by=auth.user_id,
|
||||||
created_at=datetime.now(),
|
created_at=datetime.now(),
|
||||||
reference=libra_reference, # Use libra reference with unique ID
|
reference=libra_reference, # Use libra reference with unique ID
|
||||||
flag=JournalEntryFlag.PENDING,
|
flag=JournalEntryFlag.PENDING,
|
||||||
|
|
@ -1462,7 +1461,7 @@ async def api_create_receivable_entry(
|
||||||
@libra_api_router.post("/api/v1/entries/revenue", status_code=HTTPStatus.CREATED)
|
@libra_api_router.post("/api/v1/entries/revenue", status_code=HTTPStatus.CREATED)
|
||||||
async def api_create_revenue_entry(
|
async def api_create_revenue_entry(
|
||||||
data: RevenueEntry,
|
data: RevenueEntry,
|
||||||
wallet: WalletTypeInfo = Depends(require_admin_key),
|
auth: AuthContext = Depends(require_super_user),
|
||||||
) -> JournalEntry:
|
) -> JournalEntry:
|
||||||
"""
|
"""
|
||||||
Create a revenue entry (libra receives payment).
|
Create a revenue entry (libra receives payment).
|
||||||
|
|
@ -1547,7 +1546,7 @@ async def api_create_revenue_entry(
|
||||||
id=entry_id,
|
id=entry_id,
|
||||||
description=data.description,
|
description=data.description,
|
||||||
entry_date=datetime.now(),
|
entry_date=datetime.now(),
|
||||||
created_by=wallet.wallet.user, # Use user_id, not wallet_id
|
created_by=auth.user_id,
|
||||||
created_at=datetime.now(),
|
created_at=datetime.now(),
|
||||||
reference=libra_reference,
|
reference=libra_reference,
|
||||||
flag=JournalEntryFlag.CLEARED,
|
flag=JournalEntryFlag.CLEARED,
|
||||||
|
|
@ -1934,65 +1933,6 @@ async def api_record_payment(
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@libra_api_router.post("/api/v1/pay-user")
|
|
||||||
async def api_pay_user(
|
|
||||||
user_id: str,
|
|
||||||
amount: int,
|
|
||||||
wallet: WalletTypeInfo = Depends(require_admin_key),
|
|
||||||
) -> dict:
|
|
||||||
"""
|
|
||||||
Record a payment from libra to user (reduces what libra owes user).
|
|
||||||
Admin only.
|
|
||||||
"""
|
|
||||||
# Get user's payable account (what libra owes)
|
|
||||||
user_payable = await get_or_create_user_account(
|
|
||||||
user_id, AccountType.LIABILITY, "Accounts Payable"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Get lightning account
|
|
||||||
lightning_account = await get_account_by_name("Assets:Bitcoin:Lightning")
|
|
||||||
if not lightning_account:
|
|
||||||
raise HTTPException(
|
|
||||||
status_code=HTTPStatus.NOT_FOUND, detail="Lightning account not found"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Format payment entry and submit to Fava
|
|
||||||
# DR Liabilities:Payable (User), CR Assets:Bitcoin:Lightning
|
|
||||||
from .fava_client import get_fava_client
|
|
||||||
from .beancount_format import format_payment_entry
|
|
||||||
|
|
||||||
fava = get_fava_client()
|
|
||||||
|
|
||||||
# Get unsettled expense entries to link to this settlement
|
|
||||||
unsettled = await fava.get_unsettled_entries_bql(user_id, "expense")
|
|
||||||
settled_links = [e["link"] for e in unsettled if e.get("link")]
|
|
||||||
|
|
||||||
entry = format_payment_entry(
|
|
||||||
user_id=user_id,
|
|
||||||
payment_account=lightning_account.name,
|
|
||||||
payable_or_receivable_account=user_payable.name,
|
|
||||||
amount_sats=amount,
|
|
||||||
description=f"Payment to user {user_id[:8]}",
|
|
||||||
entry_date=datetime.now().date(),
|
|
||||||
is_payable=True, # Libra paying user
|
|
||||||
reference=f"PAY-{user_id[:8]}",
|
|
||||||
settled_entry_links=settled_links
|
|
||||||
)
|
|
||||||
|
|
||||||
# Submit to Fava
|
|
||||||
result = await fava.add_entry(entry)
|
|
||||||
logger.info(f"Payment submitted to Fava: {result.get('data', 'Unknown')}")
|
|
||||||
|
|
||||||
# Get updated balance from Fava
|
|
||||||
balance_data = await fava.get_user_balance_bql(user_id)
|
|
||||||
|
|
||||||
return {
|
|
||||||
"journal_entry_id": f"fava-{datetime.now().timestamp()}",
|
|
||||||
"new_balance": balance_data["balance"],
|
|
||||||
"message": "Payment recorded successfully",
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@libra_api_router.post("/api/v1/receivables/settle")
|
@libra_api_router.post("/api/v1/receivables/settle")
|
||||||
async def api_settle_receivable(
|
async def api_settle_receivable(
|
||||||
data: SettleReceivable,
|
data: SettleReceivable,
|
||||||
|
|
@ -2119,7 +2059,7 @@ async def api_settle_receivable(
|
||||||
if "meta" not in entry:
|
if "meta" not in entry:
|
||||||
entry["meta"] = {}
|
entry["meta"] = {}
|
||||||
entry["meta"]["payment-method"] = data.payment_method
|
entry["meta"]["payment-method"] = data.payment_method
|
||||||
entry["meta"]["settled-by"] = wallet.wallet.user
|
entry["meta"]["settled-by"] = auth.user_id
|
||||||
if data.txid:
|
if data.txid:
|
||||||
entry["meta"]["txid"] = data.txid
|
entry["meta"]["txid"] = data.txid
|
||||||
|
|
||||||
|
|
@ -2493,7 +2433,7 @@ async def api_expense_report(
|
||||||
|
|
||||||
@libra_api_router.get("/api/v1/reports/contributions")
|
@libra_api_router.get("/api/v1/reports/contributions")
|
||||||
async def api_contributions_report(
|
async def api_contributions_report(
|
||||||
wallet: WalletTypeInfo = Depends(require_admin_key),
|
auth: AuthContext = Depends(require_super_user),
|
||||||
) -> dict:
|
) -> dict:
|
||||||
"""
|
"""
|
||||||
Get user contribution report using BQL.
|
Get user contribution report using BQL.
|
||||||
|
|
@ -2562,7 +2502,7 @@ async def api_contributions_report(
|
||||||
async def api_get_unsettled_entries(
|
async def api_get_unsettled_entries(
|
||||||
user_id: str,
|
user_id: str,
|
||||||
entry_type: str = "expense",
|
entry_type: str = "expense",
|
||||||
wallet: WalletTypeInfo = Depends(require_admin_key),
|
auth: AuthContext = Depends(require_super_user),
|
||||||
) -> dict:
|
) -> dict:
|
||||||
"""
|
"""
|
||||||
Get unsettled expense or receivable entries for a user.
|
Get unsettled expense or receivable entries for a user.
|
||||||
|
|
@ -2770,7 +2710,7 @@ async def api_approve_manual_payment_request(
|
||||||
# Approve the request with Fava entry reference
|
# Approve the request with Fava entry reference
|
||||||
entry_id = f"fava-{datetime.now().timestamp()}"
|
entry_id = f"fava-{datetime.now().timestamp()}"
|
||||||
return await approve_manual_payment_request(
|
return await approve_manual_payment_request(
|
||||||
request_id, wallet.wallet.user, entry_id
|
request_id, auth.user_id, entry_id
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -3344,18 +3284,18 @@ async def api_get_user_info(
|
||||||
@libra_api_router.post("/api/v1/admin/equity-eligibility", status_code=HTTPStatus.CREATED)
|
@libra_api_router.post("/api/v1/admin/equity-eligibility", status_code=HTTPStatus.CREATED)
|
||||||
async def api_grant_equity_eligibility(
|
async def api_grant_equity_eligibility(
|
||||||
data: CreateUserEquityStatus,
|
data: CreateUserEquityStatus,
|
||||||
wallet: WalletTypeInfo = Depends(require_admin_key),
|
auth: AuthContext = Depends(require_super_user),
|
||||||
) -> UserEquityStatus:
|
) -> UserEquityStatus:
|
||||||
"""Grant equity contribution eligibility to a user (admin only)"""
|
"""Grant equity contribution eligibility to a user (admin only)"""
|
||||||
from .crud import create_or_update_user_equity_status
|
from .crud import create_or_update_user_equity_status
|
||||||
|
|
||||||
return await create_or_update_user_equity_status(data, wallet.wallet.user)
|
return await create_or_update_user_equity_status(data, auth.user_id)
|
||||||
|
|
||||||
|
|
||||||
@libra_api_router.delete("/api/v1/admin/equity-eligibility/{user_id}")
|
@libra_api_router.delete("/api/v1/admin/equity-eligibility/{user_id}")
|
||||||
async def api_revoke_equity_eligibility(
|
async def api_revoke_equity_eligibility(
|
||||||
user_id: str,
|
user_id: str,
|
||||||
wallet: WalletTypeInfo = Depends(require_admin_key),
|
auth: AuthContext = Depends(require_super_user),
|
||||||
) -> UserEquityStatus:
|
) -> UserEquityStatus:
|
||||||
"""Revoke equity contribution eligibility from a user (admin only)"""
|
"""Revoke equity contribution eligibility from a user (admin only)"""
|
||||||
from .crud import revoke_user_equity_eligibility
|
from .crud import revoke_user_equity_eligibility
|
||||||
|
|
@ -3371,7 +3311,7 @@ async def api_revoke_equity_eligibility(
|
||||||
|
|
||||||
@libra_api_router.get("/api/v1/admin/equity-eligibility")
|
@libra_api_router.get("/api/v1/admin/equity-eligibility")
|
||||||
async def api_list_equity_eligible_users(
|
async def api_list_equity_eligible_users(
|
||||||
wallet: WalletTypeInfo = Depends(require_admin_key),
|
auth: AuthContext = Depends(require_super_user),
|
||||||
) -> list[UserEquityStatus]:
|
) -> list[UserEquityStatus]:
|
||||||
"""List all equity-eligible users (admin only)"""
|
"""List all equity-eligible users (admin only)"""
|
||||||
from .crud import get_all_equity_eligible_users
|
from .crud import get_all_equity_eligible_users
|
||||||
|
|
@ -3385,7 +3325,7 @@ async def api_list_equity_eligible_users(
|
||||||
@libra_api_router.post("/api/v1/admin/permissions", status_code=HTTPStatus.CREATED)
|
@libra_api_router.post("/api/v1/admin/permissions", status_code=HTTPStatus.CREATED)
|
||||||
async def api_grant_permission(
|
async def api_grant_permission(
|
||||||
data: CreateAccountPermission,
|
data: CreateAccountPermission,
|
||||||
wallet: WalletTypeInfo = Depends(require_admin_key),
|
auth: AuthContext = Depends(require_super_user),
|
||||||
) -> AccountPermission:
|
) -> AccountPermission:
|
||||||
"""Grant account permission to a user (admin only)"""
|
"""Grant account permission to a user (admin only)"""
|
||||||
# Validate that account exists
|
# Validate that account exists
|
||||||
|
|
@ -3396,14 +3336,14 @@ async def api_grant_permission(
|
||||||
detail=f"Account with ID '{data.account_id}' not found",
|
detail=f"Account with ID '{data.account_id}' not found",
|
||||||
)
|
)
|
||||||
|
|
||||||
return await create_account_permission(data, wallet.wallet.user)
|
return await create_account_permission(data, auth.user_id)
|
||||||
|
|
||||||
|
|
||||||
@libra_api_router.get("/api/v1/admin/permissions")
|
@libra_api_router.get("/api/v1/admin/permissions")
|
||||||
async def api_list_permissions(
|
async def api_list_permissions(
|
||||||
user_id: str | None = None,
|
user_id: str | None = None,
|
||||||
account_id: str | None = None,
|
account_id: str | None = None,
|
||||||
wallet: WalletTypeInfo = Depends(require_admin_key),
|
auth: AuthContext = Depends(require_super_user),
|
||||||
) -> list[AccountPermission]:
|
) -> list[AccountPermission]:
|
||||||
"""
|
"""
|
||||||
List account permissions (admin only).
|
List account permissions (admin only).
|
||||||
|
|
@ -3436,7 +3376,7 @@ async def api_list_permissions(
|
||||||
@libra_api_router.delete("/api/v1/admin/permissions/{permission_id}")
|
@libra_api_router.delete("/api/v1/admin/permissions/{permission_id}")
|
||||||
async def api_revoke_permission(
|
async def api_revoke_permission(
|
||||||
permission_id: str,
|
permission_id: str,
|
||||||
wallet: WalletTypeInfo = Depends(require_admin_key),
|
auth: AuthContext = Depends(require_super_user),
|
||||||
) -> dict:
|
) -> dict:
|
||||||
"""Revoke (delete) an account permission (admin only)"""
|
"""Revoke (delete) an account permission (admin only)"""
|
||||||
# Verify permission exists
|
# Verify permission exists
|
||||||
|
|
@ -3458,7 +3398,7 @@ async def api_revoke_permission(
|
||||||
@libra_api_router.post("/api/v1/admin/permissions/bulk", status_code=HTTPStatus.CREATED)
|
@libra_api_router.post("/api/v1/admin/permissions/bulk", status_code=HTTPStatus.CREATED)
|
||||||
async def api_bulk_grant_permissions(
|
async def api_bulk_grant_permissions(
|
||||||
permissions: list[CreateAccountPermission],
|
permissions: list[CreateAccountPermission],
|
||||||
wallet: WalletTypeInfo = Depends(require_admin_key),
|
auth: AuthContext = Depends(require_super_user),
|
||||||
) -> list[AccountPermission]:
|
) -> list[AccountPermission]:
|
||||||
"""Grant multiple account permissions at once (admin only)"""
|
"""Grant multiple account permissions at once (admin only)"""
|
||||||
created_permissions = []
|
created_permissions = []
|
||||||
|
|
@ -3472,7 +3412,7 @@ async def api_bulk_grant_permissions(
|
||||||
detail=f"Account with ID '{perm_data.account_id}' not found",
|
detail=f"Account with ID '{perm_data.account_id}' not found",
|
||||||
)
|
)
|
||||||
|
|
||||||
perm = await create_account_permission(perm_data, wallet.wallet.user)
|
perm = await create_account_permission(perm_data, auth.user_id)
|
||||||
created_permissions.append(perm)
|
created_permissions.append(perm)
|
||||||
|
|
||||||
return created_permissions
|
return created_permissions
|
||||||
|
|
@ -3481,7 +3421,7 @@ async def api_bulk_grant_permissions(
|
||||||
@libra_api_router.post("/api/v1/admin/permissions/bulk-grant", status_code=HTTPStatus.CREATED)
|
@libra_api_router.post("/api/v1/admin/permissions/bulk-grant", status_code=HTTPStatus.CREATED)
|
||||||
async def api_bulk_grant_permission_to_users(
|
async def api_bulk_grant_permission_to_users(
|
||||||
data: "BulkGrantPermission",
|
data: "BulkGrantPermission",
|
||||||
wallet: WalletTypeInfo = Depends(require_admin_key),
|
auth: AuthContext = Depends(require_super_user),
|
||||||
) -> "BulkGrantResult":
|
) -> "BulkGrantResult":
|
||||||
"""
|
"""
|
||||||
Grant the same permission to multiple users at once (admin only).
|
Grant the same permission to multiple users at once (admin only).
|
||||||
|
|
@ -3515,7 +3455,7 @@ async def api_bulk_grant_permission_to_users(
|
||||||
expires_at=data.expires_at,
|
expires_at=data.expires_at,
|
||||||
notes=data.notes,
|
notes=data.notes,
|
||||||
)
|
)
|
||||||
perm = await create_account_permission(perm_data, wallet.wallet.user)
|
perm = await create_account_permission(perm_data, auth.user_id)
|
||||||
granted.append(perm)
|
granted.append(perm)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
failed.append({
|
failed.append({
|
||||||
|
|
@ -3628,7 +3568,7 @@ async def api_get_account_hierarchy(
|
||||||
@libra_api_router.post("/api/v1/admin/accounts/sync")
|
@libra_api_router.post("/api/v1/admin/accounts/sync")
|
||||||
async def api_sync_all_accounts(
|
async def api_sync_all_accounts(
|
||||||
force_full_sync: bool = False,
|
force_full_sync: bool = False,
|
||||||
wallet: WalletTypeInfo = Depends(require_admin_key),
|
auth: AuthContext = Depends(require_super_user),
|
||||||
) -> dict:
|
) -> dict:
|
||||||
"""
|
"""
|
||||||
Sync all accounts from Beancount to Libra DB (admin only).
|
Sync all accounts from Beancount to Libra DB (admin only).
|
||||||
|
|
@ -3644,7 +3584,7 @@ async def api_sync_all_accounts(
|
||||||
"""
|
"""
|
||||||
from .account_sync import sync_accounts_from_beancount
|
from .account_sync import sync_accounts_from_beancount
|
||||||
|
|
||||||
logger.info(f"Admin {wallet.wallet.user[:8]} triggered account sync (force={force_full_sync})")
|
logger.info(f"Admin {auth.user_id[:8]} triggered account sync (force={force_full_sync})")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
stats = await sync_accounts_from_beancount(force_full_sync=force_full_sync)
|
stats = await sync_accounts_from_beancount(force_full_sync=force_full_sync)
|
||||||
|
|
@ -3661,7 +3601,7 @@ async def api_sync_all_accounts(
|
||||||
@libra_api_router.post("/api/v1/admin/accounts/sync/{account_name:path}")
|
@libra_api_router.post("/api/v1/admin/accounts/sync/{account_name:path}")
|
||||||
async def api_sync_single_account(
|
async def api_sync_single_account(
|
||||||
account_name: str,
|
account_name: str,
|
||||||
wallet: WalletTypeInfo = Depends(require_admin_key),
|
auth: AuthContext = Depends(require_super_user),
|
||||||
) -> dict:
|
) -> dict:
|
||||||
"""
|
"""
|
||||||
Sync a single account from Beancount to Libra DB (admin only).
|
Sync a single account from Beancount to Libra DB (admin only).
|
||||||
|
|
@ -3677,7 +3617,7 @@ async def api_sync_single_account(
|
||||||
"""
|
"""
|
||||||
from .account_sync import sync_single_account_from_beancount
|
from .account_sync import sync_single_account_from_beancount
|
||||||
|
|
||||||
logger.info(f"Admin {wallet.wallet.user[:8]} triggered sync for account: {account_name}")
|
logger.info(f"Admin {auth.user_id[:8]} triggered sync for account: {account_name}")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
created = await sync_single_account_from_beancount(account_name)
|
created = await sync_single_account_from_beancount(account_name)
|
||||||
|
|
@ -3707,7 +3647,7 @@ async def api_sync_single_account(
|
||||||
|
|
||||||
@libra_api_router.get("/api/v1/admin/roles")
|
@libra_api_router.get("/api/v1/admin/roles")
|
||||||
async def api_get_all_roles(
|
async def api_get_all_roles(
|
||||||
wallet: WalletTypeInfo = Depends(require_admin_key),
|
auth: AuthContext = Depends(require_super_user),
|
||||||
) -> list:
|
) -> list:
|
||||||
"""Get all roles (admin only)"""
|
"""Get all roles (admin only)"""
|
||||||
from . import crud
|
from . import crud
|
||||||
|
|
@ -3737,13 +3677,13 @@ async def api_get_all_roles(
|
||||||
@libra_api_router.post("/api/v1/admin/roles", status_code=HTTPStatus.CREATED)
|
@libra_api_router.post("/api/v1/admin/roles", status_code=HTTPStatus.CREATED)
|
||||||
async def api_create_role(
|
async def api_create_role(
|
||||||
data: CreateRole,
|
data: CreateRole,
|
||||||
wallet: WalletTypeInfo = Depends(require_admin_key),
|
auth: AuthContext = Depends(require_super_user),
|
||||||
):
|
):
|
||||||
"""Create a new role (admin only)"""
|
"""Create a new role (admin only)"""
|
||||||
from . import crud
|
from . import crud
|
||||||
|
|
||||||
try:
|
try:
|
||||||
role = await crud.create_role(data, created_by=wallet.wallet.user)
|
role = await crud.create_role(data, created_by=auth.user_id)
|
||||||
return {
|
return {
|
||||||
"id": role.id,
|
"id": role.id,
|
||||||
"name": role.name,
|
"name": role.name,
|
||||||
|
|
@ -3763,7 +3703,7 @@ async def api_create_role(
|
||||||
@libra_api_router.get("/api/v1/admin/roles/{role_id}")
|
@libra_api_router.get("/api/v1/admin/roles/{role_id}")
|
||||||
async def api_get_role(
|
async def api_get_role(
|
||||||
role_id: str,
|
role_id: str,
|
||||||
wallet: WalletTypeInfo = Depends(require_admin_key),
|
auth: AuthContext = Depends(require_super_user),
|
||||||
):
|
):
|
||||||
"""Get a specific role with its permissions and users (admin only)"""
|
"""Get a specific role with its permissions and users (admin only)"""
|
||||||
from . import crud
|
from . import crud
|
||||||
|
|
@ -3813,7 +3753,7 @@ async def api_get_role(
|
||||||
async def api_update_role(
|
async def api_update_role(
|
||||||
role_id: str,
|
role_id: str,
|
||||||
data: UpdateRole,
|
data: UpdateRole,
|
||||||
wallet: WalletTypeInfo = Depends(require_admin_key),
|
auth: AuthContext = Depends(require_super_user),
|
||||||
):
|
):
|
||||||
"""Update a role (admin only)"""
|
"""Update a role (admin only)"""
|
||||||
from . import crud
|
from . import crud
|
||||||
|
|
@ -3838,7 +3778,7 @@ async def api_update_role(
|
||||||
@libra_api_router.delete("/api/v1/admin/roles/{role_id}")
|
@libra_api_router.delete("/api/v1/admin/roles/{role_id}")
|
||||||
async def api_delete_role(
|
async def api_delete_role(
|
||||||
role_id: str,
|
role_id: str,
|
||||||
wallet: WalletTypeInfo = Depends(require_admin_key),
|
auth: AuthContext = Depends(require_super_user),
|
||||||
):
|
):
|
||||||
"""Delete a role (admin only) - cascades to role_permissions and user_roles"""
|
"""Delete a role (admin only) - cascades to role_permissions and user_roles"""
|
||||||
from . import crud
|
from . import crud
|
||||||
|
|
@ -3861,7 +3801,7 @@ async def api_delete_role(
|
||||||
async def api_add_role_permission(
|
async def api_add_role_permission(
|
||||||
role_id: str,
|
role_id: str,
|
||||||
data: CreateRolePermission,
|
data: CreateRolePermission,
|
||||||
wallet: WalletTypeInfo = Depends(require_admin_key),
|
auth: AuthContext = Depends(require_super_user),
|
||||||
):
|
):
|
||||||
"""Add a permission to a role (admin only)"""
|
"""Add a permission to a role (admin only)"""
|
||||||
from . import crud
|
from . import crud
|
||||||
|
|
@ -3899,7 +3839,7 @@ async def api_add_role_permission(
|
||||||
async def api_delete_role_permission(
|
async def api_delete_role_permission(
|
||||||
role_id: str,
|
role_id: str,
|
||||||
permission_id: str,
|
permission_id: str,
|
||||||
wallet: WalletTypeInfo = Depends(require_admin_key),
|
auth: AuthContext = Depends(require_super_user),
|
||||||
):
|
):
|
||||||
"""Remove a permission from a role (admin only)"""
|
"""Remove a permission from a role (admin only)"""
|
||||||
from . import crud
|
from . import crud
|
||||||
|
|
@ -3914,7 +3854,7 @@ async def api_delete_role_permission(
|
||||||
@libra_api_router.post("/api/v1/admin/user-roles", status_code=HTTPStatus.CREATED)
|
@libra_api_router.post("/api/v1/admin/user-roles", status_code=HTTPStatus.CREATED)
|
||||||
async def api_assign_user_role(
|
async def api_assign_user_role(
|
||||||
data: AssignUserRole,
|
data: AssignUserRole,
|
||||||
wallet: WalletTypeInfo = Depends(require_admin_key),
|
auth: AuthContext = Depends(require_super_user),
|
||||||
):
|
):
|
||||||
"""Assign a user to a role (admin only)"""
|
"""Assign a user to a role (admin only)"""
|
||||||
from . import crud
|
from . import crud
|
||||||
|
|
@ -3928,7 +3868,7 @@ async def api_assign_user_role(
|
||||||
)
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
user_role = await crud.assign_user_role(data, granted_by=wallet.wallet.user)
|
user_role = await crud.assign_user_role(data, granted_by=auth.user_id)
|
||||||
return {
|
return {
|
||||||
"id": user_role.id,
|
"id": user_role.id,
|
||||||
"user_id": user_role.user_id,
|
"user_id": user_role.user_id,
|
||||||
|
|
@ -3949,7 +3889,7 @@ async def api_assign_user_role(
|
||||||
@libra_api_router.get("/api/v1/admin/user-roles/{user_id}")
|
@libra_api_router.get("/api/v1/admin/user-roles/{user_id}")
|
||||||
async def api_get_user_roles(
|
async def api_get_user_roles(
|
||||||
user_id: str,
|
user_id: str,
|
||||||
wallet: WalletTypeInfo = Depends(require_admin_key),
|
auth: AuthContext = Depends(require_super_user),
|
||||||
):
|
):
|
||||||
"""Get all roles assigned to a user (admin only)"""
|
"""Get all roles assigned to a user (admin only)"""
|
||||||
from . import crud
|
from . import crud
|
||||||
|
|
@ -3982,7 +3922,7 @@ async def api_get_user_roles(
|
||||||
@libra_api_router.delete("/api/v1/admin/user-roles/{user_role_id}")
|
@libra_api_router.delete("/api/v1/admin/user-roles/{user_role_id}")
|
||||||
async def api_revoke_user_role(
|
async def api_revoke_user_role(
|
||||||
user_role_id: str,
|
user_role_id: str,
|
||||||
wallet: WalletTypeInfo = Depends(require_admin_key),
|
auth: AuthContext = Depends(require_super_user),
|
||||||
):
|
):
|
||||||
"""Revoke a user's role assignment (admin only)"""
|
"""Revoke a user's role assignment (admin only)"""
|
||||||
from . import crud
|
from . import crud
|
||||||
|
|
@ -3993,7 +3933,7 @@ async def api_revoke_user_role(
|
||||||
|
|
||||||
@libra_api_router.get("/api/v1/admin/users/roles")
|
@libra_api_router.get("/api/v1/admin/users/roles")
|
||||||
async def api_get_all_user_roles(
|
async def api_get_all_user_roles(
|
||||||
wallet: WalletTypeInfo = Depends(require_admin_key),
|
auth: AuthContext = Depends(require_super_user),
|
||||||
):
|
):
|
||||||
"""Get all user role assignments (admin only)"""
|
"""Get all user role assignments (admin only)"""
|
||||||
from . import crud
|
from . import crud
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue