Adding flash message on role add and remove. Protecting routes with flash messages.

This commit is contained in:
Bradley Shellnut 2024-03-19 20:09:25 -07:00
parent 66eb09b237
commit 82de351c03
5 changed files with 60 additions and 24 deletions

View file

@ -1,10 +1,10 @@
import { redirect } from 'sveltekit-flash-message/server'; import { redirect, loadFlash } from 'sveltekit-flash-message/server';
import { notSignedInMessage } from '$lib/flashMessages'; import { forbiddenMessage, notSignedInMessage } from '$lib/flashMessages';
import { eq } from 'drizzle-orm'; import { eq } from 'drizzle-orm';
import db from '$lib/drizzle'; import db from '$lib/drizzle';
import { user_roles } from '../../../../schema'; import { user_roles } from '../../../../schema';
export async function load(event) { export const load = loadFlash(async (event) => {
const { locals } = event; const { locals } = event;
if (!locals?.user) { if (!locals?.user) {
redirect(302, '/login', notSignedInMessage, event); redirect(302, '/login', notSignedInMessage, event);
@ -25,8 +25,8 @@ export async function load(event) {
const containsAdminRole = userRoles.some((user_role) => user_role?.role?.name === 'admin'); const containsAdminRole = userRoles.some((user_role) => user_role?.role?.name === 'admin');
if (!userRoles?.length || !containsAdminRole) { if (!userRoles?.length || !containsAdminRole) {
console.log('Not an admin'); console.log('Not an admin');
redirect(302, '/login', notSignedInMessage, event); redirect(302, '/', forbiddenMessage, event);
} }
return {}; return {};
} });

View file

@ -1,7 +1,47 @@
<script lang="ts">
import { getFlash } from 'sveltekit-flash-message';
import { page } from '$app/stores';
import { onMount } from 'svelte';
import { theme } from '$state/theme';
import toast, { Toaster } from 'svelte-french-toast';
export let data;
$: ({ user } = data);
const flash = getFlash(page, {
clearOnNavigate: true,
clearAfterMs: 3000,
clearArray: true
});
onMount(() => {
// set the theme to the user's active theme
$theme = user?.theme || 'system';
document.querySelector('html')?.setAttribute('data-theme', $theme);
});
$: if ($flash) {
if ($flash.type === 'success') {
toast.success($flash.message);
} else {
toast.error($flash.message, {
duration: 5000
});
}
// Clearing the flash message could sometimes
// be required here to avoid double-toasting.
flash.set(undefined);
}
</script>
<h1>Do the admin stuff</h1> <h1>Do the admin stuff</h1>
<slot /> <slot />
<Toaster />
<style lang="postcss"> <style lang="postcss">
:global(main) { :global(main) {
margin: 0; margin: 0;

View file

@ -8,7 +8,6 @@ import { roles, user_roles, users } from '../../../../../../schema';
export const load: PageServerLoad = async (event) => { export const load: PageServerLoad = async (event) => {
const { params } = event; const { params } = event;
const { id } = params; const { id } = params;
const { user } = event.locals;
// TODO: Ensure admin user // TODO: Ensure admin user
if (!event.locals.user) { if (!event.locals.user) {
@ -67,7 +66,7 @@ export const actions = {
} }
const userRoles = await db.query.user_roles.findMany({ const userRoles = await db.query.user_roles.findMany({
where: eq(users.id, user.id), where: eq(user_roles.user_id, user.id),
with: { with: {
role: { role: {
columns: { columns: {
@ -78,9 +77,12 @@ export const actions = {
} }
}); });
console.log('userRoles', userRoles);
const containsAdminRole = userRoles.some((user_role) => user_role?.role?.name === 'admin'); const containsAdminRole = userRoles.some((user_role) => user_role?.role?.name === 'admin');
console.log('containsAdminRole', containsAdminRole);
if (!containsAdminRole) { if (!containsAdminRole) {
redirect(302, '/login', forbiddenMessage, event); redirect(302, '/', forbiddenMessage, event);
} }
const data = await request.formData(); const data = await request.formData();
@ -94,9 +96,9 @@ export const actions = {
user_id: user.id, user_id: user.id,
role_id: dbRole.id role_id: dbRole.id
}); });
return { redirect({ type: 'success', message: `Successfully added role ${dbRole.name}!` }, event);
success: true } else {
}; redirect({ type: 'error', message: `Failed to add role ${dbRole.name}!` }, event);
} }
}, },
removeRole: async (event) => { removeRole: async (event) => {
@ -107,7 +109,7 @@ export const actions = {
} }
const userRoles = await db.query.user_roles.findMany({ const userRoles = await db.query.user_roles.findMany({
where: eq(users.id, user.id), where: eq(user_roles.user_id, user.id),
with: { with: {
role: { role: {
columns: { columns: {
@ -120,7 +122,7 @@ export const actions = {
const containsAdminRole = userRoles.some((user_role) => user_role?.role?.name === 'admin'); const containsAdminRole = userRoles.some((user_role) => user_role?.role?.name === 'admin');
if (!containsAdminRole) { if (!containsAdminRole) {
redirect(302, '/login', forbiddenMessage, event); redirect(302, '/', forbiddenMessage, event);
} }
const data = await request.formData(); const data = await request.formData();
@ -133,9 +135,9 @@ export const actions = {
await db await db
.delete(user_roles) .delete(user_roles)
.where(and(eq(user_roles.user_id, user.id), eq(user_roles.role_id, dbRole.id))); .where(and(eq(user_roles.user_id, user.id), eq(user_roles.role_id, dbRole.id)));
return { redirect({ type: 'success', message: `Successfully removed role ${dbRole.name}!` }, event);
success: true } else {
}; redirect({ type: 'error', message: `Failed to remove role ${dbRole.name} !` }, event);
} }
} }
}; };

View file

@ -5,7 +5,6 @@
// import AddRolesForm from './add-roles-form.svelte'; // import AddRolesForm from './add-roles-form.svelte';
export let data; export let data;
export let form;
const { user, availableRoles } = data; const { user, availableRoles } = data;
const { user_roles }: { user_roles: { role: { name: string, cuid: string } }[] } = user; const { user_roles }: { user_roles: { role: { name: string, cuid: string } }[] } = user;
@ -20,7 +19,7 @@
<h2>User Roles</h2> <h2>User Roles</h2>
{#each user_roles as user_role} {#each user_roles as user_role}
{#if user_role?.role?.name !== 'user'} {#if user_role?.role?.name !== 'user'}
<form action="?/removeRole" method="POST" use:enhance data-sveltekit-reload> <form action="?/removeRole" method="POST" use:enhance data-sveltekit-replacestate>
<div class="flex flex-row space-x-3 place-items-center mt-2"> <div class="flex flex-row space-x-3 place-items-center mt-2">
<input id="role" type="hidden" name="role" value={user_role?.role?.cuid} /> <input id="role" type="hidden" name="role" value={user_role?.role?.cuid} />
<Button type="submit">Remove</Button> <Button type="submit">Remove</Button>
@ -32,14 +31,10 @@
{/if} {/if}
{/each} {/each}
{#if form?.success}
<p>Sucessfully added role</p>
{/if}
<h2>Roles Available to Assign</h2> <h2>Roles Available to Assign</h2>
<!--<AddRolesForm {availableRoles} />--> <!--<AddRolesForm {availableRoles} />-->
{#each availableRoles as role} {#each availableRoles as role}
<form action="?/addRole" method="POST" use:enhance data-sveltekit-reload> <form action="?/addRole" method="POST" use:enhance data-sveltekit-replacestate>
<div class="flex flex-row space-x-3 place-items-center mt-2"> <div class="flex flex-row space-x-3 place-items-center mt-2">
<input id="role" type="hidden" name="role" value={role?.cuid} /> <input id="role" type="hidden" name="role" value={role?.cuid} />
<Button type="submit">Add</Button> <Button type="submit">Add</Button>

View file

@ -8,7 +8,6 @@
import { page } from '$app/stores'; import { page } from '$app/stores';
import { onNavigate } from "$app/navigation"; import { onNavigate } from "$app/navigation";
import Analytics from '$components/Analytics.svelte'; import Analytics from '$components/Analytics.svelte';
import Loading from '$lib/components/Loading.svelte';
import { theme } from '$state/theme'; import { theme } from '$state/theme';
import PageLoadingIndicator from '$lib/page_loading_indicator.svelte'; import PageLoadingIndicator from '$lib/page_loading_indicator.svelte';