Skip to content

Commit 3882c1a

Browse files
committed
feat: add AdminResolvers with loadFixtures mutation
- Add loadFixtures mutation in AdminResolvers - Inside loadFixtures, verify the provided admin token - Use public key from Auth0 Machine to Machine application for token verification - On successful verification, proceed with loading the fixtures
1 parent ac67b61 commit 3882c1a

File tree

6 files changed

+156
-2
lines changed

6 files changed

+156
-2
lines changed

package-lock.json

Lines changed: 71 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
"drizzle-orm": "^0.29.3",
2222
"graphql": "^16.8.1",
2323
"jsonwebtoken": "^9.0.2",
24+
"jwks-rsa": "^3.1.0",
2425
"pg": "^8.11.3",
2526
"pg-hstore": "^2.3.4",
2627
"reflect-metadata": "^0.1.13",

src/graphql/resolvers/Admin.ts

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import { client, db } from "../../db";
2+
import { book, favorite } from "../../schema";
3+
import booksData from "../../fixtures/raw/books.json";
4+
import { faker } from "@faker-js/faker";
5+
import jwt from "jsonwebtoken";
6+
import jwksClient from "jwks-rsa";
7+
8+
const initializeBooks = async (bookData) => {
9+
if (isNaN(Date.parse(bookData.publicationDate))) {
10+
console.log(
11+
`Skipping book with invalid publication date: ${bookData.title}`
12+
);
13+
return;
14+
}
15+
16+
const bookValues = {
17+
title: bookData.title,
18+
author: bookData.author,
19+
publicationDate: new Date(bookData.publicationDate).toISOString(),
20+
image: bookData.image || faker.image.url({ width: 150, height: 150 }),
21+
rating: bookData.rating,
22+
ratingsCount: bookData.ratingsCount,
23+
};
24+
25+
return db.insert(book).values(bookValues).returning();
26+
};
27+
28+
export const loadFixtures = async () => {
29+
console.log("Truncating the favorite and book tables...");
30+
await db.delete(favorite);
31+
await db.delete(book);
32+
33+
console.log("Inserting new books into the database...");
34+
const books = await Promise.all(
35+
booksData.map((bookData) => initializeBooks(bookData))
36+
);
37+
console.log(`Inserted ${books.length} books.`);
38+
await client.end();
39+
};
40+
41+
function getKey(header, callback) {
42+
const client = jwksClient({
43+
jwksUri: `https://dev-udel1dobwtbe8ips.us.auth0.com/.well-known/jwks.json`,
44+
});
45+
client.getSigningKey(header.kid, function (err, key) {
46+
const signingKey = key.getPublicKey();
47+
callback(null, signingKey);
48+
});
49+
}
50+
51+
export const AdminResolvers = {
52+
Mutation: {
53+
loadFixtures: async (_: any, args: { adminToken: string }) => {
54+
try {
55+
await new Promise((resolve, reject) => {
56+
jwt.verify(
57+
args.adminToken,
58+
getKey,
59+
{ algorithms: ["RS256"] },
60+
function (err, decoded) {
61+
if (err) {
62+
reject(new Error("Invalid admin token"));
63+
} else {
64+
resolve(decoded);
65+
}
66+
}
67+
);
68+
});
69+
70+
await loadFixtures();
71+
return true;
72+
} catch (error) {
73+
console.error("Error:", error);
74+
throw error;
75+
}
76+
},
77+
},
78+
};

src/graphql/resolvers/resolvers.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
import { BookResolvers } from "./Book";
22
import { FavoriteResolvers } from "./Favorite";
3+
import { AdminResolvers } from "./Admin";
34

45
export const resolvers = {
56
Query: {
67
...BookResolvers.Query,
78
},
89
Mutation: {
910
...FavoriteResolvers.Mutation,
11+
...AdminResolvers.Mutation,
1012
},
1113
};

src/graphql/types/typeDefs.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,5 @@ export const typeDefs = `#graphql
1616
type Mutation {
1717
addFavorite(bookId: ID!): Favorite
1818
removeFavorite(bookId: ID!): Boolean
19+
loadFixtures(adminToken: String!): Boolean
1920
}`;

src/server.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,9 @@ const decodeToken = (token: string): string | undefined => {
3636
const jwtToken = token.slice(7, token.length).trimStart();
3737
try {
3838
const decoded = jwt.decode(jwtToken);
39-
return decoded?.sub;
39+
if (typeof decoded !== "string" && decoded?.sub) {
40+
return decoded.sub;
41+
}
4042
} catch (err) {
4143
logger.error("Invalid token");
4244
}

0 commit comments

Comments
 (0)