Finished single form and all forms of user getting. Added resolver authentication. Some code refactors
This commit is contained in:
parent
aa8fdda13d
commit
db8b3eea51
4
.gitignore
vendored
4
.gitignore
vendored
@ -2,10 +2,10 @@
|
||||
|
||||
/build
|
||||
|
||||
.env.local
|
||||
|
||||
*.gen.ts
|
||||
|
||||
*.local*
|
||||
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
30
src/controllers/auth.ts
Normal file
30
src/controllers/auth.ts
Normal file
@ -0,0 +1,30 @@
|
||||
import { PrismaClient } from "@prisma/client"
|
||||
|
||||
import { getDBFormAuthor } from "../db"
|
||||
import { CheckRightsAndResolve } from "./types"
|
||||
|
||||
const checkRightsAndResolve: CheckRightsAndResolve = async (params) => {
|
||||
const { user, expected, controller } = params
|
||||
|
||||
if (!user) throw new Error("Authentication required")
|
||||
|
||||
if (expected.id.self && (!expected.admin || user.admin)) return controller(user.id)
|
||||
else if (
|
||||
(!expected.id.n || user.id == expected.id.n) &&
|
||||
(!expected.admin || user.admin)
|
||||
)
|
||||
return controller()
|
||||
throw new Error("Authentication error")
|
||||
}
|
||||
|
||||
const getFormAuthor = async (db: PrismaClient, id: number) => {
|
||||
const author = await getDBFormAuthor(db, id)
|
||||
|
||||
if (!author) throw Error("Not found")
|
||||
|
||||
const authorId = author.author.id
|
||||
|
||||
return authorId
|
||||
}
|
||||
|
||||
export { checkRightsAndResolve, getFormAuthor }
|
54
src/controllers/form.ts
Normal file
54
src/controllers/form.ts
Normal file
@ -0,0 +1,54 @@
|
||||
import { PrismaClient } from "@prisma/client"
|
||||
import { getDBForm, getDBFormByUser } from "../db"
|
||||
import { FullForm } from "../db/types"
|
||||
|
||||
import { Form as GraphqlForm, FormSubmission } from "../typeDefs/typeDefs.gen"
|
||||
|
||||
const getForm = async (
|
||||
db: PrismaClient,
|
||||
id: number
|
||||
): Promise<GraphqlForm | null> => {
|
||||
const dbForm: FullForm = await getDBForm(db, id)
|
||||
|
||||
if (dbForm == null) throw new Error("Not found")
|
||||
|
||||
const form: GraphqlForm = {
|
||||
id: dbForm.id,
|
||||
title: dbForm.title,
|
||||
questions: [...dbForm.choisesQuestions, ...dbForm.inputQuestions],
|
||||
dateCreated: dbForm.dateCreated.toString(),
|
||||
submissions: dbForm.submissions.map<FormSubmission>((submission) => ({
|
||||
answers: submission.answers,
|
||||
date: submission.date.toString(),
|
||||
id: submission.id,
|
||||
})),
|
||||
author: dbForm.author,
|
||||
}
|
||||
|
||||
return form
|
||||
}
|
||||
|
||||
const getForms = async (
|
||||
db: PrismaClient,
|
||||
userId: number
|
||||
): Promise<GraphqlForm[]> => {
|
||||
const dbForms = await getDBFormByUser(db, userId)
|
||||
|
||||
const forms = [
|
||||
...dbForms.map((form) => ({
|
||||
id: form.id,
|
||||
title: form.title,
|
||||
questions: [...form.choisesQuestions, ...form.inputQuestions],
|
||||
dateCreated: form.dateCreated.toString(),
|
||||
submissions: form.submissions.map<FormSubmission>((submission) => ({
|
||||
answers: submission.answers,
|
||||
date: submission.date.toString(),
|
||||
id: submission.id,
|
||||
})),
|
||||
})),
|
||||
]
|
||||
|
||||
return forms
|
||||
}
|
||||
|
||||
export { getForm, getForms }
|
@ -1,77 +1,4 @@
|
||||
import { PrismaClient } from "@prisma/client"
|
||||
import { getDBForm, getDBFormAuthor, getDBFormByUser } from "../db"
|
||||
import { FullForm } from "../db/types"
|
||||
import { getForm, getForms } from "./form"
|
||||
import { checkRightsAndResolve, getFormAuthor } from "./auth"
|
||||
|
||||
import { Form as GraphqlForm, FormSubmission } from "../typeDefs/typeDefs.gen"
|
||||
import { JwtPayloadType } from "../types"
|
||||
|
||||
const getForm = async (
|
||||
db: PrismaClient,
|
||||
id?: number
|
||||
): Promise<GraphqlForm | null> => {
|
||||
const dbForm: FullForm = await getDBForm(db, id)
|
||||
|
||||
if (dbForm == null) throw new Error("Not found")
|
||||
|
||||
const form: GraphqlForm = {
|
||||
id: dbForm.id,
|
||||
title: dbForm.title,
|
||||
questions: [...dbForm.choisesQuestions, ...dbForm.inputQuestions],
|
||||
dateCreated: dbForm.dateCreated.toString(),
|
||||
submissions: dbForm.submissions.map<FormSubmission>((submission) => ({
|
||||
answers: submission.answers,
|
||||
date: submission.date.toString(),
|
||||
id: submission.id,
|
||||
})),
|
||||
}
|
||||
|
||||
return form
|
||||
}
|
||||
|
||||
const getForms = async (
|
||||
db: PrismaClient,
|
||||
userId: number
|
||||
): Promise<GraphqlForm[]> => {
|
||||
const dbForms = await getDBFormByUser(db, userId)
|
||||
|
||||
const forms = [
|
||||
...dbForms.map((form) => ({
|
||||
id: form.id,
|
||||
title: form.title,
|
||||
questions: [...form.choisesQuestions, ...form.inputQuestions],
|
||||
dateCreated: form.dateCreated.toString(),
|
||||
submissions: form.submissions.map<FormSubmission>((submission) => ({
|
||||
answers: submission.answers,
|
||||
date: submission.date.toString(),
|
||||
id: submission.id,
|
||||
})),
|
||||
})),
|
||||
]
|
||||
|
||||
return forms
|
||||
}
|
||||
|
||||
const checkRightsAndResolve = async (
|
||||
user: JwtPayloadType,
|
||||
expected: JwtPayloadType,
|
||||
controller: any
|
||||
) => {
|
||||
if (
|
||||
(!expected.id || user.id == expected.id) &&
|
||||
(!expected.admin || expected.admin)
|
||||
)
|
||||
return controller()
|
||||
throw new Error("Authentification error")
|
||||
}
|
||||
|
||||
const getFormAuthor = async (db: PrismaClient, id: number) => {
|
||||
const author = await getDBFormAuthor(db, id)
|
||||
|
||||
if (!author) throw Error("Not found")
|
||||
|
||||
const authorId = author.author.id
|
||||
|
||||
return authorId
|
||||
}
|
||||
|
||||
export { getForm, getForms, checkRightsAndResolve, getFormAuthor }
|
||||
export { checkRightsAndResolve, getForm, getFormAuthor, getForms }
|
||||
|
21
src/controllers/types.ts
Normal file
21
src/controllers/types.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import { JwtPayloadType } from "../types"
|
||||
|
||||
type expectedType = {
|
||||
id: {
|
||||
n: number
|
||||
self: boolean
|
||||
}
|
||||
admin: boolean
|
||||
}
|
||||
|
||||
interface ICheckRightsAndResolve<T> {
|
||||
user: JwtPayloadType | null
|
||||
expected: expectedType
|
||||
controller: T
|
||||
}
|
||||
|
||||
type CheckRightsAndResolve = <ReturnType, ControllerType extends Function>(
|
||||
params: ICheckRightsAndResolve<ControllerType>
|
||||
) => Promise<ReturnType>
|
||||
|
||||
export { CheckRightsAndResolve }
|
@ -1,12 +1,17 @@
|
||||
import { PrismaClient } from "@prisma/client"
|
||||
|
||||
const getDBForm = async (db: PrismaClient, id?: number) => {
|
||||
const getDBForm = async (db: PrismaClient, id: number) => {
|
||||
return await db.form.findOne({
|
||||
where: {
|
||||
id: id ? id : undefined,
|
||||
id,
|
||||
},
|
||||
include: {
|
||||
author: true,
|
||||
author: {
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
},
|
||||
},
|
||||
choisesQuestions: {
|
||||
include: {
|
||||
variants: true,
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { ApolloServer } from "apollo-server-express"
|
||||
import { ApolloServer, makeExecutableSchema } from "apollo-server-express"
|
||||
import express from "express"
|
||||
import expressJwt from "express-jwt"
|
||||
import { PrismaClient } from "@prisma/client"
|
||||
@ -18,8 +18,10 @@ app.use(
|
||||
)
|
||||
|
||||
const server = new ApolloServer({
|
||||
typeDefs,
|
||||
resolvers,
|
||||
schema: makeExecutableSchema({
|
||||
typeDefs,
|
||||
resolvers,
|
||||
}),
|
||||
context: async ({
|
||||
req,
|
||||
}: {
|
||||
|
@ -1,4 +1,9 @@
|
||||
import { checkRightsAndResolve, getForm, getFormAuthor, getForms } from "../controllers"
|
||||
import {
|
||||
checkRightsAndResolve,
|
||||
getForm,
|
||||
getFormAuthor,
|
||||
getForms,
|
||||
} from "../controllers"
|
||||
import {
|
||||
Form,
|
||||
QueryFormArgs,
|
||||
@ -18,11 +23,17 @@ const formQuery: Resolver<Form, {}, ApolloContextType, QueryFormArgs> = async (
|
||||
|
||||
const getFormById = () => getForm(db, id)
|
||||
|
||||
return await checkRightsAndResolve(
|
||||
user!,
|
||||
{ id: authorId, admin: false },
|
||||
getFormById
|
||||
)
|
||||
return await checkRightsAndResolve({
|
||||
user,
|
||||
expected: {
|
||||
id: {
|
||||
n: 0,
|
||||
self: false,
|
||||
},
|
||||
admin: false,
|
||||
},
|
||||
controller: getFormById,
|
||||
})
|
||||
} catch (err) {
|
||||
return err
|
||||
}
|
||||
@ -31,10 +42,25 @@ const formQuery: Resolver<Form, {}, ApolloContextType, QueryFormArgs> = async (
|
||||
const formsQuery: Resolver<Form[], {}, ApolloContextType> = async (
|
||||
_,
|
||||
__,
|
||||
{ db }
|
||||
{ db, user }
|
||||
) => {
|
||||
try {
|
||||
return await getForms(db, 1)
|
||||
const getFormsByUserId = (userId: number) => getForms(db, userId)
|
||||
|
||||
return await checkRightsAndResolve<
|
||||
Form[],
|
||||
(userId: number) => Promise<Form[] | null>
|
||||
>({
|
||||
user,
|
||||
expected: {
|
||||
id: {
|
||||
n: 0,
|
||||
self: true,
|
||||
},
|
||||
admin: false,
|
||||
},
|
||||
controller: getFormsByUserId,
|
||||
})
|
||||
} catch (err) {
|
||||
return err
|
||||
}
|
||||
|
@ -1,5 +1,9 @@
|
||||
import jwt from "jsonwebtoken"
|
||||
import { MutationLoginArgs, Resolver, User } from "../typeDefs/typeDefs.gen"
|
||||
import {
|
||||
MutationLoginArgs,
|
||||
Resolver,
|
||||
User,
|
||||
} from "../typeDefs/typeDefs.gen"
|
||||
import { ApolloContextType, JwtPayloadType } from "../types"
|
||||
|
||||
const loginResolver: Resolver<
|
||||
|
@ -13,6 +13,7 @@ type Form {
|
||||
questions: [Question!]!
|
||||
submissions: [FormSubmission!]!
|
||||
dateCreated: String!
|
||||
author: User
|
||||
}
|
||||
|
||||
interface Question {
|
||||
@ -73,6 +74,6 @@ enum AnswerType {
|
||||
type User {
|
||||
name: String!
|
||||
id: Int!
|
||||
forms: [Form!]!
|
||||
forms: [Form!]
|
||||
token: String
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user