mirror of
https://github.com/BradNut/boredgame
synced 2025-09-08 17:40:22 +00:00
Fixing get all wishlists, style wishlist cards, and fix TOTP.
This commit is contained in:
parent
fc4396ccdd
commit
4032838f49
12 changed files with 68 additions and 68 deletions
|
|
@ -80,7 +80,7 @@
|
|||
"@hono/zod-validator": "^0.2.2",
|
||||
"@iconify-icons/line-md": "^1.2.30",
|
||||
"@iconify-icons/mdi": "^1.2.48",
|
||||
"@internationalized/date": "^3.5.5",
|
||||
"@internationalized/date": "^3.5.6",
|
||||
"@lucia-auth/adapter-drizzle": "^1.1.0",
|
||||
"@lukeed/uuid": "^2.0.1",
|
||||
"@neondatabase/serverless": "^0.9.5",
|
||||
|
|
@ -97,7 +97,7 @@
|
|||
"@types/feather-icons": "^4.29.4",
|
||||
"bits-ui": "^0.21.13",
|
||||
"boardgamegeekclient": "^1.9.1",
|
||||
"bullmq": "^5.14.0",
|
||||
"bullmq": "^5.15.0",
|
||||
"class-variance-authority": "^0.7.0",
|
||||
"clsx": "^2.1.1",
|
||||
"cookie": "^0.6.0",
|
||||
|
|
|
|||
|
|
@ -27,8 +27,8 @@ importers:
|
|||
specifier: ^1.2.48
|
||||
version: 1.2.48
|
||||
'@internationalized/date':
|
||||
specifier: ^3.5.5
|
||||
version: 3.5.5
|
||||
specifier: ^3.5.6
|
||||
version: 3.5.6
|
||||
'@lucia-auth/adapter-drizzle':
|
||||
specifier: ^1.1.0
|
||||
version: 1.1.0(drizzle-orm@0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.10)(pg@8.13.0(pg-native@3.2.0))(postgres@3.4.4))(lucia@3.2.0)
|
||||
|
|
@ -78,8 +78,8 @@ importers:
|
|||
specifier: ^1.9.1
|
||||
version: 1.9.1
|
||||
bullmq:
|
||||
specifier: ^5.14.0
|
||||
version: 5.14.0
|
||||
specifier: ^5.15.0
|
||||
version: 5.15.0
|
||||
class-variance-authority:
|
||||
specifier: ^0.7.0
|
||||
version: 0.7.0
|
||||
|
|
@ -1415,8 +1415,8 @@ packages:
|
|||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@internationalized/date@3.5.5':
|
||||
resolution: {integrity: sha512-H+CfYvOZ0LTJeeLOqm19E3uj/4YjrmOFtBufDHPfvtI80hFAMqtrp7oCACpe4Cil5l8S0Qu/9dYfZc/5lY8WQQ==}
|
||||
'@internationalized/date@3.5.6':
|
||||
resolution: {integrity: sha512-jLxQjefH9VI5P9UQuqB6qNKnvFt1Ky1TPIzHGsIlCi7sZZoMR8SdYbBGRvM0y+Jtb+ez4ieBzmiAUcpmPYpyOw==}
|
||||
|
||||
'@ioredis/commands@1.2.0':
|
||||
resolution: {integrity: sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==}
|
||||
|
|
@ -2366,8 +2366,8 @@ packages:
|
|||
buffer-from@1.1.2:
|
||||
resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
|
||||
|
||||
bullmq@5.14.0:
|
||||
resolution: {integrity: sha512-qxZHtRuGEp0oHM1aNokuZ4gA0xr6vcZQPe1OLuQoDTuhaEXB4faxApUoo85v/PHnzrniAAqNT9kqD+UBbmECDQ==}
|
||||
bullmq@5.15.0:
|
||||
resolution: {integrity: sha512-h53shVjx8s6wxYGtUfzAfENpSP7N5T0D4PMTvbZncozLjb8yUKhopfpa7PmcpQfq7SSO9dm/OZ9XQuGOCSGNug==}
|
||||
|
||||
bytes@3.1.2:
|
||||
resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==}
|
||||
|
|
@ -5668,7 +5668,7 @@ snapshots:
|
|||
'@img/sharp-win32-x64@0.33.5':
|
||||
optional: true
|
||||
|
||||
'@internationalized/date@3.5.5':
|
||||
'@internationalized/date@3.5.6':
|
||||
dependencies:
|
||||
'@swc/helpers': 0.5.13
|
||||
|
||||
|
|
@ -5746,7 +5746,7 @@ snapshots:
|
|||
dependencies:
|
||||
'@floating-ui/core': 1.6.7
|
||||
'@floating-ui/dom': 1.6.10
|
||||
'@internationalized/date': 3.5.5
|
||||
'@internationalized/date': 3.5.6
|
||||
dequal: 2.0.3
|
||||
focus-trap: 7.5.4
|
||||
nanoid: 5.0.7
|
||||
|
|
@ -5756,7 +5756,7 @@ snapshots:
|
|||
dependencies:
|
||||
'@floating-ui/core': 1.6.7
|
||||
'@floating-ui/dom': 1.6.10
|
||||
'@internationalized/date': 3.5.5
|
||||
'@internationalized/date': 3.5.6
|
||||
dequal: 2.0.3
|
||||
focus-trap: 7.5.4
|
||||
nanoid: 5.0.7
|
||||
|
|
@ -6577,7 +6577,7 @@ snapshots:
|
|||
|
||||
bits-ui@0.21.15(svelte@5.0.0-next.175):
|
||||
dependencies:
|
||||
'@internationalized/date': 3.5.5
|
||||
'@internationalized/date': 3.5.6
|
||||
'@melt-ui/svelte': 0.76.2(svelte@5.0.0-next.175)
|
||||
nanoid: 5.0.7
|
||||
svelte: 5.0.0-next.175
|
||||
|
|
@ -6631,7 +6631,7 @@ snapshots:
|
|||
|
||||
buffer-from@1.1.2: {}
|
||||
|
||||
bullmq@5.14.0:
|
||||
bullmq@5.15.0:
|
||||
dependencies:
|
||||
cron-parser: 4.9.0
|
||||
ioredis: 5.4.1
|
||||
|
|
|
|||
|
|
@ -48,6 +48,11 @@ export class CollectionsRepository {
|
|||
async findAllByUserId(userId: string, db = this.drizzle.db) {
|
||||
return db.query.collections.findMany({
|
||||
where: eq(collections.user_id, userId),
|
||||
columns: {
|
||||
cuid: true,
|
||||
name: true,
|
||||
createdAt: true,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ export class RecoveryCodesRepository {
|
|||
}
|
||||
|
||||
async findAllByUserId(userId: string, db = this.drizzle.db) {
|
||||
return db.query.recoveryCodesTable.findFirst({
|
||||
return db.query.recoveryCodesTable.findMany({
|
||||
where: eq(recoveryCodesTable.userId, userId),
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ export class WishlistsRepository {
|
|||
columns: {
|
||||
cuid: true,
|
||||
name: true,
|
||||
createdAt: true,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import { CredentialsRepository } from '$lib/server/api/repositories/credentials.repository'
|
||||
import { HMAC } from 'oslo/crypto'
|
||||
import { decodeHex, encodeHexLowerCase } from '@oslojs/encoding'
|
||||
import { verifyTOTP } from '@oslojs/otp'
|
||||
import { inject, injectable } from 'tsyringe'
|
||||
|
|
@ -22,12 +21,11 @@ export class TotpService {
|
|||
}
|
||||
|
||||
async create(userId: string) {
|
||||
const twoFactorSecret = await new HMAC('SHA-1').generateKey()
|
||||
|
||||
const secret = new Uint8Array(20)
|
||||
try {
|
||||
return await this.credentialsRepository.create({
|
||||
user_id: userId,
|
||||
secret_data: encodeHexLowerCase(twoFactorSecret),
|
||||
secret_data: encodeHexLowerCase(crypto.getRandomValues(secret)),
|
||||
type: 'totp',
|
||||
})
|
||||
} catch (e) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
<script lang="ts">
|
||||
import * as Card from '$components/ui/card'
|
||||
|
||||
const { data } = $props()
|
||||
let collections = data?.collections || []
|
||||
</script>
|
||||
|
|
@ -9,14 +10,13 @@ let collections = data?.collections || []
|
|||
</svelte:head>
|
||||
|
||||
<div class="container">
|
||||
<h1>Your Collections</h1>
|
||||
|
||||
<h1>Your Collections</h1>
|
||||
<div class="collection-list">
|
||||
{#if collections.length === 0}
|
||||
<h2>You have no collections</h2>
|
||||
{:else}
|
||||
{#each collections as collection}
|
||||
<Card.Root>
|
||||
<Card.Root class="shadow-sm hover:shadow-md transition-shadow duration-300 ease-in-out">
|
||||
<Card.Header>
|
||||
<Card.Title>{collection.name}</Card.Title>
|
||||
</Card.Header>
|
||||
|
|
@ -25,10 +25,6 @@ let collections = data?.collections || []
|
|||
<p>Created at: {new Date(collection.createdAt).toLocaleString()}</p>
|
||||
</Card.Content>
|
||||
</Card.Root>
|
||||
<!-- <div class="collection grid gap-0.5">
|
||||
<h2><a href="/collections/{collection.cuid}">{collection.name}</a></h2>
|
||||
<h3>Created at: {new Date(collection.createdAt).toLocaleString()}</h3>
|
||||
</div> -->
|
||||
{/each}
|
||||
{/if}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -34,7 +34,12 @@ let { children } = $props()
|
|||
.security-nav {
|
||||
display: flex;
|
||||
|
||||
@media (width <= 1000px) {
|
||||
display: grid;
|
||||
}
|
||||
|
||||
nav {
|
||||
@media (width > 1000px) {
|
||||
width: 16rem;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
|
|
@ -43,6 +48,7 @@ let { children } = $props()
|
|||
padding: 1rem;
|
||||
border-right: 1px solid #ddd;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style-type: none;
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import { notSignedInMessage } from '$lib/flashMessages'
|
||||
import env from '$lib/server/api/common/env'
|
||||
import { decodeHex, encodeBase32 } from '@oslojs/encoding'
|
||||
import { createTOTPKeyURI } from '@oslojs/otp'
|
||||
import { type Actions, fail } from '@sveltejs/kit'
|
||||
import kebabCase from 'just-kebab-case'
|
||||
import { encodeBase32, decodeHex } from '@oslojs/encoding'
|
||||
import { createTOTPKeyURI } from '@oslojs/otp'
|
||||
import QRCode from 'qrcode'
|
||||
import { redirect } from 'sveltekit-flash-message/server'
|
||||
import { zod } from 'sveltekit-superforms/adapters'
|
||||
|
|
@ -63,7 +63,7 @@ export const load: PageServerLoad = async (event) => {
|
|||
})
|
||||
}
|
||||
const decodedHexSecret = decodeHex(createdTotpCredentials.secret_data)
|
||||
const secret = encodeBase32(new TextEncoder().encode(decodedHexSecret))
|
||||
const secret = encodeBase32(decodedHexSecret)
|
||||
const intervalInSeconds = 30
|
||||
const digits = 6
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import { notSignedInMessage } from '$lib/flashMessages.js'
|
||||
import { gamesTable, wishlist_items, wishlistsTable } from '$lib/server/api/databases/tables'
|
||||
import { db } from '$lib/server/api/packages/drizzle'
|
||||
import { userNotAuthenticated } from '$lib/server/auth-utils'
|
||||
import { modifyListGameSchema } from '$lib/validations/zod-schemas'
|
||||
import { type Actions, error, fail } from '@sveltejs/kit'
|
||||
import { and, eq } from 'drizzle-orm'
|
||||
|
|
@ -17,15 +16,8 @@ export async function load(event) {
|
|||
throw redirect(302, '/login', notSignedInMessage, event)
|
||||
}
|
||||
|
||||
const userWishlists = await db.query.wishlists.findMany({
|
||||
columns: {
|
||||
cuid: true,
|
||||
name: true,
|
||||
createdAt: true,
|
||||
},
|
||||
where: eq(wishlistsTable.user_id, authedUser.id),
|
||||
})
|
||||
console.log('wishlists', userWishlists)
|
||||
const { data } = await locals.api.wishlists.$get().then(locals.parseApiResponse)
|
||||
const userWishlists = data?.wishlists
|
||||
|
||||
if (userWishlists?.length === 0) {
|
||||
console.log('Wishlists not found')
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
<script lang="ts">
|
||||
import * as Card from '$components/ui/card'
|
||||
|
||||
const { data } = $props()
|
||||
const { wishlists = [] } = data
|
||||
</script>
|
||||
|
|
@ -8,22 +10,26 @@ const { wishlists = [] } = data
|
|||
</svelte:head>
|
||||
|
||||
<div class="container">
|
||||
<h1>Your wishlistsTable</h1>
|
||||
<h1>Your wishlists</h1>
|
||||
|
||||
<div class="wishlists">
|
||||
<div class="wishlist-list">
|
||||
{#if wishlists.length === 0}
|
||||
<h2>You have no wishlistsTable</h2>
|
||||
<h2>You have no wishlists</h2>
|
||||
{:else}
|
||||
{#each wishlists as wishlist}
|
||||
<div class="collection grid gap-0.5">
|
||||
<h2><a href="/wishlists/{wishlist.cuid}">{wishlist.name}</a></h2>
|
||||
<h3>Created at: {new Date(wishlist.created_at).toLocaleString()}</h3>
|
||||
</div>
|
||||
<Card.Root class="shadow-sm hover:shadow-md transition-shadow duration-300 ease-in-out">
|
||||
<a href="/wishlists/{wishlist.cuid}">
|
||||
<Card.Header>
|
||||
<Card.Title>{wishlist.name}</Card.Title>
|
||||
</Card.Header>
|
||||
<Card.Content>
|
||||
<h3>Created at: {new Date(wishlist.createdAt).toLocaleString()}</h3>
|
||||
</Card.Content>
|
||||
</a>
|
||||
</Card.Root>
|
||||
{/each}
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style lang="postcss">
|
||||
|
|
@ -32,10 +38,6 @@ const { wishlists = [] } = data
|
|||
width: 100%;
|
||||
}
|
||||
|
||||
.wishlists {
|
||||
margin: 2rem 0;
|
||||
}
|
||||
|
||||
.wishlist-list {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(200px, 1fr));
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ const welcomeName = $derived.by(() => {
|
|||
welcomeName += data?.user?.firstName
|
||||
}
|
||||
if (data?.user?.lastName) {
|
||||
welcomeName += ' ' + data?.user?.lastName
|
||||
welcomeName = welcomeName.length === 0 ? data?.user?.lastName : welcomeName
|
||||
}
|
||||
|
||||
if (welcomeName.length === 0) {
|
||||
|
|
@ -23,7 +23,7 @@ const welcomeName = $derived.by(() => {
|
|||
{#if user}
|
||||
<h1>Welcome, {welcomeName}!</h1>
|
||||
<div>
|
||||
<h2>You wishlistsTable:</h2>
|
||||
<h2>You wishlists:</h2>
|
||||
{#each wishlists as wishlist}
|
||||
<a href="/wishlists/{wishlist.cuid}">{wishlist.name}</a>
|
||||
{/each}
|
||||
|
|
|
|||
Loading…
Reference in a new issue