feat: add directory opt-out sync and layout/xss seed data extensions
This commit is contained in:
@@ -659,6 +659,24 @@ async function createAnnouncements(context: SeedContext) {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const longTitle = await prisma.announcement.create({
|
||||||
|
data: {
|
||||||
|
kitaId: kita.id,
|
||||||
|
title: "Dies ist eine extrem lange Ankuendigung mit einem superlangen Titel um das Layout des Dashboards und des Schwarzen Bretts auf korrekten Textumbruch und Mobilfreundlichkeit zu testen",
|
||||||
|
content: "Inhalt der superlangen Ankuendigung fuer Layout-Testing.",
|
||||||
|
authorId: admin.id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const xssTitle = await prisma.announcement.create({
|
||||||
|
data: {
|
||||||
|
kitaId: kita.id,
|
||||||
|
title: "Boesartiger Titel mit <script>alert('XSS_NEWS_TITLE')</script> HTML Tags",
|
||||||
|
content: "Dieser Beitrag testet, ob die Anwendung XSS-Angriffe im Titel oder im Inhalt filtert. <script>alert('XSS_NEWS_CONTENT')</script>",
|
||||||
|
authorId: admin.id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
await prisma.attachment.create({
|
await prisma.attachment.create({
|
||||||
data: {
|
data: {
|
||||||
announcementId: sommerfest.id,
|
announcementId: sommerfest.id,
|
||||||
@@ -808,6 +826,41 @@ async function createTermine(
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const highDensityDay = addDays(now, 7);
|
||||||
|
for (let i = 1; i <= 8; i++) {
|
||||||
|
await prisma.termin.create({
|
||||||
|
data: {
|
||||||
|
kitaId: kita.id,
|
||||||
|
title: `Parallel-Termin #${i}`,
|
||||||
|
description: `Beschreibung fuer Parallel-Termin #${i}`,
|
||||||
|
type: TerminType.SONSTIGES,
|
||||||
|
status: TerminStatus.CONFIRMED,
|
||||||
|
startDate: highDensityDay,
|
||||||
|
endDate: highDensityDay,
|
||||||
|
allDay: false,
|
||||||
|
createdById: admin.id,
|
||||||
|
approvedById: admin.id,
|
||||||
|
approvedAt: now,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
await prisma.termin.create({
|
||||||
|
data: {
|
||||||
|
kitaId: kita.id,
|
||||||
|
title: "Boesartiger Termin <script>alert('XSS_CAL_TITLE')</script>",
|
||||||
|
description: "XSS Test im Terminkalender <script>alert('XSS_CAL_DESC')</script>",
|
||||||
|
type: TerminType.SONSTIGES,
|
||||||
|
status: TerminStatus.CONFIRMED,
|
||||||
|
startDate: addDays(now, 5),
|
||||||
|
endDate: addDays(now, 5),
|
||||||
|
allDay: true,
|
||||||
|
createdById: admin.id,
|
||||||
|
approvedById: admin.id,
|
||||||
|
approvedAt: now,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
await prisma.mitbringselItem.createMany({
|
await prisma.mitbringselItem.createMany({
|
||||||
data: [
|
data: [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ type ContactFormProps = {
|
|||||||
street: string | null;
|
street: string | null;
|
||||||
postalCode: string | null;
|
postalCode: string | null;
|
||||||
city: string | null;
|
city: string | null;
|
||||||
|
directoryOptIn: boolean;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -30,6 +31,7 @@ export function ContactForm({ contact }: ContactFormProps) {
|
|||||||
street: String(formData.get("street") ?? ""),
|
street: String(formData.get("street") ?? ""),
|
||||||
postalCode: String(formData.get("postalCode") ?? ""),
|
postalCode: String(formData.get("postalCode") ?? ""),
|
||||||
city: String(formData.get("city") ?? ""),
|
city: String(formData.get("city") ?? ""),
|
||||||
|
directoryOptIn: formData.get("directoryOptIn") === "on",
|
||||||
});
|
});
|
||||||
|
|
||||||
if (result.error) {
|
if (result.error) {
|
||||||
@@ -106,6 +108,22 @@ export function ContactForm({ contact }: ContactFormProps) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className="flex items-center gap-2 mt-2">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
id="directoryOptIn"
|
||||||
|
name="directoryOptIn"
|
||||||
|
defaultChecked={contact.directoryOptIn}
|
||||||
|
className="rounded border-[var(--hairline)] accent-[var(--accent-deep)]"
|
||||||
|
/>
|
||||||
|
<Label
|
||||||
|
htmlFor="directoryOptIn"
|
||||||
|
className="font-normal cursor-pointer text-xs text-[var(--ink-soft)]"
|
||||||
|
>
|
||||||
|
Im Adressbuch anzeigen (Datenschutzerklärung)
|
||||||
|
</Label>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="flex justify-end pt-1">
|
<div className="flex justify-end pt-1">
|
||||||
<Button type="submit" disabled={isPending}>
|
<Button type="submit" disabled={isPending}>
|
||||||
{isPending ? (
|
{isPending ? (
|
||||||
|
|||||||
@@ -80,6 +80,7 @@ const contactSchema = z.object({
|
|||||||
"Bitte eine gültige Postleitzahl angeben.",
|
"Bitte eine gültige Postleitzahl angeben.",
|
||||||
),
|
),
|
||||||
city: z.string().trim().max(100).optional(),
|
city: z.string().trim().max(100).optional(),
|
||||||
|
directoryOptIn: z.boolean().optional(),
|
||||||
});
|
});
|
||||||
|
|
||||||
// Gibt die erste konkrete Field-Error-Message aus einem Zod-Fehler zurück,
|
// Gibt die erste konkrete Field-Error-Message aus einem Zod-Fehler zurück,
|
||||||
@@ -183,6 +184,20 @@ export async function updateMyContact(rawPayload: unknown) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
const currentUser = await prisma.user.findUniqueOrThrow({
|
||||||
|
where: { id: session.user.id },
|
||||||
|
select: { directoryOptInAt: true },
|
||||||
|
});
|
||||||
|
|
||||||
|
let newDirectoryOptInAt: Date | null = currentUser.directoryOptInAt;
|
||||||
|
if (parsed.data.directoryOptIn) {
|
||||||
|
if (!newDirectoryOptInAt) {
|
||||||
|
newDirectoryOptInAt = new Date();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
newDirectoryOptInAt = null;
|
||||||
|
}
|
||||||
|
|
||||||
await prisma.user.update({
|
await prisma.user.update({
|
||||||
where: { id: session.user.id },
|
where: { id: session.user.id },
|
||||||
data: {
|
data: {
|
||||||
@@ -190,6 +205,7 @@ export async function updateMyContact(rawPayload: unknown) {
|
|||||||
street: parsed.data.street || null,
|
street: parsed.data.street || null,
|
||||||
postalCode: parsed.data.postalCode || null,
|
postalCode: parsed.data.postalCode || null,
|
||||||
city: parsed.data.city || null,
|
city: parsed.data.city || null,
|
||||||
|
directoryOptInAt: newDirectoryOptInAt,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ export default async function ProfilPage() {
|
|||||||
street: true,
|
street: true,
|
||||||
postalCode: true,
|
postalCode: true,
|
||||||
city: true,
|
city: true,
|
||||||
|
directoryOptInAt: true,
|
||||||
createdAt: true,
|
createdAt: true,
|
||||||
family: {
|
family: {
|
||||||
select: {
|
select: {
|
||||||
@@ -173,6 +174,7 @@ export default async function ProfilPage() {
|
|||||||
street: user.street,
|
street: user.street,
|
||||||
postalCode: user.postalCode,
|
postalCode: user.postalCode,
|
||||||
city: user.city,
|
city: user.city,
|
||||||
|
directoryOptIn: !!user.directoryOptInAt,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
|
|||||||
Reference in New Issue
Block a user