Fixing get all wishlists, style wishlist cards, and fix TOTP.

This commit is contained in:
Bradley Shellnut 2024-10-01 17:09:56 -07:00
parent fc4396ccdd
commit 4032838f49
12 changed files with 68 additions and 68 deletions

View file

@ -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",

View file

@ -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

View file

@ -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,
},
})
}

View file

@ -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),
})
}

View file

@ -51,6 +51,7 @@ export class WishlistsRepository {
columns: {
cuid: true,
name: true,
createdAt: true,
},
})
}

View file

@ -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) {

View file

@ -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>

View file

@ -34,15 +34,21 @@ let { children } = $props()
.security-nav {
display: flex;
@media (width <= 1000px) {
display: grid;
}
nav {
width: 16rem;
position: sticky;
top: 0;
left: 0;
background-color: #fff;
padding: 1rem;
border-right: 1px solid #ddd;
height: 100vh;
@media (width > 1000px) {
width: 16rem;
position: sticky;
top: 0;
left: 0;
background-color: #fff;
padding: 1rem;
border-right: 1px solid #ddd;
height: 100vh;
}
ul {
list-style-type: none;

View file

@ -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

View file

@ -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')

View file

@ -1,4 +1,6 @@
<script lang="ts">
import * as Card from '$components/ui/card'
const { data } = $props()
const { wishlists = [] } = data
</script>
@ -8,21 +10,25 @@ 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>
{: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>
{/each}
{/if}
</div>
<div class="wishlist-list">
{#if wishlists.length === 0}
<h2>You have no wishlists</h2>
{:else}
{#each wishlists as wishlist}
<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>
@ -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));

View file

@ -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}