rewrite website
This commit is contained in:
82
src/db/schema/admin.ts
Normal file
82
src/db/schema/admin.ts
Normal file
@@ -0,0 +1,82 @@
|
||||
import { int, mysqlTable, varchar } from 'drizzle-orm/mysql-core';
|
||||
import type { MySql2Database } from 'drizzle-orm/mysql2';
|
||||
import { eq } from 'drizzle-orm';
|
||||
import { Permissions } from '@util/permissions.ts';
|
||||
import * as bcrypt from 'bcrypt';
|
||||
|
||||
type Database = MySql2Database<{ admin: typeof admin }>;
|
||||
|
||||
export const admin = mysqlTable('admin', {
|
||||
id: int('id').primaryKey().autoincrement(),
|
||||
username: varchar('username', { length: 255 }).notNull(),
|
||||
password: varchar('password', { length: 255 }).notNull(),
|
||||
permissions: int('permissions').notNull()
|
||||
});
|
||||
|
||||
export type AddAdminReq = Omit<typeof admin.$inferInsert, 'id'>;
|
||||
|
||||
export type EditAdminReq = {
|
||||
id: number;
|
||||
username: string;
|
||||
password: string | null;
|
||||
permissions: number;
|
||||
};
|
||||
|
||||
export type DeleteAdminReq = {
|
||||
id: number;
|
||||
};
|
||||
|
||||
export type GetAdminReq = {};
|
||||
export type GetAdminRes = Omit<typeof admin.$inferSelect, 'password'>[];
|
||||
|
||||
export type ExistsAdminReq = {
|
||||
username: string;
|
||||
password: string;
|
||||
};
|
||||
export type ExistsAdminRes = {
|
||||
id: number;
|
||||
username: string;
|
||||
permissions: Permissions;
|
||||
} | null;
|
||||
|
||||
export async function addAdmin(db: Database, values: AddAdminReq) {
|
||||
values.password = bcrypt.hashSync(values.password, 10);
|
||||
|
||||
const adminIds = await db.insert(admin).values(values).$returningId();
|
||||
|
||||
return adminIds[0];
|
||||
}
|
||||
|
||||
export async function editAdmin(db: Database, values: EditAdminReq) {
|
||||
return db
|
||||
.update(admin)
|
||||
.set({
|
||||
id: values.id,
|
||||
username: values.username,
|
||||
password: values.password != null ? bcrypt.hashSync(values.password, 10) : undefined,
|
||||
permissions: values.permissions
|
||||
})
|
||||
.where(eq(admin.id, values.id));
|
||||
}
|
||||
|
||||
export async function deleteAdmin(db: Database, values: DeleteAdminReq) {
|
||||
return db.delete(admin).where(eq(admin.id, values.id));
|
||||
}
|
||||
|
||||
export async function getAdmins(db: Database, _values: GetAdminReq): Promise<GetAdminRes> {
|
||||
return db.select({ id: admin.id, username: admin.username, permissions: admin.permissions }).from(admin);
|
||||
}
|
||||
|
||||
export async function existsAdmin(db: Database, values: ExistsAdminReq): Promise<ExistsAdminRes> {
|
||||
const a = await db.query.admin.findFirst({
|
||||
where: eq(admin.username, values.username)
|
||||
});
|
||||
|
||||
if (!a || !bcrypt.compareSync(values.password, a.password)) return null;
|
||||
|
||||
return {
|
||||
id: a.id,
|
||||
username: a.username,
|
||||
permissions: new Permissions(a.permissions)
|
||||
};
|
||||
}
|
||||
58
src/db/schema/blockedUser.ts
Normal file
58
src/db/schema/blockedUser.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
import { int, mysqlTable, varchar } from 'drizzle-orm/mysql-core';
|
||||
import type { MySql2Database } from 'drizzle-orm/mysql2';
|
||||
import { eq } from 'drizzle-orm';
|
||||
|
||||
type Database = MySql2Database<{ blockedUser: typeof blockedUser }>;
|
||||
|
||||
export const blockedUser = mysqlTable('blocked_user', {
|
||||
id: int('id').primaryKey().autoincrement(),
|
||||
uuid: varchar('uuid', { length: 255 }).unique().notNull(),
|
||||
comment: varchar('comment', { length: 255 })
|
||||
});
|
||||
|
||||
export type AddBlockedUserReq = {
|
||||
uuid: string;
|
||||
comment?: string | null;
|
||||
};
|
||||
|
||||
export type EditBlockedUserReq = {
|
||||
id: number;
|
||||
uuid: string;
|
||||
comment?: string | null;
|
||||
};
|
||||
|
||||
export type DeleteBlockedUserReq = {
|
||||
id: number;
|
||||
};
|
||||
|
||||
export type GetBlockedUserByUuidReq = {
|
||||
uuid: string;
|
||||
};
|
||||
|
||||
export type GetBlockedUsersReq = {};
|
||||
|
||||
export async function addBlockedUser(db: Database, values: AddBlockedUserReq) {
|
||||
const bu = await db.insert(blockedUser).values(values).$returningId();
|
||||
|
||||
return bu[0];
|
||||
}
|
||||
|
||||
export async function editBlockedUser(db: Database, values: EditBlockedUserReq) {
|
||||
await db.update(blockedUser).set(values).where(eq(blockedUser.id, values.id));
|
||||
}
|
||||
|
||||
export async function deleteBlockedUser(db: Database, values: DeleteBlockedUserReq) {
|
||||
return db.delete(blockedUser).where(eq(blockedUser.id, values.id));
|
||||
}
|
||||
|
||||
export async function getBlockedUserByUuid(db: Database, values: GetBlockedUserByUuidReq) {
|
||||
const bu = await db.query.blockedUser.findFirst({
|
||||
where: eq(blockedUser.uuid, values.uuid)
|
||||
});
|
||||
|
||||
return bu ?? null;
|
||||
}
|
||||
|
||||
export async function getBlockedUsers(db: Database, _values: GetBlockedUsersReq) {
|
||||
return db.select().from(blockedUser);
|
||||
}
|
||||
98
src/db/schema/feedback.ts
Normal file
98
src/db/schema/feedback.ts
Normal file
@@ -0,0 +1,98 @@
|
||||
import { int, mysqlTable, text, timestamp, varchar } from 'drizzle-orm/mysql-core';
|
||||
import { user } from './user.ts';
|
||||
import type { MySql2Database } from 'drizzle-orm/mysql2';
|
||||
import { eq, inArray } from 'drizzle-orm';
|
||||
import { generateRandomString } from '@util/random.ts';
|
||||
|
||||
type Database = MySql2Database<{ feedback: typeof feedback }>;
|
||||
|
||||
export const feedback = mysqlTable('feedback', {
|
||||
id: int('id').primaryKey().autoincrement(),
|
||||
event: varchar('event', { length: 255 }).notNull(),
|
||||
title: varchar('title', { length: 255 }),
|
||||
content: text('content'),
|
||||
urlHash: varchar('url_hash', { length: 255 }).unique().notNull(),
|
||||
lastChanged: timestamp('last_changed', { mode: 'date' }).notNull().defaultNow().onUpdateNow(),
|
||||
userId: int('user_id').references(() => user.id)
|
||||
});
|
||||
|
||||
export type AddFeedbackReq = {
|
||||
event: string;
|
||||
content: string;
|
||||
};
|
||||
|
||||
export type AddUserFeedbacksReq = {
|
||||
event: string;
|
||||
title: string;
|
||||
uuids: string[];
|
||||
};
|
||||
|
||||
export type SubmitFeedbackReq = {
|
||||
urlHash: string;
|
||||
content: string;
|
||||
};
|
||||
|
||||
export type GetFeedbacksReq = {};
|
||||
|
||||
export type GetFeedbackByUrlHash = {
|
||||
urlHash: string;
|
||||
};
|
||||
|
||||
export async function addFeedback(db: Database, values: AddFeedbackReq) {
|
||||
return db.insert(feedback).values({
|
||||
event: values.event,
|
||||
content: values.content,
|
||||
urlHash: generateRandomString(16)
|
||||
});
|
||||
}
|
||||
|
||||
export async function addUserFeedbacks(db: Database, values: AddUserFeedbacksReq) {
|
||||
const users = await db.select({ id: user.id, uuid: user.uuid }).from(user).where(inArray(user.uuid, values.uuids));
|
||||
|
||||
const userFeedbacks = users.map((user) => ({
|
||||
id: user.id,
|
||||
uuid: user.uuid!,
|
||||
urlHash: generateRandomString(16)
|
||||
}));
|
||||
|
||||
await db.insert(feedback).values(
|
||||
userFeedbacks.map((feedback) => ({
|
||||
event: values.event,
|
||||
title: values.title,
|
||||
urlHash: feedback.urlHash,
|
||||
userId: feedback.id
|
||||
}))
|
||||
);
|
||||
|
||||
return userFeedbacks;
|
||||
}
|
||||
|
||||
export async function submitFeedback(db: Database, values: SubmitFeedbackReq) {
|
||||
return db
|
||||
.update(feedback)
|
||||
.set({
|
||||
content: values.content
|
||||
})
|
||||
.where(eq(feedback.urlHash, values.urlHash));
|
||||
}
|
||||
|
||||
export async function getFeedbacks(db: Database, _values: GetFeedbacksReq) {
|
||||
return db
|
||||
.select({
|
||||
id: feedback.id,
|
||||
event: feedback.event,
|
||||
title: feedback.title,
|
||||
content: feedback.content,
|
||||
urlHash: feedback.urlHash,
|
||||
lastChanged: feedback.lastChanged,
|
||||
username: user.username
|
||||
})
|
||||
.from(feedback)
|
||||
.leftJoin(user, eq(feedback.userId, user.id));
|
||||
}
|
||||
|
||||
export async function getFeedbackByUrlHash(db: Database, values: GetFeedbackByUrlHash) {
|
||||
return db.query.feedback.findFirst({
|
||||
where: eq(feedback.urlHash, values.urlHash)
|
||||
});
|
||||
}
|
||||
218
src/db/schema/report.ts
Normal file
218
src/db/schema/report.ts
Normal file
@@ -0,0 +1,218 @@
|
||||
import { alias, int, mysqlTable, text, timestamp, varchar } from 'drizzle-orm/mysql-core';
|
||||
import type { MySql2Database } from 'drizzle-orm/mysql2';
|
||||
import { and, eq, isNotNull } from 'drizzle-orm';
|
||||
import { reportStatus } from './reportStatus.ts';
|
||||
import { generateRandomString } from '@util/random.ts';
|
||||
import { BASE_PATH } from 'astro:env/server';
|
||||
import { strikeReason } from '@db/schema/strikeReason.ts';
|
||||
import { strike } from '@db/schema/strike.ts';
|
||||
import { user } from '@db/schema/user.ts';
|
||||
|
||||
type Database = MySql2Database<{ report: typeof report }>;
|
||||
|
||||
export const report = mysqlTable('report', {
|
||||
id: int('id').primaryKey().autoincrement(),
|
||||
reason: varchar('reason', { length: 255 }).notNull(),
|
||||
body: text('body'),
|
||||
urlHash: varchar('url_hash', { length: 255 }).notNull(),
|
||||
createdAt: timestamp('created_at', { mode: 'date' }),
|
||||
reporterId: int('reporter_id').references(() => user.id),
|
||||
reportedId: int('reported_id').references(() => user.id)
|
||||
});
|
||||
|
||||
export type AddReportReq = {
|
||||
reason: string;
|
||||
body: string | null;
|
||||
createdAt?: Date | null;
|
||||
reporterId?: number;
|
||||
reportedId?: number | null;
|
||||
};
|
||||
|
||||
export type EditReportReq = {
|
||||
id: number;
|
||||
reportedId: number | null;
|
||||
};
|
||||
|
||||
export type SubmitReportReq = {
|
||||
urlHash: string;
|
||||
reportedId: number | null;
|
||||
reason: string;
|
||||
body: string;
|
||||
};
|
||||
|
||||
export type GetReportsReq = {
|
||||
reporter?: string | null;
|
||||
reported?: string | null;
|
||||
includeDrafts?: boolean | null;
|
||||
};
|
||||
|
||||
export type GetReportById = {
|
||||
id: number;
|
||||
};
|
||||
|
||||
export type GetReportByUrlHash = {
|
||||
urlHash: string;
|
||||
};
|
||||
|
||||
export async function addReport(db: Database, values: AddReportReq) {
|
||||
const urlHash = generateRandomString(16);
|
||||
|
||||
const r = await db
|
||||
.insert(report)
|
||||
.values({
|
||||
reason: values.reason,
|
||||
body: values.body,
|
||||
urlHash: urlHash,
|
||||
createdAt: values.createdAt,
|
||||
reporterId: values.reporterId,
|
||||
reportedId: values.reportedId
|
||||
})
|
||||
.$returningId();
|
||||
|
||||
return Object.assign(r[0], { url: `${BASE_PATH}/report/${urlHash}` });
|
||||
}
|
||||
|
||||
export async function editReport(db: Database, values: EditReportReq) {
|
||||
return db.update(report).set({
|
||||
reportedId: values.reportedId
|
||||
});
|
||||
}
|
||||
|
||||
export async function submitReport(db: Database, values: SubmitReportReq) {
|
||||
return db
|
||||
.update(report)
|
||||
.set({
|
||||
reportedId: values.reportedId,
|
||||
reason: values.reason,
|
||||
body: values.body,
|
||||
createdAt: new Date()
|
||||
})
|
||||
.where(eq(report.urlHash, values.urlHash));
|
||||
}
|
||||
|
||||
export async function getReports(db: Database, values: GetReportsReq) {
|
||||
const reporter = alias(user, 'reporter');
|
||||
const reported = alias(user, 'reported');
|
||||
|
||||
let reporterIdSubquery;
|
||||
if (values.reporter != null) {
|
||||
reporterIdSubquery = db
|
||||
.select({ id: reporter.id })
|
||||
.from(reporter)
|
||||
.where(eq(reporter.username, values.reporter))
|
||||
.as('reporter_id_subquery');
|
||||
}
|
||||
let reportedIdSubquery;
|
||||
if (values.reported != null) {
|
||||
reportedIdSubquery = db
|
||||
.select({ id: reported.id })
|
||||
.from(reported)
|
||||
.where(eq(reported.username, values.reported))
|
||||
.as('reported_id_subquery');
|
||||
}
|
||||
|
||||
return db
|
||||
.select({
|
||||
id: report.id,
|
||||
reason: report.reason,
|
||||
body: report.body,
|
||||
urlHash: report.urlHash,
|
||||
createdAt: report.createdAt,
|
||||
reporter: {
|
||||
id: reporter.id,
|
||||
username: reporter.username
|
||||
},
|
||||
reported: {
|
||||
id: reported.id,
|
||||
username: reported.username
|
||||
},
|
||||
status: {
|
||||
status: reportStatus.status,
|
||||
notice: reportStatus.notice,
|
||||
statement: reportStatus.statement
|
||||
},
|
||||
strike: {
|
||||
strikeReasonId: strikeReason.id
|
||||
}
|
||||
})
|
||||
.from(report)
|
||||
.innerJoin(reporter, eq(report.reporterId, reporter.id))
|
||||
.leftJoin(reported, eq(report.reportedId, reported.id))
|
||||
.leftJoin(reportStatus, eq(report.id, reportStatus.reportId))
|
||||
.leftJoin(strike, eq(report.id, strike.reportId))
|
||||
.leftJoin(strikeReason, eq(strike.strikeReasonId, strikeReason.id))
|
||||
.where(
|
||||
and(
|
||||
values.reporter != null ? eq(report.reporterId, reporterIdSubquery!.id) : undefined,
|
||||
values.reported != null ? eq(report.reportedId, reportedIdSubquery!.id) : undefined,
|
||||
values.includeDrafts == false ? isNotNull(report.createdAt) : undefined
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export async function getReportById(db: Database, values: GetReportById) {
|
||||
const reporter = alias(user, 'reporter');
|
||||
const reported = alias(user, 'reported');
|
||||
|
||||
const reports = await db
|
||||
.select({
|
||||
id: report.id,
|
||||
reason: report.reason,
|
||||
body: report.body,
|
||||
createdAt: report.createdAt,
|
||||
reporter: {
|
||||
id: reporter.id,
|
||||
username: reporter.username
|
||||
},
|
||||
reported: {
|
||||
id: reported.id,
|
||||
username: reported.username
|
||||
},
|
||||
status: {
|
||||
status: reportStatus.status,
|
||||
notice: reportStatus.notice,
|
||||
statement: reportStatus.statement
|
||||
}
|
||||
})
|
||||
.from(report)
|
||||
.innerJoin(reporter, eq(report.reporterId, reporter.id))
|
||||
.leftJoin(reported, eq(report.reportedId, reported.id))
|
||||
.leftJoin(reportStatus, eq(report.id, reportStatus.reportId))
|
||||
.where(eq(report.id, values.id));
|
||||
|
||||
return reports[0] ?? null;
|
||||
}
|
||||
|
||||
export async function getReportByUrlHash(db: Database, values: GetReportByUrlHash) {
|
||||
const reporter = alias(user, 'reporter');
|
||||
const reported = alias(user, 'reported');
|
||||
|
||||
const reports = await db
|
||||
.select({
|
||||
id: report.id,
|
||||
reason: report.reason,
|
||||
body: report.body,
|
||||
createdAt: report.createdAt,
|
||||
urlHash: report.urlHash,
|
||||
reporter: {
|
||||
id: reporter.id,
|
||||
username: reporter.username
|
||||
},
|
||||
reported: {
|
||||
id: reported.id,
|
||||
username: reported.username
|
||||
},
|
||||
status: {
|
||||
status: reportStatus.status,
|
||||
notice: reportStatus.notice,
|
||||
statement: reportStatus.statement
|
||||
}
|
||||
})
|
||||
.from(report)
|
||||
.innerJoin(reporter, eq(report.reporterId, reporter.id))
|
||||
.leftJoin(reported, eq(report.reportedId, reported.id))
|
||||
.leftJoin(reportStatus, eq(report.id, reportStatus.reportId))
|
||||
.where(eq(report.urlHash, values.urlHash));
|
||||
|
||||
return reports[0] ?? null;
|
||||
}
|
||||
38
src/db/schema/reportAttachment.ts
Normal file
38
src/db/schema/reportAttachment.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import { char, int, mysqlEnum, mysqlTable } from 'drizzle-orm/mysql-core';
|
||||
import { report } from '@db/schema/report.ts';
|
||||
import type { MySql2Database } from 'drizzle-orm/mysql2';
|
||||
import { eq } from 'drizzle-orm';
|
||||
|
||||
type Database = MySql2Database<{ reportAttachment: typeof reportAttachment }>;
|
||||
|
||||
export const reportAttachment = mysqlTable('report_attachment', {
|
||||
type: mysqlEnum('type', ['image', 'video']),
|
||||
hash: char('hash', { length: 32 }),
|
||||
reportId: int('report_id')
|
||||
.notNull()
|
||||
.references(() => report.id)
|
||||
});
|
||||
|
||||
export type AddReportAttachmentReq = {
|
||||
type: 'image' | 'video';
|
||||
hash: string;
|
||||
reportId: number;
|
||||
};
|
||||
|
||||
export type GetReportAttachmentsReq = {
|
||||
reportId: number;
|
||||
};
|
||||
|
||||
export async function addReportAttachment(db: Database, values: AddReportAttachmentReq) {
|
||||
await db.insert(reportAttachment).values(values);
|
||||
}
|
||||
|
||||
export async function getReportAttachments(db: Database, values: GetReportAttachmentsReq) {
|
||||
return db
|
||||
.select({
|
||||
type: reportAttachment.type,
|
||||
hash: reportAttachment.hash
|
||||
})
|
||||
.from(reportAttachment)
|
||||
.where(eq(reportAttachment.reportId, values.reportId));
|
||||
}
|
||||
50
src/db/schema/reportStatus.ts
Normal file
50
src/db/schema/reportStatus.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import { int, mysqlEnum, mysqlTable, text } from 'drizzle-orm/mysql-core';
|
||||
import { admin } from './admin.ts';
|
||||
import { report } from './report.ts';
|
||||
import type { MySql2Database } from 'drizzle-orm/mysql2';
|
||||
import { eq } from 'drizzle-orm';
|
||||
|
||||
type Database = MySql2Database<{ reportStatus: typeof reportStatus }>;
|
||||
|
||||
export const reportStatus = mysqlTable('report_status', {
|
||||
status: mysqlEnum('status', ['open', 'closed']),
|
||||
notice: text('notice'),
|
||||
statement: text('statement'),
|
||||
reportId: int('report_id')
|
||||
.notNull()
|
||||
.unique()
|
||||
.references(() => report.id),
|
||||
reviewerId: int('reviewer_id').references(() => admin.id)
|
||||
});
|
||||
|
||||
export type GetReportStatusReq = {
|
||||
reportId: number;
|
||||
};
|
||||
|
||||
export type EditReportStatusReq = {
|
||||
reportId: number;
|
||||
status: 'open' | 'closed' | null;
|
||||
notice: string | null;
|
||||
statement: string | null;
|
||||
};
|
||||
|
||||
export async function getReportStatus(db: Database, values: GetReportStatusReq) {
|
||||
const rs = await db.query.reportStatus.findFirst({
|
||||
where: eq(reportStatus.reportId, values.reportId)
|
||||
});
|
||||
|
||||
return rs ?? null;
|
||||
}
|
||||
|
||||
export async function editReportStatus(db: Database, values: EditReportStatusReq) {
|
||||
return db
|
||||
.insert(reportStatus)
|
||||
.values(values)
|
||||
.onDuplicateKeyUpdate({
|
||||
set: {
|
||||
status: values.status,
|
||||
notice: values.notice,
|
||||
statement: values.statement
|
||||
}
|
||||
});
|
||||
}
|
||||
52
src/db/schema/settings.ts
Normal file
52
src/db/schema/settings.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
import { mysqlTable, text, varchar } from 'drizzle-orm/mysql-core';
|
||||
import { eq, inArray } from 'drizzle-orm';
|
||||
import type { MySql2Database } from 'drizzle-orm/mysql2';
|
||||
|
||||
type Database = MySql2Database<{ settings: typeof settings }>;
|
||||
|
||||
export const settings = mysqlTable('settings', {
|
||||
name: varchar('name', { length: 255 }).unique().notNull(),
|
||||
value: text()
|
||||
});
|
||||
|
||||
export type GetSettingsReq = {
|
||||
names?: string[];
|
||||
};
|
||||
|
||||
export type SetSettingsReq = {
|
||||
settings: {
|
||||
name: string;
|
||||
value: string | null;
|
||||
}[];
|
||||
};
|
||||
|
||||
export type GetSettingReq = {
|
||||
name: string;
|
||||
};
|
||||
|
||||
export async function getSettings(db: Database, values: GetSettingsReq) {
|
||||
return db
|
||||
.select({ name: settings.name, value: settings.value })
|
||||
.from(settings)
|
||||
.where(values.names ? inArray(settings.name, values.names) : undefined);
|
||||
}
|
||||
|
||||
export async function setSettings(db: Database, values: SetSettingsReq) {
|
||||
return db.transaction(async (tx) => {
|
||||
for (const setting of values.settings) {
|
||||
await tx
|
||||
.insert(settings)
|
||||
.values(setting)
|
||||
.onDuplicateKeyUpdate({
|
||||
set: {
|
||||
value: setting.value
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export async function getSetting(db: Database, values: GetSettingReq): Promise<string | null> {
|
||||
const value = await db.select({ value: settings.value }).from(settings).where(eq(settings.name, values.name));
|
||||
return value.length > 0 ? value[0]?.value : null;
|
||||
}
|
||||
81
src/db/schema/strike.ts
Normal file
81
src/db/schema/strike.ts
Normal file
@@ -0,0 +1,81 @@
|
||||
import { int, mysqlTable, timestamp } from 'drizzle-orm/mysql-core';
|
||||
import { strikeReason } from '@db/schema/strikeReason.ts';
|
||||
import type { MySql2Database } from 'drizzle-orm/mysql2';
|
||||
import { eq } from 'drizzle-orm';
|
||||
import { report } from '@db/schema/report.ts';
|
||||
|
||||
type Database = MySql2Database<{ strike: typeof strike }>;
|
||||
|
||||
export const strike = mysqlTable('strike', {
|
||||
at: timestamp('at', { mode: 'date' }).notNull(),
|
||||
reportId: int('report_id')
|
||||
.notNull()
|
||||
.references(() => report.id),
|
||||
strikeReasonId: int('strike_reason_id')
|
||||
.notNull()
|
||||
.references(() => strikeReason.id)
|
||||
});
|
||||
|
||||
export type EditStrikeReq = {
|
||||
reportId: number;
|
||||
at?: Date;
|
||||
strikeReasonId: number;
|
||||
};
|
||||
|
||||
export type DeleteStrikeReq = {
|
||||
reportId: number;
|
||||
};
|
||||
|
||||
export type GetStrikeByReportIdReq = {
|
||||
reportId: number;
|
||||
};
|
||||
|
||||
export type GetStrikesByUserIdReq = {
|
||||
userId: number;
|
||||
};
|
||||
|
||||
export async function editStrike(db: Database, values: EditStrikeReq) {
|
||||
return db
|
||||
.insert(strike)
|
||||
.values({
|
||||
at: values.at ?? new Date(),
|
||||
reportId: values.reportId,
|
||||
strikeReasonId: values.strikeReasonId
|
||||
})
|
||||
.onDuplicateKeyUpdate({
|
||||
set: {
|
||||
at: values.at ?? new Date(),
|
||||
strikeReasonId: values.strikeReasonId
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export async function deleteStrike(db: Database, values: DeleteStrikeReq) {
|
||||
return db.delete(strike).where(eq(strike.reportId, values.reportId)).limit(1);
|
||||
}
|
||||
|
||||
export async function getStrikeByReportId(db: Database, values: GetStrikeByReportIdReq) {
|
||||
const strikes = await db
|
||||
.select({
|
||||
strike,
|
||||
strikeReason
|
||||
})
|
||||
.from(strike)
|
||||
.where(eq(strike.reportId, values.reportId))
|
||||
.leftJoin(strikeReason, eq(strike.strikeReasonId, strikeReason.id));
|
||||
|
||||
return strikes[0] ?? null;
|
||||
}
|
||||
|
||||
export async function getStrikesByUserId(db: Database, values: GetStrikesByUserIdReq) {
|
||||
return db
|
||||
.select({
|
||||
at: strike.at,
|
||||
report: report,
|
||||
reason: strikeReason
|
||||
})
|
||||
.from(strike)
|
||||
.innerJoin(strikeReason, eq(strike.strikeReasonId, strikeReason.id))
|
||||
.innerJoin(report, eq(strike.reportId, report.id))
|
||||
.where(eq(report.reportedId, values.userId));
|
||||
}
|
||||
42
src/db/schema/strikeReason.ts
Normal file
42
src/db/schema/strikeReason.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import { int, mysqlTable, tinyint, varchar } from 'drizzle-orm/mysql-core';
|
||||
import type { MySql2Database } from 'drizzle-orm/mysql2';
|
||||
import { asc, eq } from 'drizzle-orm';
|
||||
|
||||
type Database = MySql2Database<{ strikeReason: typeof strikeReason }>;
|
||||
|
||||
export const strikeReason = mysqlTable('strike_reason', {
|
||||
id: int('id').primaryKey().autoincrement(),
|
||||
name: varchar('name', { length: 255 }).notNull(),
|
||||
weight: tinyint('weight').notNull()
|
||||
});
|
||||
|
||||
export type AddStrikeReasonReq = {
|
||||
name: string;
|
||||
weight: number;
|
||||
};
|
||||
|
||||
export type EditStrikeReasonReq = typeof strikeReason.$inferSelect;
|
||||
|
||||
export type DeleteStrikeReasonReq = {
|
||||
id: number;
|
||||
};
|
||||
|
||||
export type GetStrikeReasonsReq = {};
|
||||
|
||||
export async function addStrikeReason(db: Database, values: AddStrikeReasonReq) {
|
||||
const sr = await db.insert(strikeReason).values(values).$returningId();
|
||||
|
||||
return sr[0];
|
||||
}
|
||||
|
||||
export async function editStrikeReason(db: Database, values: EditStrikeReasonReq) {
|
||||
await db.update(strikeReason).set(values).where(eq(strikeReason.id, values.id));
|
||||
}
|
||||
|
||||
export async function deleteStrikeReason(db: Database, values: DeleteStrikeReasonReq) {
|
||||
await db.delete(strikeReason).where(eq(strikeReason.id, values.id));
|
||||
}
|
||||
|
||||
export async function getStrikeReasons(db: Database, _values: GetStrikeReasonsReq) {
|
||||
return db.select().from(strikeReason).orderBy(asc(strikeReason.weight));
|
||||
}
|
||||
106
src/db/schema/user.ts
Normal file
106
src/db/schema/user.ts
Normal file
@@ -0,0 +1,106 @@
|
||||
import { date, int, mysqlTable, varchar } from 'drizzle-orm/mysql-core';
|
||||
import type { MySql2Database } from 'drizzle-orm/mysql2';
|
||||
import { eq, like, or } from 'drizzle-orm';
|
||||
import { mysqlEnum } from 'drizzle-orm/mysql-core/columns/enum';
|
||||
|
||||
type Database = MySql2Database<{ user: typeof user }>;
|
||||
|
||||
export const user = mysqlTable('user', {
|
||||
id: int('id').primaryKey().autoincrement(),
|
||||
firstname: varchar('firstname', { length: 255 }).notNull(),
|
||||
lastname: varchar('lastname', { length: 255 }).notNull(),
|
||||
birthday: date('birthday', { mode: 'string' }).notNull(),
|
||||
telephone: varchar('telephone', { length: 255 }),
|
||||
username: varchar('username', { length: 255 }).notNull(),
|
||||
edition: mysqlEnum(['java', 'bedrock']).notNull(),
|
||||
uuid: varchar('uuid', { length: 36 })
|
||||
});
|
||||
|
||||
export type AddUserReq = Omit<typeof user.$inferInsert, 'id'>;
|
||||
|
||||
export type EditUserReq = Partial<Omit<typeof user.$inferInsert, 'id'>> & { id: number };
|
||||
|
||||
export type DeleteUserReq = {
|
||||
id: number;
|
||||
};
|
||||
|
||||
export type ExistsUserReq = {
|
||||
username?: string;
|
||||
uuid?: string;
|
||||
};
|
||||
|
||||
export type GetUsersReq = {
|
||||
username?: string | null;
|
||||
limit?: number;
|
||||
};
|
||||
export type GetUsersRes = (typeof user.$inferSelect)[];
|
||||
|
||||
export type GetUserByIdReq = {
|
||||
id: number;
|
||||
};
|
||||
export type GetUserByIdRes = typeof user.$inferSelect | null;
|
||||
|
||||
export type GetUserByUsernameReq = {
|
||||
username: string;
|
||||
};
|
||||
export type GetUserByUsernameRes = typeof user.$inferSelect | null;
|
||||
|
||||
export type GetUserByUuidReq = {
|
||||
uuid: string;
|
||||
};
|
||||
|
||||
export async function addUser(db: Database, values: AddUserReq) {
|
||||
const userIds = await db.insert(user).values(values).$returningId();
|
||||
|
||||
return userIds[0];
|
||||
}
|
||||
|
||||
export async function editUser(db: Database, values: EditUserReq) {
|
||||
await db.update(user).set(values).where(eq(user.id, values.id));
|
||||
}
|
||||
|
||||
export async function deleteUser(db: Database, values: DeleteUserReq) {
|
||||
await db.delete(user).where(eq(user.id, values.id));
|
||||
}
|
||||
|
||||
export async function existsUser(db: Database, values: ExistsUserReq) {
|
||||
const u = db.query.user.findFirst({
|
||||
where: or(
|
||||
values.username != null ? eq(user.username, values.username) : undefined,
|
||||
values.uuid != null ? eq(user.uuid, values.uuid) : undefined
|
||||
)
|
||||
});
|
||||
|
||||
return u ?? null;
|
||||
}
|
||||
|
||||
export async function getUsers(db: Database, values: GetUsersReq): Promise<GetUsersRes> {
|
||||
return db.query.user.findMany({
|
||||
where: values.username != null ? like(user.username, `%${values.username}%`) : undefined,
|
||||
limit: values.limit
|
||||
});
|
||||
}
|
||||
|
||||
export async function getUserById(db: Database, values: GetUserByIdReq): Promise<GetUserByIdRes> {
|
||||
const u = await db.query.user.findFirst({
|
||||
where: eq(user.id, values.id)
|
||||
});
|
||||
|
||||
return u ?? null;
|
||||
}
|
||||
|
||||
export async function getUserByUsername(db: Database, values: GetUserByUsernameReq): Promise<GetUserByUsernameRes> {
|
||||
const u = await db.query.user.findFirst({
|
||||
where: eq(user.username, values.username)
|
||||
});
|
||||
|
||||
return u ?? null;
|
||||
}
|
||||
|
||||
export async function getUserByUuid(db: Database, values: GetUserByUuidReq) {
|
||||
const u = await db.query.user.findFirst({
|
||||
where: eq(user.uuid, values.uuid)
|
||||
});
|
||||
|
||||
return u ?? null;
|
||||
}
|
||||
Reference in New Issue
Block a user