updated context
This commit is contained in:
parent
04b606b7fa
commit
40c35bda13
7 changed files with 67 additions and 25 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -13,6 +13,7 @@ dist-ssr
|
||||||
*.local
|
*.local
|
||||||
.env
|
.env
|
||||||
__generated__/
|
__generated__/
|
||||||
|
vite.config.ts.timestamp-*.mjs
|
||||||
|
|
||||||
|
|
||||||
# Editor directories and files
|
# Editor directories and files
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,14 @@
|
||||||
|
import { IdentityContext } from '@app/server/identity';
|
||||||
import { prisma } from '@app/server/prisma/client';
|
import { prisma } from '@app/server/prisma/client';
|
||||||
import { MutationLoginArgs, Session } from '@generated/types';
|
import { MutationLoginArgs, Session } from '@generated/types';
|
||||||
import bcrypt from 'bcrypt';
|
import bcrypt from 'bcrypt';
|
||||||
import jwt from 'jsonwebtoken';
|
import jwt from 'jsonwebtoken';
|
||||||
|
|
||||||
export async function LoginResolver(_: any, { input }: MutationLoginArgs): Promise<Session> {
|
export async function LoginResolver(
|
||||||
|
_: any,
|
||||||
|
{ input }: MutationLoginArgs,
|
||||||
|
{ identity }: IdentityContext
|
||||||
|
): Promise<Session> {
|
||||||
const error = 'Invalid username or password';
|
const error = 'Invalid username or password';
|
||||||
|
|
||||||
const user = await prisma.user.findUnique({
|
const user = await prisma.user.findUnique({
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,13 @@
|
||||||
|
import { IdentityContext } from '@app/server/identity';
|
||||||
import { prisma, uuid } from '@app/server/prisma/client';
|
import { prisma, uuid } from '@app/server/prisma/client';
|
||||||
import { RegisterInput } from '@generated/types';
|
import { RegisterInput } from '@generated/types';
|
||||||
import bcrypt from 'bcrypt';
|
import bcrypt from 'bcrypt';
|
||||||
|
|
||||||
export async function SignUpResolver(_: any, input: RegisterInput): Promise<void> {
|
export async function SignUpResolver(
|
||||||
|
_: any,
|
||||||
|
input: RegisterInput,
|
||||||
|
{ identity }: IdentityContext
|
||||||
|
): Promise<void> {
|
||||||
const existingUsername = await prisma.user.findUnique({
|
const existingUsername = await prisma.user.findUnique({
|
||||||
where: { username: input.username },
|
where: { username: input.username },
|
||||||
select: { id: true }
|
select: { id: true }
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,12 @@
|
||||||
|
import { IdentityContext } from '@app/server/identity';
|
||||||
import { Book, QueryBookOneArgs } from '@generated/types';
|
import { Book, QueryBookOneArgs } from '@generated/types';
|
||||||
import { books } from './booksManyResolver';
|
import { books } from './booksManyResolver';
|
||||||
|
|
||||||
export async function BookOneResolver(_: any, { id }: QueryBookOneArgs): Promise<Book> {
|
export async function BookOneResolver(
|
||||||
|
_: any,
|
||||||
|
{ id }: QueryBookOneArgs,
|
||||||
|
{ identity }: IdentityContext
|
||||||
|
): Promise<Book> {
|
||||||
const book = books.filter(item => item.id === id)[0];
|
const book = books.filter(item => item.id === id)[0];
|
||||||
|
|
||||||
return book;
|
return book;
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { IdentityContext } from '@app/server/identity';
|
||||||
import { Book } from '@generated/types';
|
import { Book } from '@generated/types';
|
||||||
|
|
||||||
export const books = [
|
export const books = [
|
||||||
|
|
@ -13,6 +14,10 @@ export const books = [
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
export async function BooksManyResolver(_: any): Promise<Book[]> {
|
export async function BooksManyResolver(
|
||||||
|
_: any,
|
||||||
|
__: any,
|
||||||
|
{ identity }: IdentityContext
|
||||||
|
): Promise<Book[]> {
|
||||||
return books;
|
return books;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
39
app/server/identity.ts
Normal file
39
app/server/identity.ts
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
import 'dotenv/config';
|
||||||
|
import { Request, Response } from 'express';
|
||||||
|
import jwt from 'jsonwebtoken';
|
||||||
|
|
||||||
|
import { prisma } from './prisma/client';
|
||||||
|
|
||||||
|
export interface IdentityContext {
|
||||||
|
identity?: {
|
||||||
|
id: string;
|
||||||
|
username: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getIdentityContext({
|
||||||
|
req,
|
||||||
|
res
|
||||||
|
}: {
|
||||||
|
req: Request;
|
||||||
|
res: Response;
|
||||||
|
}): Promise<IdentityContext> {
|
||||||
|
const authHeader = req.headers.authorization;
|
||||||
|
if (authHeader == null) return {};
|
||||||
|
const token = authHeader.split(' ')[1];
|
||||||
|
|
||||||
|
const accessTokenSecret = process.env.ACCESS_TOKEN_SECRET;
|
||||||
|
if (accessTokenSecret == null) throw new Error('No `accessToken`.');
|
||||||
|
|
||||||
|
const decoded = jwt.verify(token, accessTokenSecret) as { userId: string };
|
||||||
|
const identity = await prisma.user.findUnique({
|
||||||
|
where: { id: decoded.userId },
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
email: true,
|
||||||
|
username: true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (identity == null) throw new Error("Couldn't find the user.");
|
||||||
|
return { identity };
|
||||||
|
}
|
||||||
|
|
@ -3,15 +3,14 @@ import { expressMiddleware } from '@apollo/server/express4';
|
||||||
import { ApolloServerPluginDrainHttpServer } from '@apollo/server/plugin/drainHttpServer';
|
import { ApolloServerPluginDrainHttpServer } from '@apollo/server/plugin/drainHttpServer';
|
||||||
import cors from 'cors';
|
import cors from 'cors';
|
||||||
import 'dotenv/config';
|
import 'dotenv/config';
|
||||||
import express, { Request, Response } from 'express';
|
import express from 'express';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import http from 'http';
|
import http from 'http';
|
||||||
import jwt from 'jsonwebtoken';
|
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import ViteExpress from 'vite-express';
|
import ViteExpress from 'vite-express';
|
||||||
|
import { getIdentityContext, IdentityContext } from './identity';
|
||||||
|
|
||||||
import { Mutation, Query } from './graphql/graphql';
|
import { Mutation, Query } from './graphql/graphql';
|
||||||
import { prisma } from './prisma/client';
|
|
||||||
|
|
||||||
const __dirname = import.meta.dirname;
|
const __dirname = import.meta.dirname;
|
||||||
const HOST = process.env.VITE_HOST || 'localhost';
|
const HOST = process.env.VITE_HOST || 'localhost';
|
||||||
|
|
@ -29,10 +28,6 @@ const resolvers = {
|
||||||
// Subscription,
|
// Subscription,
|
||||||
};
|
};
|
||||||
|
|
||||||
interface IdentityContext {
|
|
||||||
authScope?: String;
|
|
||||||
}
|
|
||||||
|
|
||||||
const apollo = new ApolloServer<IdentityContext>({
|
const apollo = new ApolloServer<IdentityContext>({
|
||||||
typeDefs,
|
typeDefs,
|
||||||
resolvers,
|
resolvers,
|
||||||
|
|
@ -46,7 +41,7 @@ app.use(
|
||||||
cors<cors.CorsRequest>(),
|
cors<cors.CorsRequest>(),
|
||||||
express.json(),
|
express.json(),
|
||||||
expressMiddleware(apollo, {
|
expressMiddleware(apollo, {
|
||||||
context: getUser
|
context: getIdentityContext
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -55,16 +50,3 @@ await new Promise<void>(resolve => server.listen({ hostname: HOST, port: PORT },
|
||||||
process.stdout.write(MOTD);
|
process.stdout.write(MOTD);
|
||||||
|
|
||||||
ViteExpress.bind(app, server);
|
ViteExpress.bind(app, server);
|
||||||
|
|
||||||
async function getUser({ req, res }: { req: Request; res: Response }) {
|
|
||||||
const authHeader = req.headers.authorization;
|
|
||||||
if (!authHeader) return { identity: null };
|
|
||||||
const token = authHeader.split(' ')[1];
|
|
||||||
|
|
||||||
const accessTokenSecret = process.env.ACCESS_TOKEN_SECRET;
|
|
||||||
if (accessTokenSecret == null) throw Error('No `accessToken`');
|
|
||||||
|
|
||||||
const decoded = jwt.verify(token, accessTokenSecret) as { userId: string };
|
|
||||||
const identity = await prisma.user.findUnique({ where: { id: decoded.userId } });
|
|
||||||
return { identity };
|
|
||||||
}
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue