Added user query, some code refactors
This commit is contained in:
parent
ec2c5feb69
commit
301281b7fc
@ -9,15 +9,17 @@ import jwt from 'jsonwebtoken'
|
||||
require('dotenv').config()
|
||||
|
||||
import { getDBFormAuthor } from '../db'
|
||||
import { sendToken } from '../mailer'
|
||||
import { CheckRightsAndResolve } from './types'
|
||||
|
||||
const checkRightsAndResolve: CheckRightsAndResolve = async (params) => {
|
||||
const { user, expected, controller } = params
|
||||
|
||||
if (!user) throw new AuthenticationError('Authentication required')
|
||||
if (!user) throw new AuthenticationError('Authorization required')
|
||||
|
||||
if (expected.id.self) return controller(user.id)
|
||||
if (!expected.id.n || user.id == expected.id.n) return controller()
|
||||
if (expected.id && expected.self) return controller(expected.id || user.id)
|
||||
if (expected.self) return controller(user.id)
|
||||
if (!expected.id || user.id == expected.id) return controller()
|
||||
|
||||
throw new ForbiddenError('Access denied')
|
||||
}
|
||||
@ -39,4 +41,15 @@ const tokenGenerate = (email: string, id: number) => {
|
||||
})
|
||||
}
|
||||
|
||||
export { checkRightsAndResolve, getFormAuthor, tokenGenerate }
|
||||
const sendTokenEmail = async (
|
||||
email: string,
|
||||
user: { id: number; name: string }
|
||||
) => {
|
||||
const token = tokenGenerate(email, user.id)
|
||||
|
||||
const res = await sendToken(user.name, email, token)
|
||||
|
||||
if (res[0].statusCode != 202) return new ApolloError("Couldn't send email")
|
||||
}
|
||||
|
||||
export { checkRightsAndResolve, getFormAuthor, tokenGenerate, sendTokenEmail }
|
||||
|
@ -1,11 +1,8 @@
|
||||
import { JwtPayloadType } from "../types"
|
||||
import { JwtPayloadType } from '../types'
|
||||
|
||||
type expectedType = {
|
||||
id: {
|
||||
n: number
|
||||
self: boolean
|
||||
}
|
||||
admin: boolean
|
||||
id: number
|
||||
self: boolean
|
||||
}
|
||||
|
||||
interface ICheckRightsAndResolve<T> {
|
||||
|
@ -1,9 +1,12 @@
|
||||
import { PrismaClient } from "@prisma/client"
|
||||
import { PrismaClient } from '@prisma/client'
|
||||
import { UserInputError } from 'apollo-server-express'
|
||||
import { MutationRegisterArgs } from '../typeDefs/typeDefs.gen'
|
||||
import { IFindUserParams } from './types'
|
||||
|
||||
const getDBForm = async (db: PrismaClient, id: number) => {
|
||||
return await db.form.findOne({
|
||||
where: {
|
||||
id,
|
||||
id
|
||||
},
|
||||
include: {
|
||||
author: {
|
||||
@ -11,20 +14,20 @@ const getDBForm = async (db: PrismaClient, id: number) => {
|
||||
id: true,
|
||||
name: true,
|
||||
email: true
|
||||
},
|
||||
}
|
||||
},
|
||||
choisesQuestions: {
|
||||
include: {
|
||||
variants: true,
|
||||
},
|
||||
variants: true
|
||||
}
|
||||
},
|
||||
inputQuestions: true,
|
||||
submissions: {
|
||||
include: {
|
||||
answers: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
answers: true
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@ -32,38 +35,58 @@ const getDBFormByUser = async (db: PrismaClient, id: number) => {
|
||||
return await db.form.findMany({
|
||||
where: {
|
||||
author: {
|
||||
id,
|
||||
},
|
||||
id
|
||||
}
|
||||
},
|
||||
include: {
|
||||
choisesQuestions: {
|
||||
include: {
|
||||
variants: true,
|
||||
},
|
||||
variants: true
|
||||
}
|
||||
},
|
||||
inputQuestions: true,
|
||||
submissions: {
|
||||
include: {
|
||||
answers: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
answers: true
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const getDBFormAuthor = async (db: PrismaClient, id: number) => {
|
||||
return await db.form.findOne({
|
||||
where: {
|
||||
id,
|
||||
id
|
||||
},
|
||||
select: {
|
||||
author: {
|
||||
select: {
|
||||
id: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
id: true
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export { getDBForm, getDBFormByUser, getDBFormAuthor }
|
||||
const createUser = async (
|
||||
db: PrismaClient,
|
||||
{ email, name }: MutationRegisterArgs
|
||||
) => {
|
||||
return await db.user.create({
|
||||
data: { email, name }
|
||||
})
|
||||
}
|
||||
|
||||
const findUserBy = async (db: PrismaClient, params: IFindUserParams) => {
|
||||
const user = await db.user.findOne({
|
||||
where: {
|
||||
...params
|
||||
}
|
||||
})
|
||||
if (!user) throw new UserInputError('Not found')
|
||||
|
||||
return user
|
||||
}
|
||||
|
||||
export { getDBForm, getDBFormByUser, getDBFormAuthor, createUser, findUserBy }
|
||||
|
@ -1,6 +1,11 @@
|
||||
import { PromiseReturnType } from "@prisma/client"
|
||||
import { getDBForm } from "../db"
|
||||
import { PromiseReturnType } from '@prisma/client'
|
||||
import { getDBForm } from '../db'
|
||||
|
||||
type FullForm = PromiseReturnType<typeof getDBForm>
|
||||
|
||||
export { FullForm }
|
||||
interface IFindUserParams {
|
||||
email?: string
|
||||
id?: number
|
||||
}
|
||||
|
||||
export { FullForm, IFindUserParams }
|
||||
|
28
src/index.ts
28
src/index.ts
@ -1,31 +1,31 @@
|
||||
import { ApolloServer, makeExecutableSchema } from "apollo-server-express"
|
||||
import express from "express"
|
||||
import expressJwt from "express-jwt"
|
||||
import { PrismaClient } from "@prisma/client"
|
||||
import { ApolloServer, makeExecutableSchema } from 'apollo-server-express'
|
||||
import express from 'express'
|
||||
import expressJwt from 'express-jwt'
|
||||
import { PrismaClient } from '@prisma/client'
|
||||
|
||||
require("dotenv").config()
|
||||
require('dotenv').config()
|
||||
|
||||
import typeDefs from "./typeDefs"
|
||||
import resolvers from "./resolvers"
|
||||
import { ApolloContextType, JwtPayloadType } from "./types"
|
||||
import typeDefs from './typeDefs'
|
||||
import resolvers from './resolvers'
|
||||
import { ApolloContextType, JwtPayloadType } from './types'
|
||||
|
||||
const app = express()
|
||||
|
||||
app.use(
|
||||
expressJwt({
|
||||
secret: "" + process.env.JWT_SECRET,
|
||||
secret: '' + process.env.JWT_SECRET,
|
||||
credentialsRequired: false,
|
||||
algorithms: ["HS256"],
|
||||
algorithms: ['HS256']
|
||||
})
|
||||
)
|
||||
|
||||
const server = new ApolloServer({
|
||||
schema: makeExecutableSchema({
|
||||
typeDefs,
|
||||
resolvers,
|
||||
resolvers
|
||||
}),
|
||||
context: async ({
|
||||
req,
|
||||
req
|
||||
}: {
|
||||
req: Request & { user: JwtPayloadType }
|
||||
}): Promise<ApolloContextType> => {
|
||||
@ -34,11 +34,11 @@ const server = new ApolloServer({
|
||||
|
||||
return { db, user }
|
||||
},
|
||||
debug: false,
|
||||
debug: false
|
||||
})
|
||||
|
||||
server.applyMiddleware({ app })
|
||||
|
||||
app.listen(4000, () => {
|
||||
console.log("Server ready at http://localhost:4000")
|
||||
console.log('Server ready at http://localhost:4000')
|
||||
})
|
||||
|
@ -2,16 +2,16 @@ import {
|
||||
checkRightsAndResolve,
|
||||
getForm,
|
||||
getFormAuthor,
|
||||
getForms,
|
||||
} from "../controllers"
|
||||
getForms
|
||||
} from '../controllers'
|
||||
import {
|
||||
Form,
|
||||
QueryFormArgs,
|
||||
QuestionResolvers,
|
||||
Resolver,
|
||||
AnswerResolvers,
|
||||
} from "../typeDefs/typeDefs.gen"
|
||||
import { ApolloContextType } from "../types"
|
||||
AnswerResolvers
|
||||
} from '../typeDefs/typeDefs.gen'
|
||||
import { ApolloContextType } from '../types'
|
||||
|
||||
const formQuery: Resolver<Form, {}, ApolloContextType, QueryFormArgs> = async (
|
||||
_,
|
||||
@ -26,13 +26,10 @@ const formQuery: Resolver<Form, {}, ApolloContextType, QueryFormArgs> = async (
|
||||
return await checkRightsAndResolve({
|
||||
user,
|
||||
expected: {
|
||||
id: {
|
||||
n: 0,
|
||||
self: false,
|
||||
},
|
||||
admin: false,
|
||||
id: 0,
|
||||
self: false
|
||||
},
|
||||
controller: getFormById,
|
||||
controller: getFormById
|
||||
})
|
||||
} catch (err) {
|
||||
return err
|
||||
@ -53,13 +50,10 @@ const formsQuery: Resolver<Form[], {}, ApolloContextType> = async (
|
||||
>({
|
||||
user,
|
||||
expected: {
|
||||
id: {
|
||||
n: 0,
|
||||
self: true,
|
||||
},
|
||||
admin: false,
|
||||
id: 0,
|
||||
self: true
|
||||
},
|
||||
controller: getFormsByUserId,
|
||||
controller: getFormsByUserId
|
||||
})
|
||||
} catch (err) {
|
||||
return err
|
||||
@ -69,19 +63,19 @@ const formsQuery: Resolver<Form[], {}, ApolloContextType> = async (
|
||||
const QuestionResolver: QuestionResolvers = {
|
||||
__resolveType(obj: any) {
|
||||
if (obj.type) {
|
||||
return "ChoisesQuestion"
|
||||
return 'ChoisesQuestion'
|
||||
}
|
||||
return "InputQuestion"
|
||||
},
|
||||
return 'InputQuestion'
|
||||
}
|
||||
}
|
||||
|
||||
const AnswerResolver: AnswerResolvers = {
|
||||
__resolveType(obj) {
|
||||
if (obj.type == "CHOISE") return "ChoiseAnswer"
|
||||
if (obj.type == "INPUT") return "InputAnswer"
|
||||
if (obj.type == 'CHOISE') return 'ChoiseAnswer'
|
||||
if (obj.type == 'INPUT') return 'InputAnswer'
|
||||
|
||||
return null
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
export { formQuery, formsQuery, QuestionResolver, AnswerResolver }
|
||||
|
@ -1,13 +1,14 @@
|
||||
import { ApolloError, UserInputError } from 'apollo-server-express'
|
||||
import { UserInputError } from 'apollo-server-express'
|
||||
|
||||
import { tokenGenerate } from '../controllers/auth'
|
||||
import { sendToken } from '../mailer'
|
||||
import { checkRightsAndResolve, sendTokenEmail } from '../controllers/auth'
|
||||
import { createUser, findUserBy } from '../db'
|
||||
import {
|
||||
MutationLoginArgs,
|
||||
MutationRegisterArgs,
|
||||
Resolver,
|
||||
LoginResult,
|
||||
User,
|
||||
LoginResult
|
||||
QueryUserArgs
|
||||
} from '../typeDefs/typeDefs.gen'
|
||||
import { ApolloContextType } from '../types'
|
||||
|
||||
@ -18,19 +19,11 @@ const loginResolver: Resolver<
|
||||
MutationLoginArgs
|
||||
> = async (_, { email }, { db }) => {
|
||||
try {
|
||||
const user = await db.user.findOne({
|
||||
where: {
|
||||
email
|
||||
}
|
||||
})
|
||||
const user = await findUserBy(db, { email })
|
||||
|
||||
if (!user) throw new UserInputError('No such user')
|
||||
|
||||
const token = tokenGenerate(email, user.id)
|
||||
|
||||
const res = await sendToken(user.name, email, token)
|
||||
|
||||
if (res[0].statusCode != 202) return new ApolloError("Couldn't send email")
|
||||
await sendTokenEmail(email, user)
|
||||
|
||||
return { success: true }
|
||||
} catch (err) {
|
||||
@ -45,15 +38,9 @@ const registerResolver: Resolver<
|
||||
MutationRegisterArgs
|
||||
> = async (_, { email, name }, { db }) => {
|
||||
try {
|
||||
const user = await db.user.create({
|
||||
data: { email, name }
|
||||
})
|
||||
const user = await createUser(db, { email, name })
|
||||
|
||||
const token = tokenGenerate(email, user.id)
|
||||
|
||||
const res = await sendToken(user.name, email, token)
|
||||
|
||||
if (res[0].statusCode != 202) return new ApolloError("Couldn't send email")
|
||||
await sendTokenEmail(email, user)
|
||||
|
||||
return { success: true }
|
||||
} catch (err) {
|
||||
@ -61,4 +48,23 @@ const registerResolver: Resolver<
|
||||
}
|
||||
}
|
||||
|
||||
export { loginResolver, registerResolver }
|
||||
const userResolver: Resolver<
|
||||
User,
|
||||
{},
|
||||
ApolloContextType,
|
||||
QueryUserArgs
|
||||
> = async (_, { id }, { db, user }) => {
|
||||
const findUserById = (id: number) => findUserBy(db, { id })
|
||||
|
||||
try {
|
||||
return await checkRightsAndResolve({
|
||||
user,
|
||||
expected: { id: id || 0, self: true },
|
||||
controller: findUserById
|
||||
})
|
||||
} catch (err) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
export { loginResolver, registerResolver, userResolver }
|
||||
|
@ -1,24 +1,29 @@
|
||||
import { ApolloContextType } from "../types"
|
||||
import { Resolvers } from "../typeDefs/typeDefs.gen"
|
||||
import { ApolloContextType } from '../types'
|
||||
import { Resolvers } from '../typeDefs/typeDefs.gen'
|
||||
import {
|
||||
formQuery as form,
|
||||
QuestionResolver as Question,
|
||||
AnswerResolver as Answer,
|
||||
formsQuery as forms,
|
||||
} from "./Form"
|
||||
import { loginResolver as login, registerResolver as register } from "./User"
|
||||
formsQuery as forms
|
||||
} from './Form'
|
||||
import {
|
||||
loginResolver as login,
|
||||
registerResolver as register,
|
||||
userResolver as user
|
||||
} from './User'
|
||||
|
||||
const resolvers: Resolvers<ApolloContextType> = {
|
||||
Query: {
|
||||
form,
|
||||
forms,
|
||||
user
|
||||
},
|
||||
Mutation: {
|
||||
login,
|
||||
register
|
||||
},
|
||||
Question,
|
||||
Answer,
|
||||
Answer
|
||||
}
|
||||
|
||||
export default resolvers
|
||||
|
@ -1,6 +1,7 @@
|
||||
type Query {
|
||||
forms: [Form!]!
|
||||
form(id: Int!): Form
|
||||
user(id: Int): User
|
||||
}
|
||||
|
||||
type Mutation {
|
||||
@ -77,7 +78,6 @@ type User {
|
||||
email: String!
|
||||
id: Int!
|
||||
forms: [Form!]
|
||||
token: String
|
||||
}
|
||||
|
||||
type LoginResult {
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { PrismaClient } from "@prisma/client"
|
||||
import {} from "express-jwt"
|
||||
import { PrismaClient } from '@prisma/client'
|
||||
|
||||
export type ApolloContextType = {
|
||||
db: PrismaClient
|
||||
|
Loading…
x
Reference in New Issue
Block a user