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 { notSignedInMessage } from '$lib/flashMessages';
import { redirect, loadFlash } from 'sveltekit-flash-message/server';
import { forbiddenMessage, notSignedInMessage } from '$lib/flashMessages';
import { eq } from 'drizzle-orm';
import db from '$lib/drizzle';
import { user_roles } from '../../../../schema';
export async function load(event) {
export const load = loadFlash(async (event) => {
const { locals } = event;
if (!locals?.user) {
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');
if (!userRoles?.length || !containsAdminRole) {
console.log('Not an admin');
redirect(302, '/login', notSignedInMessage, event);
redirect(302, '/', forbiddenMessage, event);
}
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>
<slot />
<Toaster />
<style lang="postcss">
:global(main) {
margin: 0;

View file

@ -8,7 +8,6 @@ import { roles, user_roles, users } from '../../../../../../schema';
export const load: PageServerLoad = async (event) => {
const { params } = event;
const { id } = params;
const { user } = event.locals;
// TODO: Ensure admin user
if (!event.locals.user) {
@ -67,7 +66,7 @@ export const actions = {
}
const userRoles = await db.query.user_roles.findMany({
where: eq(users.id, user.id),
where: eq(user_roles.user_id, user.id),
with: {
role: {
columns: {
@ -78,9 +77,12 @@ export const actions = {
}
});
console.log('userRoles', userRoles);
const containsAdminRole = userRoles.some((user_role) => user_role?.role?.name === 'admin');
console.log('containsAdminRole', containsAdminRole);
if (!containsAdminRole) {
redirect(302, '/login', forbiddenMessage, event);
redirect(302, '/', forbiddenMessage, event);
}
const data = await request.formData();
@ -94,9 +96,9 @@ export const actions = {
user_id: user.id,
role_id: dbRole.id
});
return {
success: true
};
redirect({ type: 'success', message: `Successfully added role ${dbRole.name}!` }, event);
} else {
redirect({ type: 'error', message: `Failed to add role ${dbRole.name}!` }, event);
}
},
removeRole: async (event) => {
@ -107,7 +109,7 @@ export const actions = {
}
const userRoles = await db.query.user_roles.findMany({
where: eq(users.id, user.id),
where: eq(user_roles.user_id, user.id),
with: {
role: {
columns: {
@ -120,7 +122,7 @@ export const actions = {
const containsAdminRole = userRoles.some((user_role) => user_role?.role?.name === 'admin');
if (!containsAdminRole) {
redirect(302, '/login', forbiddenMessage, event);
redirect(302, '/', forbiddenMessage, event);
}
const data = await request.formData();
@ -133,9 +135,9 @@ export const actions = {
await db
.delete(user_roles)
.where(and(eq(user_roles.user_id, user.id), eq(user_roles.role_id, dbRole.id)));
return {
success: true
};
redirect({ type: 'success', message: `Successfully removed role ${dbRole.name}!` }, event);
} 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';
export let data;
export let form;
const { user, availableRoles } = data;
const { user_roles }: { user_roles: { role: { name: string, cuid: string } }[] } = user;
@ -20,7 +19,7 @@
<h2>User Roles</h2>
{#each user_roles as user_role}
{#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">
<input id="role" type="hidden" name="role" value={user_role?.role?.cuid} />
<Button type="submit">Remove</Button>
@ -32,14 +31,10 @@
{/if}
{/each}
{#if form?.success}
<p>Sucessfully added role</p>
{/if}
<h2>Roles Available to Assign</h2>
<!--<AddRolesForm {availableRoles} />-->
{#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">
<input id="role" type="hidden" name="role" value={role?.cuid} />
<Button type="submit">Add</Button>

View file

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