Add account ban management page
This commit is contained in:
@@ -172,8 +172,8 @@ onMount(get_bans);
|
|||||||
<td>{formatDate(offence.ban_time, true, true, false)}</td>
|
<td>{formatDate(offence.ban_time, true, true, false)}</td>
|
||||||
<td>{formatDate(offence.expire_time, true, true, false)}</td>
|
<td>{formatDate(offence.expire_time, true, true, false)}</td>
|
||||||
<td>
|
<td>
|
||||||
{#if offence.file_public_id}
|
{#if offence.file_link}
|
||||||
<a href="/u/{offence.file_public_id}" target="_blank" rel="noreferrer">
|
<a href={offence.file_link} target="_blank" rel="noreferrer">
|
||||||
{offence.file_name}
|
{offence.file_name}
|
||||||
</a>
|
</a>
|
||||||
{/if}
|
{/if}
|
||||||
|
@@ -8,6 +8,7 @@ import UserManagement from "./UserManagement.svelte";
|
|||||||
import EmailReporters from "./EmailReporters.svelte";
|
import EmailReporters from "./EmailReporters.svelte";
|
||||||
import MollieSettlements from "./MollieSettlements.svelte";
|
import MollieSettlements from "./MollieSettlements.svelte";
|
||||||
import PayPalTaxes from "./PayPalTaxes.svelte";
|
import PayPalTaxes from "./PayPalTaxes.svelte";
|
||||||
|
import UserBans from "./UserBans.svelte";
|
||||||
|
|
||||||
let pages = [
|
let pages = [
|
||||||
{
|
{
|
||||||
@@ -35,6 +36,11 @@ let pages = [
|
|||||||
title: "IP Bans",
|
title: "IP Bans",
|
||||||
icon: "remove_circle",
|
icon: "remove_circle",
|
||||||
component: IPBans,
|
component: IPBans,
|
||||||
|
}, {
|
||||||
|
path: "/admin/user_bans",
|
||||||
|
title: "User Bans",
|
||||||
|
icon: "person_remove",
|
||||||
|
component: UserBans,
|
||||||
}, {
|
}, {
|
||||||
path: "/admin/user_management",
|
path: "/admin/user_management",
|
||||||
title: "User Management",
|
title: "User Management",
|
||||||
|
153
svelte/src/admin_panel/UserBans.svelte
Normal file
153
svelte/src/admin_panel/UserBans.svelte
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
<script>
|
||||||
|
import { onMount } from "svelte";
|
||||||
|
import { formatDate } from "../util/Formatting.svelte";
|
||||||
|
import Expandable from "../util/Expandable.svelte";
|
||||||
|
import LoadingIndicator from "../util/LoadingIndicator.svelte";
|
||||||
|
|
||||||
|
let loading = true
|
||||||
|
let rows = []
|
||||||
|
let total_offences = 0
|
||||||
|
let expanded = false
|
||||||
|
|
||||||
|
const get_bans = async () => {
|
||||||
|
loading = true;
|
||||||
|
try {
|
||||||
|
const resp = await fetch(window.api_endpoint+"/admin/user_ban");
|
||||||
|
if(resp.status >= 400) {
|
||||||
|
throw new Error(resp.text());
|
||||||
|
}
|
||||||
|
rows = await resp.json()
|
||||||
|
|
||||||
|
total_offences = rows.reduce(
|
||||||
|
(acc, curr) => acc + curr.offences.length, 0,
|
||||||
|
)
|
||||||
|
} catch (err) {
|
||||||
|
alert(err);
|
||||||
|
} finally {
|
||||||
|
loading = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const delete_ban = async (userid) => {
|
||||||
|
if (!confirm("Delete this banned user?\n\n"+userid)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const resp = await fetch(
|
||||||
|
window.api_endpoint+"/admin/user_ban/"+encodeURI(userid),
|
||||||
|
{ method: "DELETE" }
|
||||||
|
);
|
||||||
|
if(resp.status >= 400) {
|
||||||
|
throw new Error(await resp.text());
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
alert("Failed to delete ban! "+err)
|
||||||
|
}
|
||||||
|
|
||||||
|
get_bans();
|
||||||
|
}
|
||||||
|
|
||||||
|
onMount(get_bans);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<LoadingIndicator loading={loading}/>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<div class="toolbar">
|
||||||
|
<div class="toolbar_label">
|
||||||
|
Bans {rows.length}
|
||||||
|
</div>
|
||||||
|
<div class="toolbar_label">
|
||||||
|
Offences {total_offences}
|
||||||
|
</div>
|
||||||
|
<div class="toolbar_spacer"></div>
|
||||||
|
<button class:button_highlight={expanded} on:click={() => {expanded = !expanded}}>
|
||||||
|
{#if expanded}
|
||||||
|
<i class="icon">unfold_less</i> Collapse all
|
||||||
|
{:else}
|
||||||
|
<i class="icon">unfold_more</i> Expand all
|
||||||
|
{/if}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{#each rows as row (row.address)}
|
||||||
|
<Expandable expanded={expanded} click_expand>
|
||||||
|
<div slot="header" class="header">
|
||||||
|
<div class="title">
|
||||||
|
{row.username}<br/>
|
||||||
|
{row.user_id}
|
||||||
|
</div>
|
||||||
|
<div class="stats">
|
||||||
|
Offences<br/>
|
||||||
|
{row.offences.length}
|
||||||
|
</div>
|
||||||
|
<div class="stats">
|
||||||
|
Date<br/>
|
||||||
|
{formatDate(row.offences[0].ban_time, false, false, false)}
|
||||||
|
</div>
|
||||||
|
<button on:click|stopPropagation={() => {delete_ban(row.user_id)}} class="button button_red" style="align-self: center;">
|
||||||
|
<i class="icon">delete</i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="table_scroll">
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td>Reason</td>
|
||||||
|
<td>Reporter</td>
|
||||||
|
<td>Ban time</td>
|
||||||
|
<td>Expire time</td>
|
||||||
|
<td>File</td>
|
||||||
|
</tr>
|
||||||
|
{#each row.offences as offence (offence.ban_time)}
|
||||||
|
<tr>
|
||||||
|
<td>{offence.reason}</td>
|
||||||
|
<td>{offence.reporter}</td>
|
||||||
|
<td>{formatDate(offence.ban_time, true, true, false)}</td>
|
||||||
|
<td>{formatDate(offence.expire_time, true, true, false)}</td>
|
||||||
|
<td>
|
||||||
|
{#if offence.file_link}
|
||||||
|
<a href={offence.file_link} target="_blank" rel="noreferrer">
|
||||||
|
{offence.file_name}
|
||||||
|
</a>
|
||||||
|
{/if}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{/each}
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</Expandable>
|
||||||
|
{/each}
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.toolbar {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
width: 100%;
|
||||||
|
text-align: left;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
.toolbar > * { flex: 0 0 auto; }
|
||||||
|
.toolbar_spacer { flex: 1 1 auto; }
|
||||||
|
.toolbar_label { margin: 5px; }
|
||||||
|
|
||||||
|
|
||||||
|
.header {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
line-height: 1.2em;
|
||||||
|
}
|
||||||
|
.title {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
align-self: center;
|
||||||
|
word-break: break-all;
|
||||||
|
padding-left: 8px;
|
||||||
|
}
|
||||||
|
.stats {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
padding: 0 4px;
|
||||||
|
border-left: 1px solid var(--separator);
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
</style>
|
@@ -3,7 +3,7 @@ import { onMount } from "svelte";
|
|||||||
import Expandable from "../util/Expandable.svelte";
|
import Expandable from "../util/Expandable.svelte";
|
||||||
import { formatDate } from "../util/Formatting.svelte";
|
import { formatDate } from "../util/Formatting.svelte";
|
||||||
|
|
||||||
let result = false;
|
let result = null;
|
||||||
let offences = 0
|
let offences = 0
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
@@ -13,24 +13,71 @@ onMount(async () => {
|
|||||||
throw new Error(resp.text());
|
throw new Error(resp.text());
|
||||||
}
|
}
|
||||||
result = await resp.json()
|
result = await resp.json()
|
||||||
offences = result.offences.length
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if result !== false && offences > 0}
|
|
||||||
|
{#if result !== null && result.user_banned}
|
||||||
<section>
|
<section>
|
||||||
<Expandable click_expand>
|
<Expandable click_expand>
|
||||||
<div slot="header" class="header" class:red={result.banned === true} class:yellow={result.banned === false}>
|
<div slot="header" class="header red">
|
||||||
{#if result.banned === true}
|
Your account has been banned, click for details
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
Your user account has been banned from uploading to
|
||||||
|
pixeldrain due to violation of the
|
||||||
|
<a href="/abuse">content policy</a>. Below is a list of
|
||||||
|
files originating from your account which have been blocked:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="table_scroll">
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td>File</td>
|
||||||
|
<td>Reason</td>
|
||||||
|
<td>Ban date</td>
|
||||||
|
<td>Expiry date</td>
|
||||||
|
</tr>
|
||||||
|
{#each result.user_offences as offence (offence.ban_time)}
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
{#if offence.file_link}
|
||||||
|
<a href={offence.file_link} target="_blank" rel="noreferrer">
|
||||||
|
{offence.file_name}
|
||||||
|
</a>
|
||||||
|
{/if}
|
||||||
|
</td>
|
||||||
|
<td>{offence.reason}</td>
|
||||||
|
<td>{formatDate(offence.ban_time, false, false, false)}</td>
|
||||||
|
<td>{formatDate(offence.expire_time, false, false, false)}</td>
|
||||||
|
</tr>
|
||||||
|
{/each}
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
If you would like to dispute your account you can mail me at
|
||||||
|
support@pixeldrain.com. Please do not mail unless you have a
|
||||||
|
good reason. If you do not provide a valid reason why the ban
|
||||||
|
should be reversed your e-mail will be ignored. And do not
|
||||||
|
forget to put your username ({window.user.username}) in the
|
||||||
|
e-mail.
|
||||||
|
</p>
|
||||||
|
</Expandable>
|
||||||
|
</section>
|
||||||
|
{:else if result !== null && result.ip_offences.length > 0}
|
||||||
|
<section>
|
||||||
|
<Expandable click_expand>
|
||||||
|
<div slot="header" class="header" class:red={result.ip_banned} class:yellow={!result.ip_banned}>
|
||||||
|
{#if result.ip_banned}
|
||||||
Your IP address has been banned, click for details
|
Your IP address has been banned, click for details
|
||||||
{:else}
|
{:else}
|
||||||
Your IP address has received a copyright strike, click for details
|
Your IP address has received a copyright strike, click for details
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{#if result.banned === true}
|
{#if result.ip_banned}
|
||||||
<p>
|
<p>
|
||||||
Your IP address ({result.address}) has been banned from
|
Your IP address ({result.address}) has been banned from
|
||||||
uploading to pixeldrain due to violation of the
|
uploading to pixeldrain due to violation of the
|
||||||
@@ -56,11 +103,11 @@ onMount(async () => {
|
|||||||
<td>Ban date</td>
|
<td>Ban date</td>
|
||||||
<td>Expiry date</td>
|
<td>Expiry date</td>
|
||||||
</tr>
|
</tr>
|
||||||
{#each result.offences as offence (offence.ban_time)}
|
{#each result.ip_offences as offence (offence.ban_time)}
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
{#if offence.file_public_id}
|
{#if offence.file_link}
|
||||||
<a href="/u/{offence.file_public_id}" target="_blank" rel="noreferrer">
|
<a href={offence.file_link} target="_blank" rel="noreferrer">
|
||||||
{offence.file_name}
|
{offence.file_name}
|
||||||
</a>
|
</a>
|
||||||
{/if}
|
{/if}
|
||||||
@@ -102,6 +149,8 @@ onMount(async () => {
|
|||||||
</section>
|
</section>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
|
@@ -192,6 +192,7 @@ func New(r *httprouter.Router, prefix string, conf Config) (wc *WebController) {
|
|||||||
{GET, "admin/email_reporters" /* */, wc.serveTemplate("admin", handlerOpts{Auth: true})},
|
{GET, "admin/email_reporters" /* */, wc.serveTemplate("admin", handlerOpts{Auth: true})},
|
||||||
{GET, "admin/abuse_reports" /* */, wc.serveTemplate("admin", handlerOpts{Auth: true})},
|
{GET, "admin/abuse_reports" /* */, wc.serveTemplate("admin", handlerOpts{Auth: true})},
|
||||||
{GET, "admin/ip_bans" /* */, wc.serveTemplate("admin", handlerOpts{Auth: true})},
|
{GET, "admin/ip_bans" /* */, wc.serveTemplate("admin", handlerOpts{Auth: true})},
|
||||||
|
{GET, "admin/user_bans" /* */, wc.serveTemplate("admin", handlerOpts{Auth: true})},
|
||||||
{GET, "admin/user_management" /* */, wc.serveTemplate("admin", handlerOpts{Auth: true})},
|
{GET, "admin/user_management" /* */, wc.serveTemplate("admin", handlerOpts{Auth: true})},
|
||||||
{GET, "admin/mollie_settlements" /**/, wc.serveTemplate("admin", handlerOpts{Auth: true})},
|
{GET, "admin/mollie_settlements" /**/, wc.serveTemplate("admin", handlerOpts{Auth: true})},
|
||||||
{GET, "admin/paypal_taxes" /* */, wc.serveTemplate("admin", handlerOpts{Auth: true})},
|
{GET, "admin/paypal_taxes" /* */, wc.serveTemplate("admin", handlerOpts{Auth: true})},
|
||||||
|
Reference in New Issue
Block a user