Skip to content

Commit 6285fd2

Browse files
committed
fix(answer-form) prevent sending double
1 parent e160274 commit 6285fd2

File tree

8 files changed

+53
-34
lines changed

8 files changed

+53
-34
lines changed

components/elements/AnswerForm.vue

+17-17
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
const props = defineProps(['questionId'])
44
55
const addAnswer = 'addAnswer';
6-
const emit = defineEmits<{(e: typeof addAnswer, answer: IAnswer): void}>()
6+
const emit = defineEmits<{ (e: typeof addAnswer, answer: IAnswer): void }>()
77
88
const questionId = props.questionId
99
@@ -15,38 +15,38 @@ const data: IAnswerPost = reactive({
1515
const showAnswerForm = useState('showAnswerForm' + questionId)
1616
1717
async function postAnswer() {
18-
const answer = await useFetch(
19-
() => `/api/ask-jack/answer`, { method: 'post', body: { data } }
20-
);
18+
const answer = await $fetch(`/api/ask-jack/answer`, { method: 'post', body: { data } });
2119
2220
const newAnswer = useState('newAnswer')
23-
newAnswer.value = answer.data.value
21+
newAnswer.value = answer
2422
25-
emit('addAnswer', newAnswer.value as IAnswer)
23+
emit('addAnswer', answer)
2624
2725
data.text = ''
26+
console.log('&&&&&&&&& end post answer')
2827
}
28+
2929
</script>
3030

3131

3232
<template>
33-
<form @submit.preventDefault="postAnswer">
34-
<label for="message" class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-400">Answer</label>
35-
<textarea v-model="data.text" id="message" rows="4"
36-
class="block p-2.5 w-full text-sm text-gray-900 bg-gray-50 rounded-lg border border-gray-300 focus:ring-indigo-500 focus:border-indigo-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-indigo-500 dark:focus:border-indigo-500"
37-
placeholder="Be specific and kind">
33+
<form @submit.preventDefault="postAnswer">
34+
<label for="message" class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-400">Answer</label>
35+
<textarea v-model="data.text" id="message" rows="4"
36+
class="block p-2.5 w-full text-sm text-gray-900 bg-gray-50 rounded-lg border border-gray-300 focus:ring-indigo-500 focus:border-indigo-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-indigo-500 dark:focus:border-indigo-500"
37+
placeholder="Be specific and kind">
3838
</textarea>
39-
<div>
40-
</div>
41-
<div class="flex justify-end">
42-
<button @click="postAnswer" type="button"
39+
<div>
40+
</div>
41+
<div class="flex justify-end">
42+
<button @click="postAnswer" type="button"
4343
class="mt-5 px-6 py-3.5 text-white bg-gradient-to-r from-indigo-500 via-indigo-600 to-indigo-700 hover:bg-gradient-to-br focus:ring-4 focus:outline-none focus:ring-indigo-300 dark:focus:ring-indigo-800 font-medium rounded-lg text-sm px-5 py-2.5 text-center mr-2 mb-2">
4444
Submit
4545
</button>
4646
<button @click="showAnswerForm = !showAnswerForm" type="button"
4747
class="mt-5 px-6 py-3.5 text-white bg-gradient-to-r from-red-500 via-red-600 to-red-700 hover:bg-gradient-to-br focus:ring-4 focus:outline-none focus:ring-indigo-300 dark:focus:ring-indigo-800 font-medium rounded-lg text-sm px-5 py-2.5 text-center mr-2 mb-2">
4848
Cancel
4949
</button>
50-
</div>
51-
</form>
50+
</div>
51+
</form>
5252
</template>

pages/ask-jack/question/[id].vue

+1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ async function deleteQuestion() {
3636
3737
const editEndpoint = '/api/ask-jack/edit-question'
3838
function addAnswer(answer: IAnswer) {
39+
console.log('&&&&&&&&& add answer')
3940
question.value?.answers.push(answer)
4041
showAnswerForm.value = false
4142
}

server/api/ask-jack/answer.ts

+15-4
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,24 @@
1-
import { defineEventHandler, readBody, getCookie } from "h3";
1+
import { readBody, getCookie } from "h3";
22
import { createAnswer } from "~/server/database/repositories/askJackRespository";
33
import { getUserBySessionToken } from '~/server/services/sessionService'
44

5-
export default defineEventHandler(async (event) => {
5+
export default eventHandler(async (event) => {
66
const body = await readBody(event)
77
const data: IAnswerPost = body.data
88

9-
const authToken = getCookie(event, 'auth_token')
10-
const user = await getUserBySessionToken(authToken)
9+
const authToken = getCookie(event, 'auth_token') ?? null
10+
11+
if(authToken == null) {
12+
throw Error('unauthorized')
13+
}
14+
15+
const user = await getUserBySessionToken(authToken)
16+
17+
if(!user) {
18+
throw Error('unauthorized')
19+
}
20+
21+
console.log('************ create answer *******************')
1122

1223
return await createAnswer(data, user.id)
1324
})

server/api/ask-jack/search.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import { CompatibilityEvent, defineEventHandler } from "h3";
1+
22
import { searchQuestions } from "~/server/database/repositories/askJackRespository";
33
import { getUserById } from "~/server/database/repositories/userRespository";
44

5-
export default defineEventHandler(async (event: CompatibilityEvent) => {
5+
export default eventHandler(async (event) => {
66
const queries = getQuery(event)
77

88
const questions = await searchQuestions(queries.search as string)

server/database/repositories/sessionRepository.ts

+10-5
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,28 @@
11
import { IUser } from '~/types/IUser';
22
import prisma from "~/server/database/client";
33
import { ISession } from '~~/types/ISession';
4+
import { User } from '@prisma/client';
45

5-
export async function createSession(data: ISession): Promise<ISession> {
6+
export async function createSession(sessionData: ISession): Promise<ISession> {
7+
if (!sessionData.authToken) {
8+
throw Error('missing auth token for session')
9+
}
10+
611
return await prisma.session.create({
712
data: {
8-
userId: data.userId,
9-
authToken: data.authToken
13+
userId: sessionData.userId,
14+
authToken: sessionData.authToken
1015
},
1116
})
1217
}
1318

1419
export async function getSessionByAuthToken(authToken: string): Promise<ISession> {
15-
const user: IUser = await getUserByAuthToken(authToken) as unknown as IUser
20+
const user: User = await getUserByAuthToken(authToken) as unknown as User
1621

1722
return { authToken, user }
1823
}
1924

20-
async function getUserByAuthToken(authToken: string): Promise<IUser> {
25+
async function getUserByAuthToken(authToken: string): Promise<User | null> {
2126
return prisma.session.findUnique({
2227
where: {
2328
authToken: authToken,

server/services/sessionService.ts

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import { sanitizeUserForFrontend } from '~~/server/services/userService';
2-
import { CompatibilityEvent } from "h3"
2+
import { H3Event } from "h3"
33
import { createSession, getSessionByAuthToken } from "~~/server/database/repositories/sessionRepository"
44
import { IUser } from "~~/types/IUser"
55
import { v4 as uuidv4 } from 'uuid'
6+
import { User } from '@prisma/client';
67

78

8-
export async function makeSession(user: IUser, event: CompatibilityEvent): Promise<IUser> {
9+
export async function makeSession(user: IUser, event: H3Event): Promise<User|undefined> {
910
const authToken = uuidv4().replaceAll('-', '')
1011
const session = await createSession({ authToken, userId: user.id })
1112
const userId = session.userId
@@ -18,7 +19,7 @@ export async function makeSession(user: IUser, event: CompatibilityEvent): Promi
1819
throw Error('Error Creating Session')
1920
}
2021

21-
export async function getUserBySessionToken(authToken: string): Promise<IUser> {
22+
export async function getUserBySessionToken(authToken: string): Promise<User|undefined> {
2223
const session = await getSessionByAuthToken(authToken)
2324

2425
return sanitizeUserForFrontend(session.user)

server/services/userService.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { validate } from '~~/server/services/validator';
44
import { H3Event } from 'h3';
55
import { getUserBySessionToken } from './sessionService';
66
import { isString } from '@vueuse/core';
7+
import { User } from '@prisma/client';
78

89
export async function validateUser(data: RegistationRequest): Promise<FormValidation> {
910

@@ -17,7 +18,7 @@ export async function validateUser(data: RegistationRequest): Promise<FormValida
1718
return { hasErrors: false }
1819
}
1920

20-
export function sanitizeUserForFrontend(user: IUser | undefined): IUser | undefined {
21+
export function sanitizeUserForFrontend(user: User | undefined): User | undefined {
2122

2223
if (!user) {
2324
return user

types/ISession.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import { IUser } from "./IUser";
1+
import { User } from "@prisma/client";
22

33
export interface ISession {
44
authToken?: string;
5-
user?: IUser
5+
user?: User
66
userId?: number
77
}

0 commit comments

Comments
 (0)