114 lines
4.8 KiB
Plaintext
114 lines
4.8 KiB
Plaintext
<%- include("../_partials/admin-header", { title: "Users - OAI Reverse Proxy Admin" }) %>
|
|
<h1>User Token List</h1>
|
|
|
|
<!-- <input type="hidden" name="_csrf" value="<%= csrfToken %>" /> -->
|
|
<% if (users.length === 0) { %>
|
|
<p>No users found.</p>
|
|
<% } else { %>
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>User Token</th>
|
|
<th <% if (sort.includes("ip")) { %>class="active"<% } %> ><a href="/admin/manage/list-users?sort=ip">IPs</a></th>
|
|
<th <% if (sort.includes("promptCount")) { %>class="active"<% } %> ><a href="/admin/manage/list-users?sort=promptCount">Prompts</a></th>
|
|
<th <% if (sort.includes("sumTokenCounts")) { %>class="active"<% } %> ><a href="/admin/manage/list-users?sort=sumTokenCounts">Tokens</a></th>
|
|
<th>Type</th>
|
|
<th <% if (sort.includes("createdAt")) { %>class="active"<% } %> ><a href="/admin/manage/list-users?sort=createdAt">Created (UTC)</a></th>
|
|
<th <% if (sort.includes("lastUsedAt")) { %>class="active"<% } %> ><a href="/admin/manage/list-users?sort=lastUsedAt">Last Used (UTC)</a></th>
|
|
<th colspan="2">Banned?</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<% users.forEach(function(user){ %>
|
|
<tr>
|
|
<td>
|
|
<code><a href="/admin/manage/view-user/<%= user.token %>"><%= user.token %></a></code>
|
|
</td>
|
|
<td><%= user.ip.length %></td>
|
|
<td><%= user.promptCount %></td>
|
|
<td><%= user.sumTokenCounts %></td>
|
|
<td><%= user.type %></td>
|
|
<td><%= user.createdAt %></td>
|
|
<td><%= user.lastUsedAt ?? "never" %></td>
|
|
<td class="actions">
|
|
<% if (user.disabledAt) { %>
|
|
<a title="Unban" href="#" class="unban" data-token="<%= user.token %>">🔄️</a>
|
|
<% } else { %>
|
|
<a title="Ban" href="#" class="ban" data-token="<%= user.token %>">🚫</a>
|
|
<% } %>
|
|
<td><%= user.disabledAt ? "Yes" : "No" %> <%= user.disabledReason ? `(${user.disabledReason})` : "" %></td>
|
|
</td>
|
|
</tr>
|
|
<% }); %>
|
|
</table>
|
|
|
|
<% if (quotasEnabled) { %>
|
|
<form action="/admin/manage/refresh-all-quotas" method="POST">
|
|
<input type="hidden" name="_csrf" value="<%- csrfToken %>" />
|
|
<button type="submit" class="btn btn-primary">Refresh All Quotas</button>
|
|
</form>
|
|
<% } %>
|
|
|
|
<ul class="pagination">
|
|
<% if (page > 1) { %>
|
|
<li><a href="/admin/manage/list-users?sort=<%= sort %>&page=<%= page - 1 %>">«</a></li>
|
|
<% } %> <% for (var i = 1; i <= pageCount; i++) { %>
|
|
<li <% if (i === page) { %>class="active"<% } %>><a href="/admin/manage/list-users?sort=<%= sort %>&page=<%= i %>"><%= i %></a></li>
|
|
<% } %> <% if (page < pageCount) { %>
|
|
<li><a href="/admin/manage/list-users?sort=<%= sort %>&page=<%= page + 1 %>">»</a></li>
|
|
<% } %>
|
|
</ul>
|
|
|
|
<p>Showing <%= page * pageSize - pageSize + 1 %> to <%= users.length + page * pageSize - pageSize %> of <%= totalCount %> users.</p>
|
|
<%- include("../_partials/pagination") %>
|
|
<% } %>
|
|
|
|
<script>
|
|
document.querySelectorAll("td.actions a.ban").forEach(function (a) {
|
|
a.addEventListener("click", function (e) {
|
|
e.preventDefault();
|
|
var token = a.getAttribute("data-token");
|
|
if (confirm("Are you sure you want to ban this user?")) {
|
|
let reason = prompt("Reason for ban:");
|
|
fetch(
|
|
"/admin/manage/disable-user/" + token,
|
|
{
|
|
method: "POST",
|
|
credentials: "same-origin",
|
|
body: JSON.stringify({ reason, _csrf: document.querySelector("meta[name=csrf-token]").getAttribute("content") }),
|
|
headers: { "Content-Type": "application/json" }
|
|
}).then(() => window.location.reload());
|
|
}
|
|
});
|
|
});
|
|
|
|
document.querySelectorAll("td.actions a.unban").forEach(function (a) {
|
|
a.addEventListener("click", function (e) {
|
|
e.preventDefault();
|
|
var token = a.getAttribute("data-token");
|
|
if (confirm("Are you sure you want to unban this user?")) {
|
|
fetch(
|
|
"/admin/manage/reactivate-user/" + token,
|
|
{
|
|
method: "POST",
|
|
credentials: "same-origin",
|
|
body: JSON.stringify({ _csrf: document.querySelector("meta[name=csrf-token]").getAttribute("content") }),
|
|
headers: { "Content-Type": "application/json" }
|
|
}
|
|
).then(() => window.location.reload());
|
|
}
|
|
});
|
|
});
|
|
</script>
|
|
|
|
<script>
|
|
document.querySelectorAll("td").forEach(function(td) {
|
|
if (td.innerText.match(/^\d{13}$/)) {
|
|
if (td.innerText == 0) return 'never';
|
|
var date = new Date(parseInt(td.innerText));
|
|
td.innerText = date.toISOString().replace("T", " ").replace(/\.\d+Z$/, "");
|
|
}
|
|
});
|
|
</script>
|
|
<%- include("../_partials/admin-footer") %>
|