Add admin token override feature for user accounts
- Add tokenOverride field to token usage bucket - Create POST /api/admin/accounts/tokens endpoint for setting manual token limits - Update admin accounts page to display token usage and override status - Add 'Set Tokens' button to manually override user token limits for the month - Override takes precedence over plan-based limits when set
This commit is contained in:
@@ -78,6 +78,7 @@
|
||||
<th style="padding:12px 8px;">Renews</th>
|
||||
<th style="padding:12px 8px;">Created</th>
|
||||
<th style="padding:12px 8px;">Last login</th>
|
||||
<th style="padding:12px 8px;">Tokens</th>
|
||||
<th style="padding:12px 8px;">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
@@ -1713,7 +1713,7 @@
|
||||
if (!state.accounts.length) {
|
||||
const row = document.createElement('tr');
|
||||
const cell = document.createElement('td');
|
||||
cell.colSpan = 8;
|
||||
cell.colSpan = 9;
|
||||
cell.textContent = 'No accounts found.';
|
||||
cell.className = 'muted';
|
||||
cell.style.padding = '12px';
|
||||
@@ -1739,6 +1739,18 @@
|
||||
row.appendChild(cell);
|
||||
});
|
||||
|
||||
const tokenUsage = acct.tokenUsage || {};
|
||||
const tokensUsed = tokenUsage.used || 0;
|
||||
const tokensLimit = tokenUsage.limit || 0;
|
||||
const tokenOverride = tokenUsage.tokenOverride;
|
||||
const tokensDisplay = `${tokensUsed.toLocaleString()} / ${tokensLimit.toLocaleString()}${tokenOverride !== null && tokenOverride !== undefined ? ' (override)' : ''}`;
|
||||
|
||||
const tokenCell = document.createElement('td');
|
||||
tokenCell.style.padding = '10px 8px';
|
||||
tokenCell.textContent = tokensDisplay;
|
||||
tokenCell.title = tokenOverride !== null && tokenOverride !== undefined ? `Manual override: ${tokenOverride.toLocaleString()} tokens` : 'Plan-based limit';
|
||||
row.appendChild(tokenCell);
|
||||
|
||||
const actionsCell = document.createElement('td');
|
||||
actionsCell.style.padding = '10px 8px';
|
||||
actionsCell.style.display = 'flex';
|
||||
@@ -1750,6 +1762,13 @@
|
||||
changeBtn.addEventListener('click', () => changePlan(acct));
|
||||
actionsCell.appendChild(changeBtn);
|
||||
|
||||
const tokensBtn = document.createElement('button');
|
||||
tokensBtn.className = 'ghost';
|
||||
tokensBtn.textContent = 'Set Tokens';
|
||||
tokensBtn.title = 'Manually set token limit for this user';
|
||||
tokensBtn.addEventListener('click', () => setTokens(acct));
|
||||
actionsCell.appendChild(tokensBtn);
|
||||
|
||||
const deleteBtn = document.createElement('button');
|
||||
deleteBtn.className = 'danger';
|
||||
deleteBtn.textContent = 'Delete';
|
||||
@@ -1830,6 +1849,46 @@
|
||||
}
|
||||
}
|
||||
|
||||
async function setTokens(acct) {
|
||||
const tokenUsage = acct.tokenUsage || {};
|
||||
const currentLimit = tokenUsage.limit || 0;
|
||||
const hasOverride = tokenUsage.tokenOverride !== null && tokenUsage.tokenOverride !== undefined;
|
||||
const currentOverride = hasOverride ? tokenUsage.tokenOverride : '';
|
||||
|
||||
const promptMessage = `Set token limit for ${acct.email}\n\n` +
|
||||
`Current plan: ${acct.plan || 'starter'}\n` +
|
||||
`Current limit: ${currentLimit.toLocaleString()} tokens\n` +
|
||||
`${hasOverride ? `Current override: ${currentOverride.toLocaleString()} tokens\n` : ''}\n` +
|
||||
`Enter new token limit (0 to remove override, or a number to set manual limit):`;
|
||||
|
||||
const tokenInput = prompt(promptMessage, currentOverride);
|
||||
|
||||
if (tokenInput === null) return;
|
||||
|
||||
const tokens = parseInt(tokenInput.trim(), 10);
|
||||
if (isNaN(tokens) || tokens < 0) {
|
||||
alert('Invalid token amount. Please enter a non-negative number.');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!confirm(`Are you sure you want to set ${acct.email}'s token limit to ${tokens.toLocaleString()}? This will override their plan-based limit for this month.`)) {
|
||||
return;
|
||||
}
|
||||
|
||||
setStatus(`Updating token limit for ${acct.email}...`);
|
||||
try {
|
||||
await api('/api/admin/accounts/tokens', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ userId: acct.id, tokens: tokens })
|
||||
});
|
||||
setStatus('Token limit updated successfully');
|
||||
await loadAccounts();
|
||||
setTimeout(() => setStatus(''), 3000);
|
||||
} catch (err) {
|
||||
setStatus(err.message, true);
|
||||
}
|
||||
}
|
||||
|
||||
async function loadAccounts() {
|
||||
if (!el.accountsTable) return;
|
||||
setStatus('Loading accounts...');
|
||||
|
||||
Reference in New Issue
Block a user