mirror of
https://github.com/BradNut/boredgame
synced 2025-09-08 17:40:22 +00:00
Fixing a lot of check issues.
This commit is contained in:
parent
95117cee21
commit
8c47357605
21 changed files with 95 additions and 127 deletions
|
|
@ -48,8 +48,8 @@ export function mapAPIGameToBoredGame(game: GameType): Games {
|
||||||
return {
|
return {
|
||||||
name: game.name,
|
name: game.name,
|
||||||
slug: kebabCase(game.name),
|
slug: kebabCase(game.name),
|
||||||
thumb_url: game.thumbnail,
|
thumb_url: game.thumb_url,
|
||||||
image_url: game.image,
|
image_url: game.image_url,
|
||||||
year_published: game.year_published,
|
year_published: game.year_published,
|
||||||
min_players: game.min_players,
|
min_players: game.min_players,
|
||||||
max_players: game.max_players,
|
max_players: game.max_players,
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@ export const signUpSchema = userSchema
|
||||||
username: true,
|
username: true,
|
||||||
password: true,
|
password: true,
|
||||||
confirm_password: true,
|
confirm_password: true,
|
||||||
terms: true,
|
|
||||||
})
|
})
|
||||||
.superRefine(({ confirm_password, password }, ctx) => {
|
.superRefine(({ confirm_password, password }, ctx) => {
|
||||||
refinePasswords(confirm_password, password, ctx);
|
refinePasswords(confirm_password, password, ctx);
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,8 @@ export const load = loadFlash(async (event) => {
|
||||||
redirect(302, '/login', notSignedInMessage, event);
|
redirect(302, '/login', notSignedInMessage, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
const userRoles = await db.query.userRoles.findMany({
|
const dbUserRoles = await db.query.userRoles.findMany({
|
||||||
where: eq(user_roles.user_id, user!.id!),
|
where: eq(userRoles.user_id, user!.id!),
|
||||||
with: {
|
with: {
|
||||||
role: {
|
role: {
|
||||||
columns: {
|
columns: {
|
||||||
|
|
@ -23,8 +23,8 @@ export const load = loadFlash(async (event) => {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const containsAdminRole = userRoles.some((userRoles) => user_role?.role?.name === 'admin');
|
const containsAdminRole = dbUserRoles.some((userRole) => userRole?.role?.name === 'admin');
|
||||||
if (!userRoles?.length || !containsAdminRole) {
|
if (!dbUserRoles?.length || !containsAdminRole) {
|
||||||
console.log('Not an admin');
|
console.log('Not an admin');
|
||||||
redirect(302, '/', forbiddenMessage, event);
|
redirect(302, '/', forbiddenMessage, event);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,14 @@
|
||||||
|
import { redirect } from 'sveltekit-flash-message/server';
|
||||||
import type { PageServerLoad } from './$types';
|
import type { PageServerLoad } from './$types';
|
||||||
import db from '../../../../../db';
|
import db from '../../../../../db';
|
||||||
import { userNotAuthenticated } from '$lib/server/auth-utils';
|
import { userNotAuthenticated } from '$lib/server/auth-utils';
|
||||||
|
import { notSignedInMessage } from '$lib/flashMessages';
|
||||||
|
|
||||||
export const load: PageServerLoad = async (event) => {
|
export const load: PageServerLoad = async (event) => {
|
||||||
const { locals } = event;
|
const { locals } = event;
|
||||||
const { user, session } = locals;
|
const { user, session } = locals;
|
||||||
if (userNotAuthenticated(user, session)) {
|
if (userNotAuthenticated(user, session)) {
|
||||||
return fail(401);
|
redirect(302, '/login', notSignedInMessage, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
const users = await db.query.users.findMany({
|
const users = await db.query.users.findMany({
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ export async function load(event) {
|
||||||
cuid: true,
|
cuid: true,
|
||||||
name: true,
|
name: true,
|
||||||
},
|
},
|
||||||
where: and(eq(collections.user_id, user.id), eq(collections.cuid, id)),
|
where: and(eq(collections.user_id, user!.id!), eq(collections.cuid, id)),
|
||||||
});
|
});
|
||||||
console.log('collection', collection);
|
console.log('collection', collection);
|
||||||
|
|
||||||
|
|
@ -110,7 +110,6 @@ export const actions: Actions = {
|
||||||
|
|
||||||
const form = await superValidate(event, zod(modifyListGameSchema));
|
const form = await superValidate(event, zod(modifyListGameSchema));
|
||||||
|
|
||||||
const user = event.locals.user;
|
|
||||||
const game = await db.query.games.findFirst({
|
const game = await db.query.games.findFirst({
|
||||||
where: eq(games.id, form.data.id),
|
where: eq(games.id, form.data.id),
|
||||||
});
|
});
|
||||||
|
|
@ -127,7 +126,7 @@ export const actions: Actions = {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const collection = await db.query.collections.findFirst({
|
const collection = await db.query.collections.findFirst({
|
||||||
where: eq(collections.user_id, user.id),
|
where: eq(collections.user_id, user!.id!),
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!collection) {
|
if (!collection) {
|
||||||
|
|
@ -187,7 +186,7 @@ export const actions: Actions = {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const collection = await db.query.collections.findFirst({
|
const collection = await db.query.collections.findFirst({
|
||||||
where: eq(collections.user_id, locals.user.id),
|
where: eq(collections.user_id, user!.id!),
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!collection) {
|
if (!collection) {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { redirect } from '@sveltejs/kit';
|
import { redirect } from 'sveltekit-flash-message/server';
|
||||||
import { notSignedInMessage } from '$lib/flashMessages';
|
import { notSignedInMessage } from '$lib/flashMessages';
|
||||||
import { userNotAuthenticated } from '$lib/server/auth-utils';
|
import { userNotAuthenticated } from '$lib/server/auth-utils';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,24 @@
|
||||||
import { fail } from '@sveltejs/kit';
|
import { redirect } from 'sveltekit-flash-message/server';
|
||||||
import { eq } from 'drizzle-orm';
|
import { eq } from 'drizzle-orm';
|
||||||
import db from '../../../../db';
|
import db from '../../../../db';
|
||||||
import { wishlists } from '$db/schema';
|
import { wishlists } from '$db/schema';
|
||||||
import { userNotAuthenticated } from '$lib/server/auth-utils';
|
import { userNotAuthenticated } from '$lib/server/auth-utils';
|
||||||
import { notSignedInMessage } from '$lib/flashMessages';
|
import { notSignedInMessage } from '$lib/flashMessages';
|
||||||
|
|
||||||
export async function load({ locals }) {
|
export async function load(event) {
|
||||||
|
const { locals } = event;
|
||||||
const { user, session } = locals;
|
const { user, session } = locals;
|
||||||
if (userNotAuthenticated(user, session)) {
|
if (userNotAuthenticated(user, session)) {
|
||||||
throw fail(401);
|
redirect(302, '/login', notSignedInMessage, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const userWishlists = await db.query.wishlists.findMany({
|
const dbWishlists = await db.query.wishlists.findMany({
|
||||||
where: eq(wishlists.user_id, locals.user.id),
|
where: eq(wishlists.user_id, user!.id!),
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
wishlsits: userWishlists,
|
wishlists: dbWishlists,
|
||||||
};
|
};
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
import { type Actions, fail, redirect } from '@sveltejs/kit';
|
import { type Actions, fail } from '@sveltejs/kit';
|
||||||
import { eq } from 'drizzle-orm';
|
import { eq } from 'drizzle-orm';
|
||||||
import { zod } from 'sveltekit-superforms/adapters';
|
import { zod } from 'sveltekit-superforms/adapters';
|
||||||
import { superValidate } from 'sveltekit-superforms/server';
|
import { superValidate } from 'sveltekit-superforms/server';
|
||||||
|
import { redirect } from 'sveltekit-flash-message/server';
|
||||||
import db from '../../../../../db';
|
import db from '../../../../../db';
|
||||||
import { modifyListGameSchema } from '$lib/validations/zod-schemas';
|
import { modifyListGameSchema } from '$lib/validations/zod-schemas';
|
||||||
import { games, wishlist_items, wishlists } from '$db/schema';
|
import { games, wishlist_items, wishlists } from '$db/schema';
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ export const load: PageServerLoad = async (event) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const dbUser = await db.query.users.findFirst({
|
const dbUser = await db.query.users.findFirst({
|
||||||
where: eq(users.id, user.id),
|
where: eq(users.id, user!.id!),
|
||||||
});
|
});
|
||||||
|
|
||||||
const profileForm = await superValidate(zod(profileSchema), {
|
const profileForm = await superValidate(zod(profileSchema), {
|
||||||
|
|
@ -85,6 +85,7 @@ export const actions: Actions = {
|
||||||
})
|
})
|
||||||
.where(eq(users.id, user.id));
|
.where(eq(users.id, user.id));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
// @ts-expect-error
|
||||||
if (e.message === `AUTH_INVALID_USER_ID`) {
|
if (e.message === `AUTH_INVALID_USER_ID`) {
|
||||||
// invalid user id
|
// invalid user id
|
||||||
console.error(e);
|
console.error(e);
|
||||||
|
|
|
||||||
|
|
@ -92,7 +92,7 @@ export const actions: Actions = {
|
||||||
}
|
}
|
||||||
|
|
||||||
const dbUser = await db.query.users.findFirst({
|
const dbUser = await db.query.users.findFirst({
|
||||||
where: eq(users.id, user.id),
|
where: eq(users.id, user!.id!),
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!dbUser?.hashed_password) {
|
if (!dbUser?.hashed_password) {
|
||||||
|
|
@ -136,7 +136,7 @@ export const actions: Actions = {
|
||||||
return setError(addTwoFactorForm, 'two_factor_code', 'Invalid code');
|
return setError(addTwoFactorForm, 'two_factor_code', 'Invalid code');
|
||||||
}
|
}
|
||||||
|
|
||||||
await db.update(users).set({ two_factor_enabled: true }).where(eq(users.id, user.id));
|
await db.update(users).set({ two_factor_enabled: true }).where(eq(users.id, user!.id!));
|
||||||
|
|
||||||
redirect(302, '/profile/security/two-factor/recovery-codes');
|
redirect(302, '/profile/security/two-factor/recovery-codes');
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ import { games, wishlist_items, wishlists } from '$db/schema';
|
||||||
import { userNotAuthenticated } from '$lib/server/auth-utils';
|
import { userNotAuthenticated } from '$lib/server/auth-utils';
|
||||||
|
|
||||||
export async function load(event) {
|
export async function load(event) {
|
||||||
const { params, locals } = event;
|
const { locals } = event;
|
||||||
const { user, session } = locals;
|
const { user, session } = locals;
|
||||||
if (userNotAuthenticated(user, session)) {
|
if (userNotAuthenticated(user, session)) {
|
||||||
redirect(302, '/login', notSignedInMessage, event);
|
redirect(302, '/login', notSignedInMessage, event);
|
||||||
|
|
@ -22,7 +22,7 @@ export async function load(event) {
|
||||||
name: true,
|
name: true,
|
||||||
created_at: true,
|
created_at: true,
|
||||||
},
|
},
|
||||||
where: eq(wishlists.user_id, user.id),
|
where: eq(wishlists.user_id, user!.id!),
|
||||||
});
|
});
|
||||||
console.log('wishlists', userWishlists);
|
console.log('wishlists', userWishlists);
|
||||||
|
|
||||||
|
|
@ -63,7 +63,7 @@ export const actions: Actions = {
|
||||||
|
|
||||||
if (game) {
|
if (game) {
|
||||||
const wishlist = await db.query.wishlists.findFirst({
|
const wishlist = await db.query.wishlists.findFirst({
|
||||||
where: eq(wishlists.user_id, locals.user.id),
|
where: eq(wishlists.user_id, user!.id!),
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!wishlist) {
|
if (!wishlist) {
|
||||||
|
|
@ -105,7 +105,7 @@ export const actions: Actions = {
|
||||||
},
|
},
|
||||||
// Remove game from a wishlist
|
// Remove game from a wishlist
|
||||||
remove: async (event) => {
|
remove: async (event) => {
|
||||||
const { params, locals } = event;
|
const { locals } = event;
|
||||||
const { user, session } = locals;
|
const { user, session } = locals;
|
||||||
if (userNotAuthenticated(user, session)) {
|
if (userNotAuthenticated(user, session)) {
|
||||||
return fail(401);
|
return fail(401);
|
||||||
|
|
@ -129,7 +129,7 @@ export const actions: Actions = {
|
||||||
|
|
||||||
if (game) {
|
if (game) {
|
||||||
const wishlist = await db.query.wishlists.findFirst({
|
const wishlist = await db.query.wishlists.findFirst({
|
||||||
where: eq(wishlists.user_id, locals.user.id),
|
where: eq(wishlists.user_id, user!.id!),
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!wishlist) {
|
if (!wishlist) {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { error, type Actions } from '@sveltejs/kit';
|
import { error, type Actions, fail } from '@sveltejs/kit';
|
||||||
import { and, eq } from 'drizzle-orm';
|
import { and, eq } from 'drizzle-orm';
|
||||||
import { zod } from 'sveltekit-superforms/adapters';
|
import { zod } from 'sveltekit-superforms/adapters';
|
||||||
import { superValidate } from 'sveltekit-superforms/server';
|
import { superValidate } from 'sveltekit-superforms/server';
|
||||||
|
|
@ -17,11 +17,9 @@ export async function load(event) {
|
||||||
redirect(302, '/login', notSignedInMessage, event);
|
redirect(302, '/login', notSignedInMessage, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('Wishlist load User id', locals.user.id);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const wishlist = await db.query.wishlists.findMany({
|
const wishlist = await db.query.wishlists.findMany({
|
||||||
where: and(eq(wishlists.user_id, locals.user.id), eq(wishlists.cuid, id)),
|
where: and(eq(wishlists.user_id, user!.id!), eq(wishlists.cuid, id)),
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!wishlist) {
|
if (!wishlist) {
|
||||||
|
|
@ -66,7 +64,7 @@ export const actions: Actions = {
|
||||||
|
|
||||||
if (game) {
|
if (game) {
|
||||||
const wishlist = await db.query.wishlists.findFirst({
|
const wishlist = await db.query.wishlists.findFirst({
|
||||||
where: eq(wishlists.user_id, locals.user.id),
|
where: eq(wishlists.user_id, user!.id!),
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!wishlist) {
|
if (!wishlist) {
|
||||||
|
|
@ -98,7 +96,7 @@ export const actions: Actions = {
|
||||||
return error(405, 'Method not allowed');
|
return error(405, 'Method not allowed');
|
||||||
},
|
},
|
||||||
// Delete a wishlist
|
// Delete a wishlist
|
||||||
delete: async ({ locals }) => {
|
delete: async (event) => {
|
||||||
const { locals } = event;
|
const { locals } = event;
|
||||||
const { user, session } = locals;
|
const { user, session } = locals;
|
||||||
if (userNotAuthenticated(user, session)) {
|
if (userNotAuthenticated(user, session)) {
|
||||||
|
|
@ -132,7 +130,7 @@ export const actions: Actions = {
|
||||||
|
|
||||||
if (game) {
|
if (game) {
|
||||||
const wishlist = await db.query.wishlists.findFirst({
|
const wishlist = await db.query.wishlists.findFirst({
|
||||||
where: eq(wishlists.user_id, locals.user.id),
|
where: eq(wishlists.user_id, user!.id!),
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!wishlist) {
|
if (!wishlist) {
|
||||||
|
|
|
||||||
|
|
@ -5,14 +5,13 @@ import kebabCase from 'just-kebab-case';
|
||||||
import type { GameType, SearchQuery } from '$lib/types';
|
import type { GameType, SearchQuery } from '$lib/types';
|
||||||
import { mapAPIGameToBoredGame } from '$lib/utils/gameMapper.js';
|
import { mapAPIGameToBoredGame } from '$lib/utils/gameMapper.js';
|
||||||
import { search_schema } from '$lib/zodValidation';
|
import { search_schema } from '$lib/zodValidation';
|
||||||
import type { PageServerLoad } from '../$types.js';
|
|
||||||
import type { BggThingDto } from 'boardgamegeekclient/dist/esm/dto/index.js';
|
import type { BggThingDto } from 'boardgamegeekclient/dist/esm/dto/index.js';
|
||||||
import { createOrUpdateGameMinimal } from '$lib/utils/db/gameUtils';
|
import { createOrUpdateGameMinimal } from '$lib/utils/db/gameUtils';
|
||||||
|
|
||||||
async function searchForGames(
|
async function searchForGames(
|
||||||
locals: App.Locals,
|
locals: App.Locals,
|
||||||
eventFetch,
|
eventFetch: typeof fetch,
|
||||||
urlQueryParams: SearchQuery
|
urlQueryParams: URLSearchParams,
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
console.log('urlQueryParams search games', urlQueryParams);
|
console.log('urlQueryParams search games', urlQueryParams);
|
||||||
|
|
@ -21,7 +20,7 @@ async function searchForGames(
|
||||||
headers.set('Content-Type', 'application/json');
|
headers.set('Content-Type', 'application/json');
|
||||||
const requestInit: RequestInit = {
|
const requestInit: RequestInit = {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
headers
|
headers,
|
||||||
};
|
};
|
||||||
const url = `/api/games/search${urlQueryParams ? `?${urlQueryParams}` : ''}`;
|
const url = `/api/games/search${urlQueryParams ? `?${urlQueryParams}` : ''}`;
|
||||||
console.log('Calling internal api', url);
|
console.log('Calling internal api', url);
|
||||||
|
|
@ -36,7 +35,7 @@ async function searchForGames(
|
||||||
const games = await response.json();
|
const games = await response.json();
|
||||||
console.log('games from DB', games);
|
console.log('games from DB', games);
|
||||||
|
|
||||||
const gameNameSearch = urlQueryParams.get('q');
|
const gameNameSearch = urlQueryParams.get('q') ?? '';
|
||||||
let totalCount = games?.length || 0;
|
let totalCount = games?.length || 0;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
|
@ -47,7 +46,7 @@ async function searchForGames(
|
||||||
const searchQueryParams = urlQueryParams ? `?${urlQueryParams}` : '';
|
const searchQueryParams = urlQueryParams ? `?${urlQueryParams}` : '';
|
||||||
const externalResponse = await eventFetch(
|
const externalResponse = await eventFetch(
|
||||||
`/api/external/search${searchQueryParams}`,
|
`/api/external/search${searchQueryParams}`,
|
||||||
requestInit
|
requestInit,
|
||||||
);
|
);
|
||||||
|
|
||||||
console.log('Back from external search', externalResponse);
|
console.log('Back from external search', externalResponse);
|
||||||
|
|
@ -65,10 +64,10 @@ async function searchForGames(
|
||||||
console.log('totalCount', totalCount);
|
console.log('totalCount', totalCount);
|
||||||
for (const game of gameList) {
|
for (const game of gameList) {
|
||||||
console.log(
|
console.log(
|
||||||
`Retrieving simplified external game details for id: ${game.id} with name ${game.name}`
|
`Retrieving simplified external game details for id: ${game.id} with name ${game.name}`,
|
||||||
);
|
);
|
||||||
const externalGameResponse = await eventFetch(
|
const externalGameResponse = await eventFetch(
|
||||||
`/api/external/game/${game.id}?simplified=true`
|
`/api/external/game/${game.id}?simplified=true`,
|
||||||
);
|
);
|
||||||
if (externalGameResponse.ok) {
|
if (externalGameResponse.ok) {
|
||||||
const externalGame = await externalGameResponse.json();
|
const externalGame = await externalGameResponse.json();
|
||||||
|
|
@ -82,14 +81,14 @@ async function searchForGames(
|
||||||
|
|
||||||
return {
|
return {
|
||||||
totalCount,
|
totalCount,
|
||||||
games
|
games,
|
||||||
};
|
};
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(`Error searching board games ${e}`);
|
console.log(`Error searching board games ${e}`);
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
totalCount: 0,
|
totalCount: 0,
|
||||||
games: []
|
games: [],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -108,18 +107,21 @@ export const load = async ({ locals, fetch, url }) => {
|
||||||
searchParams.order = searchParams.order || defaults.order;
|
searchParams.order = searchParams.order || defaults.order;
|
||||||
searchParams.sort = searchParams.sort || defaults.sort;
|
searchParams.sort = searchParams.sort || defaults.sort;
|
||||||
searchParams.q = searchParams.q || defaults.q;
|
searchParams.q = searchParams.q || defaults.q;
|
||||||
const form = await superValidate({
|
const form = await superValidate(
|
||||||
...searchParams,
|
{
|
||||||
skip: Number(searchParams.skip || defaults.skip),
|
...searchParams,
|
||||||
limit: Number(searchParams.limit || defaults.limit),
|
skip: Number(searchParams.skip || defaults.skip),
|
||||||
exact: searchParams.exact ? searchParams.exact === 'true' : defaults.exact
|
limit: Number(searchParams.limit || defaults.limit),
|
||||||
}, zod(search_schema));
|
exact: searchParams.exact ? searchParams.exact === 'true' : defaults.exact,
|
||||||
|
},
|
||||||
|
zod(search_schema),
|
||||||
|
);
|
||||||
|
|
||||||
const queryParams: SearchQuery = {
|
const queryParams: SearchQuery = {
|
||||||
limit: form.data?.limit,
|
limit: form.data?.limit,
|
||||||
skip: form.data?.skip,
|
skip: form.data?.skip,
|
||||||
q: form.data?.q,
|
q: form.data?.q,
|
||||||
exact: form.data?.exact
|
exact: form.data?.exact,
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
@ -129,8 +131,8 @@ export const load = async ({ locals, fetch, url }) => {
|
||||||
searchData: {
|
searchData: {
|
||||||
totalCount: 0,
|
totalCount: 0,
|
||||||
games: [],
|
games: [],
|
||||||
wishlists: []
|
wishlists: [],
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -171,32 +173,32 @@ export const load = async ({ locals, fetch, url }) => {
|
||||||
form,
|
form,
|
||||||
// modifyListForm,
|
// modifyListForm,
|
||||||
searchData,
|
searchData,
|
||||||
wishlists: []
|
wishlists: [],
|
||||||
};
|
};
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(`Error searching board games ${e}`);
|
console.log(`Error searching board games ${e}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('returning default no data')
|
console.log('returning default no data');
|
||||||
return {
|
return {
|
||||||
form,
|
form,
|
||||||
searchData: {
|
searchData: {
|
||||||
totalCount: 0,
|
totalCount: 0,
|
||||||
games: []
|
games: [],
|
||||||
},
|
},
|
||||||
wishlists: []
|
wishlists: [],
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const actions = {
|
export const actions = {
|
||||||
random: async ({ request, locals, fetch }): Promise<any> => {
|
random: async ({ request, locals, fetch }) => {
|
||||||
const form = await superValidate(request, zod(search_schema));
|
const form = await superValidate(request, zod(search_schema));
|
||||||
const queryParams: SearchQuery = {
|
const queryParams: SearchQuery = {
|
||||||
order_by: 'rank',
|
order_by: 'rank',
|
||||||
ascending: false,
|
ascending: false,
|
||||||
random: true,
|
random: true,
|
||||||
fields:
|
fields:
|
||||||
'id,name,min_age,min_players,max_players,thumb_url,min_playtime,max_playtime,min_age,description'
|
'id,name,min_age,min_players,max_players,thumb_url,min_playtime,max_playtime,min_age,description',
|
||||||
};
|
};
|
||||||
|
|
||||||
const newQueryParams: Record<string, string> = {};
|
const newQueryParams: Record<string, string> = {};
|
||||||
|
|
@ -208,7 +210,7 @@ export const actions = {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
form,
|
form,
|
||||||
searchData: await searchForGames(locals, fetch, urlQueryParams)
|
searchData: await searchForGames(locals, fetch, urlQueryParams),
|
||||||
};
|
};
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,28 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { dev } from '$app/environment';
|
import { dev } from '$app/environment';
|
||||||
|
import { superForm } from 'sveltekit-superforms';
|
||||||
|
import { zodClient } from 'sveltekit-superforms/adapters';
|
||||||
import SuperDebug from 'sveltekit-superforms/client/SuperDebug.svelte';
|
import SuperDebug from 'sveltekit-superforms/client/SuperDebug.svelte';
|
||||||
import { createToolbar, melt } from '@melt-ui/svelte';
|
import { createToolbar, melt } from '@melt-ui/svelte';
|
||||||
import { LayoutList, LayoutGrid } from 'lucide-svelte';
|
import { LayoutList, LayoutGrid } from 'lucide-svelte';
|
||||||
import Game from '$components/Game.svelte';
|
import Game from '$components/Game.svelte';
|
||||||
import * as Pagination from "$lib/components/ui/pagination";
|
import * as Pagination from "$lib/components/ui/pagination";
|
||||||
import GameSearchForm from '$components/search/GameSearchForm.svelte';
|
import GameSearchForm from '$components/search/GameSearchForm.svelte';
|
||||||
|
import { search_schema } from '$lib/zodValidation';
|
||||||
|
|
||||||
export let data;
|
export let data;
|
||||||
|
|
||||||
const { games, totalCount } = data?.searchData;
|
const { games, totalCount } = data.searchData;
|
||||||
|
|
||||||
console.log('data found', data);
|
console.log('data found', data);
|
||||||
console.log('found games', games);
|
console.log('found games', games);
|
||||||
console.log('found totalCount', totalCount);
|
console.log('found totalCount', totalCount);
|
||||||
|
|
||||||
let pageSize: number = data.form.limit || 10;
|
const form = superForm(data.form, {
|
||||||
|
validators: zodClient(search_schema),
|
||||||
|
});
|
||||||
|
|
||||||
|
let pageSize: number = form.limit || 10;
|
||||||
|
|
||||||
const {
|
const {
|
||||||
elements: { root: toolbarRoot },
|
elements: { root: toolbarRoot },
|
||||||
|
|
@ -72,8 +79,8 @@
|
||||||
<Pagination.Ellipsis />
|
<Pagination.Ellipsis />
|
||||||
</Pagination.Item>
|
</Pagination.Item>
|
||||||
{:else}
|
{:else}
|
||||||
<Pagination.Item isVisible={currentPage == page.value}>
|
<Pagination.Item isVisible={currentPage === page.value}>
|
||||||
<Pagination.Link {page} isActive={currentPage == page.value}>
|
<Pagination.Link {page} isActive={currentPage === page.value}>
|
||||||
{page.value}
|
{page.value}
|
||||||
</Pagination.Link>
|
</Pagination.Link>
|
||||||
</Pagination.Item>
|
</Pagination.Item>
|
||||||
|
|
|
||||||
|
|
@ -127,22 +127,3 @@ export const actions: Actions = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
async function checkRecoveryCode(recoveryCode: string, userId: string) {
|
|
||||||
const userRecoveryCodes = await db.query.recovery_codes.findMany({
|
|
||||||
where: and(eq(recovery_codes.used, false), eq(recovery_codes.userId, userId)),
|
|
||||||
});
|
|
||||||
for (const code of userRecoveryCodes) {
|
|
||||||
const validRecoveryCode = await new Argon2id().verify(code.code, recoveryCode);
|
|
||||||
if (validRecoveryCode) {
|
|
||||||
await db
|
|
||||||
.update(recovery_codes)
|
|
||||||
.set({
|
|
||||||
used: true,
|
|
||||||
})
|
|
||||||
.where(eq(recovery_codes.id, code.id));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -12,19 +12,18 @@
|
||||||
import { boredState } from '$lib/stores/boredState.js';
|
import { boredState } from '$lib/stores/boredState.js';
|
||||||
|
|
||||||
export let data;
|
export let data;
|
||||||
export let form;
|
|
||||||
|
|
||||||
const superLoginForm = superForm(data.form, {
|
const superLoginForm = superForm(data.form, {
|
||||||
onSubmit: () => boredState.update((n) => ({ ...n, loading: true })),
|
onSubmit: () => boredState.update((n) => ({ ...n, loading: true })),
|
||||||
onResult: () => boredState.update((n) => ({ ...n, loading: false })),
|
onResult: () => boredState.update((n) => ({ ...n, loading: false })),
|
||||||
flashMessage: {
|
flashMessage: {
|
||||||
module: flashModule,
|
module: flashModule,
|
||||||
onError: ({ result, message }) => {
|
onError: ({ result, flashMessage }) => {
|
||||||
// Error handling for the flash message:
|
// Error handling for the flash message:
|
||||||
// - result is the ActionResult
|
// - result is the ActionResult
|
||||||
// - message is the flash store (not the status message store)
|
// - message is the flash store (not the status message store)
|
||||||
const errorMessage = result.error.message
|
const errorMessage = result.error.message
|
||||||
message.set({ type: 'error', message: errorMessage });
|
flashMessage.set({ type: 'error', message: errorMessage });
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
syncFlashMessage: false,
|
syncFlashMessage: false,
|
||||||
|
|
@ -34,7 +33,7 @@
|
||||||
delayMs: 0,
|
delayMs: 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
const { form: loginForm, errors, enhance } = superLoginForm;
|
const { form: loginForm, enhance } = superLoginForm;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:head>
|
<svelte:head>
|
||||||
|
|
@ -62,15 +61,6 @@
|
||||||
</Form.Control>
|
</Form.Control>
|
||||||
<Form.FieldErrors />
|
<Form.FieldErrors />
|
||||||
</Form.Field>
|
</Form.Field>
|
||||||
{#if form?.twoFactorRequired}
|
|
||||||
<Form.Field form={superLoginForm} name="totpToken">
|
|
||||||
<Form.Control let:attrs>
|
|
||||||
<Form.Label for="totpToken">Two Factor Code or Recovery Code</Form.Label>
|
|
||||||
<Input {...attrs} autocomplete="one-time-code" bind:value={$loginForm.totpToken} />
|
|
||||||
</Form.Control>
|
|
||||||
<Form.FieldErrors />
|
|
||||||
</Form.Field>
|
|
||||||
{/if}
|
|
||||||
<Form.Button>Login</Form.Button>
|
<Form.Button>Login</Form.Button>
|
||||||
<p class="px-8 text-center text-sm text-muted-foreground">
|
<p class="px-8 text-center text-sm text-muted-foreground">
|
||||||
By clicking continue, you agree to our
|
By clicking continue, you agree to our
|
||||||
|
|
@ -86,20 +76,6 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style lang="postcss">
|
<style lang="postcss">
|
||||||
.loading {
|
|
||||||
position: fixed;
|
|
||||||
top: 50%;
|
|
||||||
left: 50%;
|
|
||||||
transform: translate(-50%, -50%);
|
|
||||||
z-index: 101;
|
|
||||||
display: grid;
|
|
||||||
place-items: center;
|
|
||||||
gap: 1rem;
|
|
||||||
|
|
||||||
h3 {
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.login {
|
.login {
|
||||||
display: flex;
|
display: flex;
|
||||||
margin-top: 1.5rem;
|
margin-top: 1.5rem;
|
||||||
|
|
|
||||||
|
|
@ -116,6 +116,8 @@ export const actions: Actions = {
|
||||||
session = await lucia.createSession(user[0].id, {
|
session = await lucia.createSession(user[0].id, {
|
||||||
ip_country: event.locals.ip,
|
ip_country: event.locals.ip,
|
||||||
ip_address: event.locals.country,
|
ip_address: event.locals.country,
|
||||||
|
twoFactorAuthEnabled: false,
|
||||||
|
isTwoFactorAuthenticated: false,
|
||||||
});
|
});
|
||||||
sessionCookie = lucia.createSessionCookie(session.id);
|
sessionCookie = lucia.createSessionCookie(session.id);
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
|
|
|
||||||
|
|
@ -20,9 +20,9 @@
|
||||||
onResult: () => boredState.update((n) => ({ ...n, loading: false })),
|
onResult: () => boredState.update((n) => ({ ...n, loading: false })),
|
||||||
flashMessage: {
|
flashMessage: {
|
||||||
module: flashModule,
|
module: flashModule,
|
||||||
onError: ({ result, message }) => {
|
onError: ({ result, flashMessage }) => {
|
||||||
const errorMessage = result.error.message;
|
const errorMessage = result.error.message;
|
||||||
message.set({ type: 'error', message: errorMessage });
|
flashMessage.set({ type: 'error', message: errorMessage });
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
taintedMessage: null,
|
taintedMessage: null,
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ import { RateLimiter } from 'sveltekit-rate-limiter/server';
|
||||||
import db from '../../../db';
|
import db from '../../../db';
|
||||||
import { lucia } from '$lib/server/auth';
|
import { lucia } from '$lib/server/auth';
|
||||||
import { totpSchema } from '$lib/validations/auth';
|
import { totpSchema } from '$lib/validations/auth';
|
||||||
import { users, recovery_codes } from '$db/schema';
|
import { users, recoveryCodes } from '$db/schema';
|
||||||
import type { PageServerLoad } from './$types';
|
import type { PageServerLoad } from './$types';
|
||||||
import { notSignedInMessage } from '$lib/flashMessages';
|
import { notSignedInMessage } from '$lib/flashMessages';
|
||||||
|
|
||||||
|
|
@ -99,15 +99,17 @@ export const actions: Actions = {
|
||||||
try {
|
try {
|
||||||
const totpToken = form?.data?.totpToken;
|
const totpToken = form?.data?.totpToken;
|
||||||
|
|
||||||
if (dbUser?.two_factor_enabled && dbUser?.two_factor_secret !== '' && !totpToken) {
|
const twoFactorSecretPopulated =
|
||||||
|
dbUser?.two_factor_secret !== '' && dbUser?.two_factor_secret !== null;
|
||||||
|
if (dbUser?.two_factor_enabled && !twoFactorSecretPopulated && !totpToken) {
|
||||||
return fail(400, {
|
return fail(400, {
|
||||||
form,
|
form,
|
||||||
});
|
});
|
||||||
} else if (dbUser?.two_factor_enabled && dbUser?.two_factor_secret !== '' && totpToken) {
|
} else if (twoFactorSecretPopulated && totpToken) {
|
||||||
console.log('totpToken', totpToken);
|
console.log('totpToken', totpToken);
|
||||||
const validOTP = await new TOTPController().verify(
|
const validOTP = await new TOTPController().verify(
|
||||||
totpToken,
|
totpToken,
|
||||||
decodeHex(dbUser.two_factor_secret),
|
decodeHex(dbUser.two_factor_secret ?? ''),
|
||||||
);
|
);
|
||||||
console.log('validOTP', validOTP);
|
console.log('validOTP', validOTP);
|
||||||
|
|
||||||
|
|
@ -152,17 +154,17 @@ export const actions: Actions = {
|
||||||
|
|
||||||
async function checkRecoveryCode(recoveryCode: string, userId: string) {
|
async function checkRecoveryCode(recoveryCode: string, userId: string) {
|
||||||
const userRecoveryCodes = await db.query.recoveryCodes.findMany({
|
const userRecoveryCodes = await db.query.recoveryCodes.findMany({
|
||||||
where: and(eq(recovery_codes.used, false), eq(recovery_codes.userId, userId)),
|
where: and(eq(recoveryCodes.used, false), eq(recoveryCodes.userId, userId)),
|
||||||
});
|
});
|
||||||
for (const code of userRecoveryCodes) {
|
for (const code of userRecoveryCodes) {
|
||||||
const validRecoveryCode = await new Argon2id().verify(code.code, recoveryCode);
|
const validRecoveryCode = await new Argon2id().verify(code.code, recoveryCode);
|
||||||
if (validRecoveryCode) {
|
if (validRecoveryCode) {
|
||||||
await db
|
await db
|
||||||
.update(recovery_codes)
|
.update(recoveryCodes)
|
||||||
.set({
|
.set({
|
||||||
used: true,
|
used: true,
|
||||||
})
|
})
|
||||||
.where(eq(recovery_codes.id, code.id));
|
.where(eq(recoveryCodes.id, code.id));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,19 +12,18 @@
|
||||||
import { boredState } from '$lib/stores/boredState.js';
|
import { boredState } from '$lib/stores/boredState.js';
|
||||||
|
|
||||||
export let data;
|
export let data;
|
||||||
export let form;
|
|
||||||
|
|
||||||
const superTotpForm = superForm(data.form, {
|
const superTotpForm = superForm(data.form, {
|
||||||
onSubmit: () => boredState.update((n) => ({ ...n, loading: true })),
|
onSubmit: () => boredState.update((n) => ({ ...n, loading: true })),
|
||||||
onResult: () => boredState.update((n) => ({ ...n, loading: false })),
|
onResult: () => boredState.update((n) => ({ ...n, loading: false })),
|
||||||
flashMessage: {
|
flashMessage: {
|
||||||
module: flashModule,
|
module: flashModule,
|
||||||
onError: ({ result, message }) => {
|
onError: ({ result, flashMessage }) => {
|
||||||
// Error handling for the flash message:
|
// Error handling for the flash message:
|
||||||
// - result is the ActionResult
|
// - result is the ActionResult
|
||||||
// - message is the flash store (not the status message store)
|
// - message is the flash store (not the status message store)
|
||||||
const errorMessage = result.error.message
|
const errorMessage = result.error.message
|
||||||
message.set({ type: 'error', message: errorMessage });
|
flashMessage.set({ type: 'error', message: errorMessage });
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
syncFlashMessage: false,
|
syncFlashMessage: false,
|
||||||
|
|
@ -34,7 +33,7 @@
|
||||||
delayMs: 0,
|
delayMs: 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
const { form: totpForm, errors, enhance } = superTotpForm;
|
const { form: totpForm, enhance } = superTotpForm;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:head>
|
<svelte:head>
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,6 @@ export const GET = async ({ url, locals }) => {
|
||||||
error(400, 'Invalid request');
|
error(400, 'Invalid request');
|
||||||
}
|
}
|
||||||
|
|
||||||
const { q, limit, skip, order, exact } = searchGames;
|
|
||||||
|
|
||||||
const q = searchParams?.q?.trim() || '';
|
const q = searchParams?.q?.trim() || '';
|
||||||
const limit = parseInt(searchParams?.limit) || 10;
|
const limit = parseInt(searchParams?.limit) || 10;
|
||||||
const skip = parseInt(searchParams?.skip) || 0;
|
const skip = parseInt(searchParams?.skip) || 0;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue