add strike system (#18)
All checks were successful
delpoy / build-and-deploy (push) Successful in 1m25s
All checks were successful
delpoy / build-and-deploy (push) Successful in 1m25s
This commit is contained in:
parent
7599f233a8
commit
58bc475aec
@ -62,6 +62,9 @@ export class Report extends Model {
|
|||||||
@Column({ type: DataTypes.INTEGER })
|
@Column({ type: DataTypes.INTEGER })
|
||||||
@ForeignKey(() => Admin)
|
@ForeignKey(() => Admin)
|
||||||
declare auditor_id: number;
|
declare auditor_id: number;
|
||||||
|
@Column({ type: DataTypes.INTEGER })
|
||||||
|
@ForeignKey(() => StrikeReason)
|
||||||
|
declare strike_reason_id: number | null;
|
||||||
|
|
||||||
@BelongsTo(() => User, 'reporter_id')
|
@BelongsTo(() => User, 'reporter_id')
|
||||||
declare reporter: User;
|
declare reporter: User;
|
||||||
@ -69,6 +72,38 @@ export class Report extends Model {
|
|||||||
declare reported: User;
|
declare reported: User;
|
||||||
@BelongsTo(() => Admin, 'auditor_id')
|
@BelongsTo(() => Admin, 'auditor_id')
|
||||||
declare auditor: Admin;
|
declare auditor: Admin;
|
||||||
|
@BelongsTo(() => StrikeReason, 'strike_reason_id')
|
||||||
|
declare strike_reason: StrikeReason;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Table({ modelName: 'strike_reason', underscored: true })
|
||||||
|
export class StrikeReason extends Model {
|
||||||
|
@Column({ type: DataTypes.INTEGER, allowNull: false })
|
||||||
|
declare weight: number;
|
||||||
|
@Column({ type: DataTypes.STRING, allowNull: false })
|
||||||
|
declare name: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Table({ modelName: 'strike_punishment', underscored: true })
|
||||||
|
export class StrikePunishment extends Model {
|
||||||
|
@Column({ type: DataTypes.INTEGER, allowNull: false })
|
||||||
|
declare weight: number;
|
||||||
|
@Column({ type: DataTypes.INTEGER, allowNull: false })
|
||||||
|
declare ban_in_seconds: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Table({ modelName: 'strike', underscored: true })
|
||||||
|
export class Strike extends Model {
|
||||||
|
@Column({ type: DataTypes.INTEGER, allowNull: false, defaultValue: 0 })
|
||||||
|
declare weight: number;
|
||||||
|
@Column({ type: DataTypes.DATE, allowNull: false, defaultValue: 0 })
|
||||||
|
declare ban_until: Date;
|
||||||
|
@Column({ type: DataTypes.INTEGER, allowNull: false })
|
||||||
|
@ForeignKey(() => User)
|
||||||
|
declare user_id: number;
|
||||||
|
|
||||||
|
@BelongsTo(() => User, 'user_id')
|
||||||
|
declare user: User;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Table({ modelName: 'admin', underscored: true })
|
@Table({ modelName: 'admin', underscored: true })
|
||||||
@ -122,5 +157,5 @@ export class Settings extends Model {
|
|||||||
export const sequelize = new Sequelize(building ? 'sqlite::memory:' : env.DATABASE_URI, {
|
export const sequelize = new Sequelize(building ? 'sqlite::memory:' : env.DATABASE_URI, {
|
||||||
// only log sql queries in dev mode
|
// only log sql queries in dev mode
|
||||||
logging: dev ? console.log : false,
|
logging: dev ? console.log : false,
|
||||||
models: [User, Report, Admin, Settings]
|
models: [User, Report, StrikeReason, StrikePunishment, Strike, Admin, Settings]
|
||||||
});
|
});
|
||||||
|
@ -3,6 +3,7 @@ import { redirect } from '@sveltejs/kit';
|
|||||||
import { env } from '$env/dynamic/public';
|
import { env } from '$env/dynamic/public';
|
||||||
import { getSession } from '$lib/server/session';
|
import { getSession } from '$lib/server/session';
|
||||||
import { Permissions } from '$lib/permissions';
|
import { Permissions } from '$lib/permissions';
|
||||||
|
import { StrikeReason } from '$lib/server/database';
|
||||||
|
|
||||||
export const load: PageServerLoad = async ({ parent, cookies }) => {
|
export const load: PageServerLoad = async ({ parent, cookies }) => {
|
||||||
const { reportCount } = await parent();
|
const { reportCount } = await parent();
|
||||||
@ -12,6 +13,7 @@ export const load: PageServerLoad = async ({ parent, cookies }) => {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
count: getSession(cookies, { permissions: [Permissions.UserRead] }) != null ? reportCount : 0,
|
count: getSession(cookies, { permissions: [Permissions.UserRead] }) != null ? reportCount : 0,
|
||||||
|
strike_reasons: JSON.parse(JSON.stringify(await StrikeReason.findAll())),
|
||||||
self: self
|
self: self
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -84,11 +84,12 @@
|
|||||||
method: 'PATCH',
|
method: 'PATCH',
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
id: activeReport.id,
|
id: activeReport.id,
|
||||||
auditor: data.self?.id || -1,
|
auditor: data.self?.id ?? -1,
|
||||||
notice: activeReport.notice || '',
|
notice: activeReport.notice ?? '',
|
||||||
statement: activeReport.statement || '',
|
statement: activeReport.statement ?? '',
|
||||||
status: activeReport.status,
|
status: activeReport.status,
|
||||||
reported: activeReport.reported?.uuid || null
|
reported: activeReport.reported?.uuid ?? null,
|
||||||
|
strike_reason: activeReport.strike_reason_id ?? null
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -193,7 +194,7 @@
|
|||||||
</div>
|
</div>
|
||||||
{#if activeReport}
|
{#if activeReport}
|
||||||
<div
|
<div
|
||||||
class="relative flex flex-col w-2/5 h-screen bg-base-200/50 px-4 py-6 overflow-scroll"
|
class="relative flex flex-col w-2/5 h-[calc(100vh-3rem)] bg-base-200/50 px-4 py-6 overflow-scroll"
|
||||||
transition:fly={{ x: 200, duration: 200 }}
|
transition:fly={{ x: 200, duration: 200 }}
|
||||||
>
|
>
|
||||||
<div class="absolute right-2 top-2 flex justify-center">
|
<div class="absolute right-2 top-2 flex justify-center">
|
||||||
@ -294,6 +295,20 @@
|
|||||||
<option value="review">In Bearbeitung</option>
|
<option value="review">In Bearbeitung</option>
|
||||||
<option value="reviewed">Bearbeitet</option>
|
<option value="reviewed">Bearbeitet</option>
|
||||||
</Select>
|
</Select>
|
||||||
|
<div>
|
||||||
|
<Select
|
||||||
|
label="Vergehen"
|
||||||
|
size="sm"
|
||||||
|
disabled={activeReport.status === 'none' || !activeReport.reported}
|
||||||
|
bind:value={activeReport.strike_reason_id}
|
||||||
|
>
|
||||||
|
<option value={-1}>Keins</option>
|
||||||
|
{#each data.strike_reasons as strike_reason}
|
||||||
|
<option value={strike_reason.id}>{strike_reason.name} ({strike_reason.weight})</option
|
||||||
|
>
|
||||||
|
{/each}
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="self-end mt-auto pt-6 w-full flex justify-center">
|
<div class="self-end mt-auto pt-6 w-full flex justify-center">
|
||||||
<Input
|
<Input
|
||||||
@ -316,8 +331,10 @@
|
|||||||
value="Speichern"
|
value="Speichern"
|
||||||
on:click={async () => {
|
on:click={async () => {
|
||||||
await updateActiveReport();
|
await updateActiveReport();
|
||||||
if (activeReport.reported?.username && activeReport.reported?.id === undefined) {
|
if (activeReport.reported?.username) {
|
||||||
activeReport.reported.id = -1;
|
if (activeReport.reported?.id === undefined) {
|
||||||
|
activeReport.reported.id = -1;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
activeReport.reported = undefined;
|
activeReport.reported = undefined;
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import type { RequestHandler } from '@sveltejs/kit';
|
import type { RequestHandler } from '@sveltejs/kit';
|
||||||
import { getSession } from '$lib/server/session';
|
import { getSession } from '$lib/server/session';
|
||||||
import { Permissions } from '$lib/permissions';
|
import { Permissions } from '$lib/permissions';
|
||||||
import { Admin, Report, User } from '$lib/server/database';
|
import { Admin, Report, Strike, StrikePunishment, StrikeReason, User } from '$lib/server/database';
|
||||||
import type { Attributes } from 'sequelize';
|
import type { Attributes } from 'sequelize';
|
||||||
import { Op } from 'sequelize';
|
import { Op } from 'sequelize';
|
||||||
import { env } from '$env/dynamic/private';
|
import { env } from '$env/dynamic/private';
|
||||||
@ -55,7 +55,8 @@ export const POST = (async ({ request, cookies }) => {
|
|||||||
include: [
|
include: [
|
||||||
{ model: User, as: 'reporter' },
|
{ model: User, as: 'reporter' },
|
||||||
{ model: User, as: 'reported' },
|
{ model: User, as: 'reported' },
|
||||||
{ model: Admin, as: 'auditor' }
|
{ model: Admin, as: 'auditor' },
|
||||||
|
{ model: StrikeReason, as: 'strike_reason' }
|
||||||
],
|
],
|
||||||
order: ['created_at'],
|
order: ['created_at'],
|
||||||
offset: data.from || 0,
|
offset: data.from || 0,
|
||||||
@ -77,6 +78,9 @@ export const POST = (async ({ request, cookies }) => {
|
|||||||
} else if (r.auditor) {
|
} else if (r.auditor) {
|
||||||
delete r.dataValues.auditor.password;
|
delete r.dataValues.auditor.password;
|
||||||
}
|
}
|
||||||
|
if (!r.strike_reason) {
|
||||||
|
r.strike_reason_id = -1;
|
||||||
|
}
|
||||||
return r;
|
return r;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -97,6 +101,7 @@ export const PATCH = (async ({ request, cookies }) => {
|
|||||||
notice: string | null;
|
notice: string | null;
|
||||||
statement: string | null;
|
statement: string | null;
|
||||||
status: 'none' | 'review' | 'reviewed' | null;
|
status: 'none' | 'review' | 'reviewed' | null;
|
||||||
|
strike_reason: number | null;
|
||||||
} = await request.json();
|
} = await request.json();
|
||||||
|
|
||||||
if (data.id === null || data.auditor === null) return new Response(null, { status: 400 });
|
if (data.id === null || data.auditor === null) return new Response(null, { status: 400 });
|
||||||
@ -113,6 +118,74 @@ export const PATCH = (async ({ request, cookies }) => {
|
|||||||
if (data.notice != null) report.notice = data.notice;
|
if (data.notice != null) report.notice = data.notice;
|
||||||
if (data.statement != null) report.statement = data.statement;
|
if (data.statement != null) report.statement = data.statement;
|
||||||
if (data.status != null) report.status = data.status;
|
if (data.status != null) report.status = data.status;
|
||||||
|
if (data.strike_reason != null) {
|
||||||
|
if (data.status !== 'reviewed') {
|
||||||
|
if (data.strike_reason == -1) {
|
||||||
|
report.strike_reason_id = null;
|
||||||
|
} else {
|
||||||
|
const strike_reason = await StrikeReason.findByPk(data.strike_reason);
|
||||||
|
if (strike_reason == null) return new Response(null, { status: 400 });
|
||||||
|
report.strike_reason_id = strike_reason.id;
|
||||||
|
}
|
||||||
|
} else if (data.strike_reason == -1) {
|
||||||
|
const strike = await Strike.findOne({ where: { user_id: report.reported_id } });
|
||||||
|
if (strike != null && report.strike_reason_id != null) {
|
||||||
|
const strike_weight = (await StrikeReason.findByPk(report.strike_reason_id, {
|
||||||
|
attributes: ['weight']
|
||||||
|
}))!.weight;
|
||||||
|
const current_ban_in_seconds = (
|
||||||
|
await StrikePunishment.findOne({
|
||||||
|
attributes: ['ban_in_seconds'],
|
||||||
|
where: { weight: { [Op.lte]: strike.weight } }
|
||||||
|
})
|
||||||
|
)?.ban_in_seconds;
|
||||||
|
if (current_ban_in_seconds) {
|
||||||
|
const new_ban_in_seconds = (
|
||||||
|
await StrikePunishment.findOne({
|
||||||
|
attributes: ['ban_in_seconds'],
|
||||||
|
where: { weight: { [Op.lte]: strike.weight - strike_weight } }
|
||||||
|
})
|
||||||
|
)?.ban_in_seconds;
|
||||||
|
const time_left =
|
||||||
|
strike.ban_until.getTime() / 1000 - current_ban_in_seconds + (new_ban_in_seconds || 0);
|
||||||
|
strike.ban_until = new Date(time_left * 1000);
|
||||||
|
}
|
||||||
|
strike.weight -= strike_weight;
|
||||||
|
await strike.save();
|
||||||
|
report.strike_reason_id = null;
|
||||||
|
}
|
||||||
|
} else if (data.strike_reason != report.strike_reason_id) {
|
||||||
|
if (!report.reported_id) return new Response(null, { status: 400 });
|
||||||
|
const strike_reason = await StrikeReason.findByPk(data.strike_reason);
|
||||||
|
if (strike_reason == null) return new Response(null, { status: 400 });
|
||||||
|
const [strike] = await Strike.findOrCreate({ where: { user_id: report.reported_id } });
|
||||||
|
const old_punishment = (
|
||||||
|
await StrikePunishment.findOne({
|
||||||
|
attributes: ['ban_in_seconds'],
|
||||||
|
where: { weight: { [Op.lte]: strike.weight } }
|
||||||
|
})
|
||||||
|
)?.ban_in_seconds;
|
||||||
|
if (report.strike_reason_id) {
|
||||||
|
strike.weight -=
|
||||||
|
(await StrikeReason.findByPk(report.strike_reason_id, { attributes: ['weight'] }))
|
||||||
|
?.weight || 0;
|
||||||
|
}
|
||||||
|
strike.weight += (await StrikeReason.findByPk(strike_reason.id, {
|
||||||
|
attributes: ['weight']
|
||||||
|
}))!.weight;
|
||||||
|
const new_punishment = (
|
||||||
|
await StrikePunishment.findOne({
|
||||||
|
attributes: ['ban_in_seconds'],
|
||||||
|
where: { weight: { [Op.lte]: strike.weight } }
|
||||||
|
})
|
||||||
|
)?.ban_in_seconds;
|
||||||
|
if (old_punishment != new_punishment && new_punishment != null) {
|
||||||
|
strike.ban_until = new Date(Date.now() + new_punishment / 1000);
|
||||||
|
}
|
||||||
|
await strike.save();
|
||||||
|
report.strike_reason_id = strike_reason.id;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (admin != null) report.auditor_id = admin.id;
|
if (admin != null) report.auditor_id = admin.id;
|
||||||
|
|
||||||
await report.save();
|
await report.save();
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import type { RequestHandler } from '@sveltejs/kit';
|
import type { RequestHandler } from '@sveltejs/kit';
|
||||||
import { User } from '$lib/server/database';
|
import { Strike, User } from '$lib/server/database';
|
||||||
import { env } from '$env/dynamic/private';
|
import { env } from '$env/dynamic/private';
|
||||||
|
|
||||||
export const GET = (async ({ url }) => {
|
export const GET = (async ({ url }) => {
|
||||||
@ -12,12 +12,15 @@ export const GET = (async ({ url }) => {
|
|||||||
const user = await User.findOne({ where: { uuid: uuid } });
|
const user = await User.findOne({ where: { uuid: uuid } });
|
||||||
if (user == null) return new Response(null, { status: 400 });
|
if (user == null) return new Response(null, { status: 400 });
|
||||||
|
|
||||||
|
const strike = await Strike.findOne({ where: { user_id: user.id } });
|
||||||
|
|
||||||
return new Response(
|
return new Response(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
uuid: user.uuid,
|
uuid: user.uuid,
|
||||||
username: user.username,
|
username: user.username,
|
||||||
firstname: user.firstname,
|
firstname: user.firstname,
|
||||||
lastname: user.lastname
|
lastname: user.lastname,
|
||||||
|
ban_until: strike ? strike.ban_until.getTime() / 1000 : null
|
||||||
}),
|
}),
|
||||||
{ status: 200 }
|
{ status: 200 }
|
||||||
);
|
);
|
||||||
|
@ -77,7 +77,7 @@
|
|||||||
{#if skin}
|
{#if skin}
|
||||||
<img class="absolute" src={skin} alt="" />
|
<img class="absolute" src={skin} alt="" />
|
||||||
{:else}
|
{:else}
|
||||||
<span class="loading loading-spinner loading-lg"></span>
|
<span class="loading loading-spinner loading-lg" />
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user