293 lines
19 KiB
Plaintext
293 lines
19 KiB
Plaintext
package settings
|
|
|
|
import (
|
|
"gobeyhan/views/admin"
|
|
"gobeyhan/database/models"
|
|
"fmt"
|
|
)
|
|
|
|
templ Layout(title string) {
|
|
@admin.Layout(title) {
|
|
<div class="px-4 py-6 sm:px-0">
|
|
<div class="mb-6 border-b border-gray-200">
|
|
<nav class="-mb-px flex space-x-8" aria-label="Tabs">
|
|
<a href="/admin/settings/whitelist" class="border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300 whitespace-nowrap py-4 px-1 border-b-2 font-medium text-sm">CORS Whitelist</a>
|
|
<a href="/admin/settings/blacklist" class="border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300 whitespace-nowrap py-4 px-1 border-b-2 font-medium text-sm">CORS Blacklist</a>
|
|
<a href="/admin/settings/rate-limits" class="border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300 whitespace-nowrap py-4 px-1 border-b-2 font-medium text-sm">Rate Limits</a>
|
|
</nav>
|
|
</div>
|
|
{ children... }
|
|
</div>
|
|
<script>
|
|
function confirmDelete(formId) {
|
|
Swal.fire({
|
|
title: 'Are you sure?',
|
|
text: "You won't be able to revert this!",
|
|
icon: 'warning',
|
|
showCancelButton: true,
|
|
confirmButtonColor: '#3085d6',
|
|
cancelButtonColor: '#d33',
|
|
confirmButtonText: 'Yes, delete it!'
|
|
}).then((result) => {
|
|
if (result.isConfirmed) {
|
|
document.getElementById(formId).submit();
|
|
}
|
|
})
|
|
}
|
|
</script>
|
|
}
|
|
}
|
|
|
|
templ WhitelistList(items []models.CorsWhitelist) {
|
|
@Layout("CORS Whitelist") {
|
|
<div class="flex justify-between items-center mb-6">
|
|
<h1 class="text-2xl font-semibold text-gray-900">CORS Whitelist</h1>
|
|
<a href="/admin/settings/whitelist/new" class="bg-indigo-600 text-white px-4 py-2 rounded-md hover:bg-indigo-700">Add Origin</a>
|
|
</div>
|
|
|
|
<div class="bg-white shadow overflow-hidden sm:rounded-lg">
|
|
<table class="min-w-full divide-y divide-gray-200">
|
|
<thead class="bg-gray-50">
|
|
<tr>
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Origin</th>
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Description</th>
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Active</th>
|
|
<th class="px-6 py-3 text-right text-xs font-medium text-gray-500 uppercase tracking-wider">Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody class="bg-white divide-y divide-gray-200">
|
|
for _, item := range items {
|
|
<tr>
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">{ item.Origin }</td>
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">{ item.Description }</td>
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
|
|
if item.IsActive {
|
|
<span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800">Active</span>
|
|
} else {
|
|
<span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-red-100 text-red-800">Inactive</span>
|
|
}
|
|
</td>
|
|
<td class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
|
|
<a href={ templ.SafeURL(fmt.Sprintf("/admin/settings/whitelist/%d/edit", item.ID)) } class="text-indigo-600 hover:text-indigo-900 mr-4">Edit</a>
|
|
<form id={ fmt.Sprintf("delete-whitelist-%d", item.ID) } action={ templ.SafeURL(fmt.Sprintf("/admin/settings/whitelist/%d/delete", item.ID)) } method="POST" class="inline">
|
|
<button type="button" class="text-red-600 hover:text-red-900" onclick={ templ.ComponentScript{ Call: fmt.Sprintf("confirmDelete('delete-whitelist-%d')", item.ID) } }>Delete</button>
|
|
</form>
|
|
</td>
|
|
</tr>
|
|
}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
}
|
|
}
|
|
|
|
templ WhitelistCreate(errors map[string]string) {
|
|
@Layout("Add Whitelist Origin") {
|
|
<div class="max-w-2xl mx-auto py-6">
|
|
<h1 class="text-2xl font-semibold text-gray-900 mb-6">Add Allowed Origin</h1>
|
|
<form action="/admin/settings/whitelist" method="POST" class="space-y-6 bg-white p-6 rounded-lg shadow">
|
|
<div>
|
|
<label for="origin" class="block text-sm font-medium text-gray-700">Origin (e.g. https://example.com)</label>
|
|
<input type="text" name="origin" id="origin" class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm p-2 border" />
|
|
if errors["origin"] != "" {
|
|
<p class="mt-2 text-sm text-red-600">{ errors["origin"] }</p>
|
|
}
|
|
</div>
|
|
<div>
|
|
<label for="description" class="block text-sm font-medium text-gray-700">Description</label>
|
|
<input type="text" name="description" id="description" class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm p-2 border" />
|
|
</div>
|
|
<div class="flex justify-end gap-3">
|
|
<a href="/admin/settings/whitelist" class="bg-white py-2 px-4 border border-gray-300 rounded-md shadow-sm text-sm font-medium text-gray-700 hover:bg-gray-50">Cancel</a>
|
|
<button type="submit" class="bg-indigo-600 text-white px-4 py-2 rounded-md hover:bg-indigo-700">Save</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
}
|
|
}
|
|
|
|
templ WhitelistEdit(item *models.CorsWhitelist, errors map[string]string) {
|
|
@Layout("Edit Whitelist Origin") {
|
|
<div class="max-w-2xl mx-auto py-6">
|
|
<h1 class="text-2xl font-semibold text-gray-900 mb-6">Edit Allowed Origin</h1>
|
|
<form action={ templ.SafeURL(fmt.Sprintf("/admin/settings/whitelist/%d", item.ID)) } method="POST" class="space-y-6 bg-white p-6 rounded-lg shadow">
|
|
<div>
|
|
<label for="origin" class="block text-sm font-medium text-gray-700">Origin (e.g. https://example.com)</label>
|
|
<input type="text" name="origin" id="origin" value={ item.Origin } class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm p-2 border" />
|
|
if errors["origin"] != "" {
|
|
<p class="mt-2 text-sm text-red-600">{ errors["origin"] }</p>
|
|
}
|
|
</div>
|
|
<div>
|
|
<label for="description" class="block text-sm font-medium text-gray-700">Description</label>
|
|
<input type="text" name="description" id="description" value={ item.Description } class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm p-2 border" />
|
|
</div>
|
|
<div class="flex justify-end gap-3">
|
|
<a href="/admin/settings/whitelist" class="bg-white py-2 px-4 border border-gray-300 rounded-md shadow-sm text-sm font-medium text-gray-700 hover:bg-gray-50">Cancel</a>
|
|
<button type="submit" class="bg-indigo-600 text-white px-4 py-2 rounded-md hover:bg-indigo-700">Save Changes</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
}
|
|
}
|
|
|
|
templ BlacklistList(items []models.CorsBlacklist) {
|
|
@Layout("CORS Blacklist") {
|
|
<div class="flex justify-between items-center mb-6">
|
|
<h1 class="text-2xl font-semibold text-gray-900">CORS Blacklist</h1>
|
|
<a href="/admin/settings/blacklist/new" class="bg-red-600 text-white px-4 py-2 rounded-md hover:bg-red-700">Block Origin</a>
|
|
</div>
|
|
|
|
<div class="bg-white shadow overflow-hidden sm:rounded-lg">
|
|
<table class="min-w-full divide-y divide-gray-200">
|
|
<thead class="bg-gray-50">
|
|
<tr>
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Origin</th>
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Reason</th>
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Active</th>
|
|
<th class="px-6 py-3 text-right text-xs font-medium text-gray-500 uppercase tracking-wider">Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody class="bg-white divide-y divide-gray-200">
|
|
for _, item := range items {
|
|
<tr>
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">{ item.Origin }</td>
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">{ item.Reason }</td>
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
|
|
if item.IsActive {
|
|
<span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800">Active</span>
|
|
} else {
|
|
<span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-red-100 text-red-800">Inactive</span>
|
|
}
|
|
</td>
|
|
<td class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
|
|
<a href={ templ.SafeURL(fmt.Sprintf("/admin/settings/blacklist/%d/edit", item.ID)) } class="text-indigo-600 hover:text-indigo-900 mr-4">Edit</a>
|
|
<form id={ fmt.Sprintf("delete-blacklist-%d", item.ID) } action={ templ.SafeURL(fmt.Sprintf("/admin/settings/blacklist/%d/delete", item.ID)) } method="POST" class="inline">
|
|
<button type="button" class="text-red-600 hover:text-red-900" onclick={ templ.ComponentScript{ Call: fmt.Sprintf("confirmDelete('delete-blacklist-%d')", item.ID) } }>Delete</button>
|
|
</form>
|
|
</td>
|
|
</tr>
|
|
}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
}
|
|
}
|
|
|
|
|
|
templ BlacklistCreate(errors map[string]string) {
|
|
@Layout("Block Origin") {
|
|
<div class="max-w-2xl mx-auto py-6">
|
|
<h1 class="text-2xl font-semibold text-gray-900 mb-6">Block Origin</h1>
|
|
<form action="/admin/settings/blacklist" method="POST" class="space-y-6 bg-white p-6 rounded-lg shadow">
|
|
<div>
|
|
<label for="origin" class="block text-sm font-medium text-gray-700">Origin (e.g. 192.168.1.1)</label>
|
|
<input type="text" name="origin" id="origin" class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm p-2 border" />
|
|
if errors["origin"] != "" {
|
|
<p class="mt-2 text-sm text-red-600">{ errors["origin"] }</p>
|
|
}
|
|
</div>
|
|
<div>
|
|
<label for="reason" class="block text-sm font-medium text-gray-700">Reason</label>
|
|
<input type="text" name="reason" id="reason" class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm p-2 border" />
|
|
</div>
|
|
<div class="flex justify-end gap-3">
|
|
<a href="/admin/settings/blacklist" class="bg-white py-2 px-4 border border-gray-300 rounded-md shadow-sm text-sm font-medium text-gray-700 hover:bg-gray-50">Cancel</a>
|
|
<button type="submit" class="bg-red-600 text-white px-4 py-2 rounded-md hover:bg-red-700">Block</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
}
|
|
}
|
|
|
|
templ BlacklistEdit(item *models.CorsBlacklist, errors map[string]string) {
|
|
@Layout("Edit Blocked Origin") {
|
|
<div class="max-w-2xl mx-auto py-6">
|
|
<h1 class="text-2xl font-semibold text-gray-900 mb-6">Edit Blocked Origin</h1>
|
|
<form action={ templ.SafeURL(fmt.Sprintf("/admin/settings/blacklist/%d", item.ID)) } method="POST" class="space-y-6 bg-white p-6 rounded-lg shadow">
|
|
<div>
|
|
<label for="origin" class="block text-sm font-medium text-gray-700">Origin (e.g. 192.168.1.1)</label>
|
|
<input type="text" name="origin" id="origin" value={ item.Origin } class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm p-2 border" />
|
|
if errors["origin"] != "" {
|
|
<p class="mt-2 text-sm text-red-600">{ errors["origin"] }</p>
|
|
}
|
|
</div>
|
|
<div>
|
|
<label for="reason" class="block text-sm font-medium text-gray-700">Reason</label>
|
|
<input type="text" name="reason" id="reason" value={ item.Reason } class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm p-2 border" />
|
|
</div>
|
|
<div class="flex justify-end gap-3">
|
|
<a href="/admin/settings/blacklist" class="bg-white py-2 px-4 border border-gray-300 rounded-md shadow-sm text-sm font-medium text-gray-700 hover:bg-gray-50">Cancel</a>
|
|
<button type="submit" class="bg-indigo-600 text-white px-4 py-2 rounded-md hover:bg-indigo-700">Save Changes</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
}
|
|
}
|
|
|
|
templ RateLimitList(items []models.RateLimitSetting) {
|
|
@Layout("Rate Limits") {
|
|
<div class="flex justify-between items-center mb-6">
|
|
<h1 class="text-2xl font-semibold text-gray-900">Rate Limits</h1>
|
|
</div>
|
|
|
|
<div class="bg-white shadow overflow-hidden sm:rounded-lg">
|
|
<table class="min-w-full divide-y divide-gray-200">
|
|
<thead class="bg-gray-50">
|
|
<tr>
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Name</th>
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Description</th>
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Max Requests</th>
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Window (s)</th>
|
|
<th class="px-6 py-3 text-right text-xs font-medium text-gray-500 uppercase tracking-wider">Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody class="bg-white divide-y divide-gray-200">
|
|
for _, item := range items {
|
|
<tr>
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">{ item.Name }</td>
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">{ item.Description }</td>
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">{ fmt.Sprintf("%d", item.MaxRequests) }</td>
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">{ fmt.Sprintf("%v", item.WindowSeconds) }</td>
|
|
<td class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
|
|
<a href={ templ.SafeURL(fmt.Sprintf("/admin/settings/rate-limits/%d/edit", item.ID)) } class="text-indigo-600 hover:text-indigo-900 mr-4">Edit</a>
|
|
if item.Name != "api" {
|
|
<form id={ fmt.Sprintf("delete-ratelimit-%d", item.ID) } action={ templ.SafeURL(fmt.Sprintf("/admin/settings/rate-limits/%d/delete", item.ID)) } method="POST" class="inline">
|
|
<button type="button" class="text-red-600 hover:text-red-900" onclick={ templ.ComponentScript{ Call: fmt.Sprintf("confirmDelete('delete-ratelimit-%d')", item.ID) } }>Delete</button>
|
|
</form>
|
|
}
|
|
</td>
|
|
</tr>
|
|
}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
}
|
|
}
|
|
|
|
templ RateLimitEdit(item *models.RateLimitSetting, errors map[string]string) {
|
|
@Layout("Edit Rate Limit") {
|
|
<div class="max-w-2xl mx-auto py-6">
|
|
<h1 class="text-2xl font-semibold text-gray-900 mb-6">Edit Rate Limit: { item.Name }</h1>
|
|
<form action={ templ.SafeURL(fmt.Sprintf("/admin/settings/rate-limits/%d", item.ID)) } method="POST" class="space-y-6 bg-white p-6 rounded-lg shadow">
|
|
<div>
|
|
<label for="description" class="block text-sm font-medium text-gray-700">Description</label>
|
|
<input type="text" name="description" id="description" value={ item.Description } class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm p-2 border" />
|
|
</div>
|
|
<div>
|
|
<label for="max_requests" class="block text-sm font-medium text-gray-700">Max Requests</label>
|
|
<input type="number" name="max_requests" id="max_requests" value={ fmt.Sprintf("%d", item.MaxRequests) } class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm p-2 border" />
|
|
</div>
|
|
<div>
|
|
<label for="window_seconds" class="block text-sm font-medium text-gray-700">Window (seconds)</label>
|
|
<input type="number" name="window_seconds" id="window_seconds" value={ fmt.Sprintf("%d", item.WindowSeconds) } class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm p-2 border" />
|
|
</div>
|
|
<div class="flex justify-end gap-3">
|
|
<a href="/admin/settings/rate-limits" class="bg-white py-2 px-4 border border-gray-300 rounded-md shadow-sm text-sm font-medium text-gray-700 hover:bg-gray-50">Cancel</a>
|
|
<button type="submit" class="bg-indigo-600 text-white px-4 py-2 rounded-md hover:bg-indigo-700">Save Changes</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
}
|
|
}
|