Skip to content

Commit

Permalink
Configuration + Webhooks : PG Notify/Trigger (#361)
Browse files Browse the repository at this point in the history
* updated implementation to use configuration cache

* changed log level for cache to debug

* removed extra export fr cache

* updated config end-points to pull latest & return latest in response

* removed extra logging for webhooks

* cleaned webhooks cache debug logs
  • Loading branch information
farhanW3 authored Jan 8, 2024
1 parent ee05cf9 commit 77d3cf8
Show file tree
Hide file tree
Showing 43 changed files with 510 additions and 116 deletions.
4 changes: 2 additions & 2 deletions src/db/transactions/getQueuedTxs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { Transactions } from "@prisma/client";
import { Static } from "@sinclair/typebox";
import { PrismaTransaction } from "../../schema/prisma";
import { transactionResponseSchema } from "../../server/schemas/transaction";
import { getConfig } from "../../utils/cache/getConfig";
import { getPrismaWithPostgresTx } from "../client";
import { getConfiguration } from "../configuration/getConfiguration";
import { cleanTxs } from "./cleanTxs";

interface GetQueuedTxsParams {
Expand All @@ -14,7 +14,7 @@ export const getQueuedTxs = async ({ pgtx }: GetQueuedTxsParams = {}): Promise<
Static<typeof transactionResponseSchema>[]
> => {
const prisma = getPrismaWithPostgresTx(pgtx);
const config = await getConfiguration();
const config = await getConfig();

// TODO: Don't use env var for transactions to batch
const txs = await prisma.$queryRaw<Transactions[]>`
Expand Down
4 changes: 2 additions & 2 deletions src/db/transactions/getSentTxs.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Transactions } from "@prisma/client";
import { PrismaTransaction } from "../../schema/prisma";
import { getConfig } from "../../utils/cache/getConfig";
import { getPrismaWithPostgresTx } from "../client";
import { getConfiguration } from "../configuration/getConfiguration";

interface GetSentTxsParams {
pgtx?: PrismaTransaction;
Expand All @@ -11,7 +11,7 @@ export const getSentTxs = async ({ pgtx }: GetSentTxsParams = {}): Promise<
Transactions[]
> => {
const prisma = getPrismaWithPostgresTx(pgtx);
const config = await getConfiguration();
const config = await getConfig();

return prisma.$queryRaw<Transactions[]>`
SELECT * FROM "transactions"
Expand Down
4 changes: 2 additions & 2 deletions src/db/transactions/getSentUserOps.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Transactions } from "@prisma/client";
import { PrismaTransaction } from "../../schema/prisma";
import { getConfig } from "../../utils/cache/getConfig";
import { getPrismaWithPostgresTx } from "../client";
import { getConfiguration } from "../configuration/getConfiguration";

interface GetSentUserOpsParams {
pgtx?: PrismaTransaction;
Expand All @@ -11,7 +11,7 @@ export const getSentUserOps = async ({
pgtx,
}: GetSentUserOpsParams = {}): Promise<Transactions[]> => {
const prisma = getPrismaWithPostgresTx(pgtx);
const config = await getConfiguration();
const config = await getConfig();

return prisma.$queryRaw<Transactions[]>`
SELECT * FROM "transactions"
Expand Down
4 changes: 2 additions & 2 deletions src/db/transactions/getTxToRetry.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Transactions } from "@prisma/client";
import type { PrismaTransaction } from "../../schema/prisma";
import { getConfig } from "../../utils/cache/getConfig";
import { getPrismaWithPostgresTx } from "../client";
import { getConfiguration } from "../configuration/getConfiguration";

interface GetTxToRetryParams {
pgtx?: PrismaTransaction;
Expand All @@ -11,7 +11,7 @@ export const getTxToRetry = async ({ pgtx }: GetTxToRetryParams = {}): Promise<
Transactions | undefined
> => {
const prisma = getPrismaWithPostgresTx(pgtx);
const config = await getConfiguration();
const config = await getConfig();

// TODO: Remove transactionHash
// TODO: For now, we're not retrying user ops
Expand Down
4 changes: 0 additions & 4 deletions src/db/webhooks/createWebhook.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { createHash, randomBytes } from "crypto";
import { WebhooksEventTypes } from "../../schema/webhooks";
import { webhookCache } from "../../utils/cache/getWebhook";
import { prisma } from "../client";

interface CreateWebhooksParams {
Expand All @@ -19,9 +18,6 @@ export const insertWebhook = async ({
// hash the bytes to create the secret (this will not be stored by itself)
const secret = createHash("sha512").update(bytes).digest("base64url");

// Clear Cache
webhookCache.clear();

return prisma.webhooks.create({
data: {
url,
Expand Down
3 changes: 0 additions & 3 deletions src/db/webhooks/revokeWebhook.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
import { StatusCodes } from "http-status-codes";
import { createCustomError } from "../../server/middleware/error";
import { webhookCache } from "../../utils/cache/getWebhook";
import { prisma } from "../client";

interface RevokeWebhooksParams {
id: number;
}

export const markWebhookAsRevoked = async ({ id }: RevokeWebhooksParams) => {
// Clear Cache
webhookCache.clear();
const currentTimestamp = new Date();

const exists = await prisma.webhooks.findUnique({
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
-- Configuration Triggers
CREATE OR REPLACE FUNCTION notify_configuration_insert()
RETURNS TRIGGER
LANGUAGE plpgsql
AS $function$
BEGIN
PERFORM pg_notify('new_configuration_data', row_to_json(NEW)::text);
RETURN NEW;
END;
$function$;

CREATE OR REPLACE FUNCTION notify_configuration_update()
RETURNS TRIGGER
LANGUAGE plpgsql
AS $function$
BEGIN
PERFORM pg_notify('updated_configuration_data', json_build_object(
'id', NEW.id
)::text);
RETURN NEW;
END;
$function$;

CREATE OR REPLACE TRIGGER configuration_insert_trigger
AFTER INSERT ON configuration
FOR EACH ROW
EXECUTE FUNCTION notify_configuration_insert();

CREATE OR REPLACE TRIGGER configuration_update_trigger
AFTER UPDATE ON configuration
FOR EACH ROW
EXECUTE FUNCTION notify_configuration_update();

-- Webhooks Triggers
CREATE OR REPLACE FUNCTION notify_webhooks_insert()
RETURNS TRIGGER
LANGUAGE plpgsql
AS $function$
BEGIN
PERFORM pg_notify('new_webhook_data', row_to_json(NEW)::text);
RETURN NEW;
END;
$function$;

CREATE OR REPLACE FUNCTION notify_webhooks_update()
RETURNS TRIGGER
LANGUAGE plpgsql
AS $function$
BEGIN
PERFORM pg_notify('updated_webhook_data', json_build_object(
'id', NEW.id
)::text);
RETURN NEW;
END;
$function$;

CREATE OR REPLACE TRIGGER webhooks_insert_trigger
AFTER INSERT ON webhooks
FOR EACH ROW
EXECUTE FUNCTION notify_webhooks_insert();

CREATE OR REPLACE TRIGGER webhooks_update_trigger
AFTER UPDATE ON webhooks
FOR EACH ROW
EXECUTE FUNCTION notify_webhooks_update();
12 changes: 6 additions & 6 deletions src/server/middleware/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ import { GenericAuthWallet, LocalWallet } from "@thirdweb-dev/wallets";
import { AsyncWallet } from "@thirdweb-dev/wallets/evm/wallets/async";
import { utils } from "ethers";
import { FastifyInstance } from "fastify";
import { getConfiguration } from "../../db/configuration/getConfiguration";
import { updateConfiguration } from "../../db/configuration/updateConfiguration";
import { getPermissions } from "../../db/permissions/getPermissions";
import { createToken } from "../../db/tokens/createToken";
import { getToken } from "../../db/tokens/getToken";
import { revokeToken } from "../../db/tokens/revokeToken";
import { WebhooksEventTypes } from "../../schema/webhooks";
import { getWebhookConfig } from "../../utils/cache/getWebhook";
import { getConfig } from "../../utils/cache/getConfig";
import { getWebhook } from "../../utils/cache/getWebhook";
import { env } from "../../utils/env";
import { logger } from "../../utils/logger";
import { Permission } from "../schemas/auth";
Expand Down Expand Up @@ -73,7 +73,7 @@ const authWithApiServer = async (jwt: string, domain: string) => {
};

export const withAuth = async (server: FastifyInstance) => {
const config = await getConfiguration();
const config = await getConfig();

// Configure the ThirdwebAuth fastify plugin
const { authRouter, authMiddleware, getUser } = ThirdwebAuth<
Expand All @@ -86,7 +86,7 @@ export const withAuth = async (server: FastifyInstance) => {
wallet: new AsyncWallet({
// TODO: Use caching for the signer
getSigner: async () => {
const config = await getConfiguration();
const config = await getConfig();
const wallet = new LocalWallet();

try {
Expand Down Expand Up @@ -209,7 +209,7 @@ export const withAuth = async (server: FastifyInstance) => {
const thirdwebApiSecretKey = req.headers.authorization?.split(" ")[1];
if (thirdwebApiSecretKey === env.THIRDWEB_API_SECRET_KEY) {
// If the secret key is being used, treat the user as the auth wallet
const config = await getConfiguration();
const config = await getConfig();
const wallet = new LocalWallet();

try {
Expand Down Expand Up @@ -300,7 +300,7 @@ export const withAuth = async (server: FastifyInstance) => {
// no-op
}

const authWebhooks = await getWebhookConfig(WebhooksEventTypes.AUTH);
const authWebhooks = await getWebhook(WebhooksEventTypes.AUTH);
if (authWebhooks) {
const authResponses = await Promise.all(
authWebhooks.map((webhook) =>
Expand Down
4 changes: 2 additions & 2 deletions src/server/routes/auth/access-tokens/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import { buildJWT } from "@thirdweb-dev/auth";
import { LocalWallet } from "@thirdweb-dev/wallets";
import { FastifyInstance } from "fastify";
import { StatusCodes } from "http-status-codes";
import { getConfiguration } from "../../../../db/configuration/getConfiguration";
import { updateConfiguration } from "../../../../db/configuration/updateConfiguration";
import { createToken } from "../../../../db/tokens/createToken";
import { getConfig } from "../../../../utils/cache/getConfig";
import { env } from "../../../../utils/env";
import { AccessTokenSchema } from "./getAll";

Expand Down Expand Up @@ -42,7 +42,7 @@ export async function createAccessToken(fastify: FastifyInstance) {
handler: async (req, res) => {
const { label } = req.body;

const config = await getConfiguration();
const config = await getConfig();
const wallet = new LocalWallet();

// TODO: Remove this with next breaking change
Expand Down
4 changes: 2 additions & 2 deletions src/server/routes/backend-wallet/create.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { Static, Type } from "@sinclair/typebox";
import { FastifyInstance } from "fastify";
import { StatusCodes } from "http-status-codes";
import { getConfiguration } from "../../../db/configuration/getConfiguration";
import { WalletType } from "../../../schema/wallet";
import { getConfig } from "../../../utils/cache/getConfig";
import { standardResponseSchema } from "../../schemas/sharedApiSchemas";
import { createAwsKmsWallet } from "../../utils/wallets/createAwsKmsWallet";
import { createGcpKmsWallet } from "../../utils/wallets/createGcpKmsWallet";
Expand Down Expand Up @@ -48,7 +48,7 @@ export const createBackendWallet = async (fastify: FastifyInstance) => {
const { label } = req.body;

let walletAddress: string;
const config = await getConfiguration();
const config = await getConfig();
switch (config.walletConfiguration.type) {
case WalletType.local:
walletAddress = await createLocalWallet({ label });
Expand Down
4 changes: 2 additions & 2 deletions src/server/routes/backend-wallet/import.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { Static, Type } from "@sinclair/typebox";
import { FastifyInstance } from "fastify";
import { StatusCodes } from "http-status-codes";
import { getConfiguration } from "../../../db/configuration/getConfiguration";
import { WalletType } from "../../../schema/wallet";
import { getConfig } from "../../../utils/cache/getConfig";
import { standardResponseSchema } from "../../schemas/sharedApiSchemas";
import { importAwsKmsWallet } from "../../utils/wallets/importAwsKmsWallet";
import { importGcpKmsWallet } from "../../utils/wallets/importGcpKmsWallet";
Expand Down Expand Up @@ -111,7 +111,7 @@ export const importBackendWallet = async (fastify: FastifyInstance) => {
},
handler: async (request, reply) => {
let walletAddress: string;
const config = await getConfiguration();
const config = await getConfig();
switch (config.walletConfiguration.type) {
case WalletType.local:
// TODO: This is why where zod would be great
Expand Down
4 changes: 2 additions & 2 deletions src/server/routes/configuration/auth/get.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Static, Type } from "@sinclair/typebox";
import { FastifyInstance } from "fastify";
import { StatusCodes } from "http-status-codes";
import { getConfiguration } from "../../../../db/configuration/getConfiguration";
import { getConfig } from "../../../../utils/cache/getConfig";

export const ReplySchema = Type.Object({
result: Type.Object({
Expand All @@ -25,7 +25,7 @@ export async function getAuthConfiguration(fastify: FastifyInstance) {
},
},
handler: async (req, res) => {
const config = await getConfiguration();
const config = await getConfig();
res.status(200).send({
result: {
domain: config.authDomain,
Expand Down
5 changes: 4 additions & 1 deletion src/server/routes/configuration/auth/update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Static, Type } from "@sinclair/typebox";
import { FastifyInstance } from "fastify";
import { StatusCodes } from "http-status-codes";
import { updateConfiguration } from "../../../../db/configuration/updateConfiguration";
import { getConfig } from "../../../../utils/cache/getConfig";
import { ReplySchema } from "./get";

export const BodySchema = Type.Object({
Expand All @@ -26,10 +27,12 @@ export async function updateAuthConfiguration(fastify: FastifyInstance) {
},
},
handler: async (req, res) => {
const config = await updateConfiguration({
await updateConfiguration({
authDomain: req.body.domain,
});

const config = await getConfig(false);

res.status(200).send({
result: {
domain: config.authDomain,
Expand Down
4 changes: 2 additions & 2 deletions src/server/routes/configuration/backend-wallet-balance/get.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Static, Type } from "@sinclair/typebox";
import { FastifyInstance } from "fastify";
import { StatusCodes } from "http-status-codes";
import { getConfiguration } from "../../../../db/configuration/getConfiguration";
import { getConfig } from "../../../../utils/cache/getConfig";
import { standardResponseSchema } from "../../../schemas/sharedApiSchemas";

export const ReplySchema = Type.Object({
Expand Down Expand Up @@ -31,7 +31,7 @@ export async function getBackendWalletBalanceConfiguration(
},
},
handler: async (req, res) => {
const config = await getConfiguration();
const config = await getConfig();
res.status(200).send({
result: {
minWalletBalance: config.minWalletBalance,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Static, Type } from "@sinclair/typebox";
import { FastifyInstance } from "fastify";
import { StatusCodes } from "http-status-codes";
import { updateConfiguration } from "../../../../db/configuration/updateConfiguration";
import { getConfig } from "../../../../utils/cache/getConfig";
import { standardResponseSchema } from "../../../schemas/sharedApiSchemas";
import { ReplySchema } from "./get";

Expand Down Expand Up @@ -33,7 +34,9 @@ export async function updateBackendWalletBalanceConfiguration(
},
},
handler: async (req, res) => {
const config = await updateConfiguration({ ...req.body });
await updateConfiguration({ ...req.body });
const config = await getConfig(false);

res.status(200).send({
result: {
minWalletBalance: config.minWalletBalance,
Expand Down
4 changes: 2 additions & 2 deletions src/server/routes/configuration/chains/get.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Static, Type } from "@sinclair/typebox";
import { FastifyInstance } from "fastify";
import { StatusCodes } from "http-status-codes";
import { getConfiguration } from "../../../../db/configuration/getConfiguration";
import { getConfig } from "../../../../utils/cache/getConfig";

export const ReplySchema = Type.Object({
result: Type.Union([Type.String(), Type.Null()]),
Expand All @@ -23,7 +23,7 @@ export async function getChainsConfiguration(fastify: FastifyInstance) {
},
},
handler: async (req, res) => {
const config = await getConfiguration();
const config = await getConfig();
res.status(200).send({
result: config.chainOverrides,
});
Expand Down
4 changes: 2 additions & 2 deletions src/server/routes/configuration/chains/update.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { Static, Type } from "@sinclair/typebox";
import { FastifyInstance } from "fastify";
import { StatusCodes } from "http-status-codes";
import { getConfiguration } from "../../../../db/configuration/getConfiguration";
import { updateConfiguration } from "../../../../db/configuration/updateConfiguration";
import { getConfig } from "../../../../utils/cache/getConfig";
import { ReplySchema } from "./get";

const BodySchema = Type.Object({
Expand Down Expand Up @@ -63,7 +63,7 @@ export async function updateChainsConfiguration(fastify: FastifyInstance) {
chainOverrides: JSON.stringify(req.body.chainOverrides),
});

const config = await getConfiguration();
const config = await getConfig(false);
res.status(200).send({
result: config.chainOverrides,
});
Expand Down
Loading

0 comments on commit 77d3cf8

Please sign in to comment.