1
1
import { createBullBoard } from "@bull-board/api" ;
2
2
import { BullMQAdapter } from "@bull-board/api/bullMQAdapter" ;
3
3
import { FastifyAdapter } from "@bull-board/fastify" ;
4
+ import fastifyBasicAuth from "@fastify/basic-auth" ;
4
5
import { Queue } from "bullmq" ;
6
+ import { timingSafeEqual } from "crypto" ;
5
7
import { FastifyInstance } from "fastify" ;
8
+ import { StatusCodes } from "http-status-codes" ;
9
+ import { env } from "../../utils/env" ;
6
10
import { CancelRecycledNoncesQueue } from "../../worker/queues/cancelRecycledNoncesQueue" ;
7
11
import { MineTransactionQueue } from "../../worker/queues/mineTransactionQueue" ;
8
12
import { ProcessEventsLogQueue } from "../../worker/queues/processEventLogsQueue" ;
@@ -11,29 +15,71 @@ import { PruneTransactionsQueue } from "../../worker/queues/pruneTransactionsQue
11
15
import { SendTransactionQueue } from "../../worker/queues/sendTransactionQueue" ;
12
16
import { SendWebhookQueue } from "../../worker/queues/sendWebhookQueue" ;
13
17
14
- export const withAdminRoutes = async ( server : FastifyInstance ) => {
15
- const serverAdapter = new FastifyAdapter ( ) ;
18
+ export const ADMIN_QUEUES_BASEPATH = "/admin/queues" ;
19
+ const ADMIN_ROUTES_PASSWORD = env . THIRDWEB_API_SECRET_KEY ;
20
+ // Add queues to monitor here.
21
+ const QUEUES : Queue [ ] = [
22
+ SendWebhookQueue . q ,
23
+ ProcessEventsLogQueue . q ,
24
+ ProcessTransactionReceiptsQueue . q ,
25
+ SendTransactionQueue . q ,
26
+ MineTransactionQueue . q ,
27
+ CancelRecycledNoncesQueue . q ,
28
+ PruneTransactionsQueue . q ,
29
+ ] ;
16
30
17
- const queues : Queue [ ] = [
18
- SendWebhookQueue . q ,
19
- ProcessEventsLogQueue . q ,
20
- ProcessTransactionReceiptsQueue . q ,
21
- SendTransactionQueue . q ,
22
- MineTransactionQueue . q ,
23
- CancelRecycledNoncesQueue . q ,
24
- PruneTransactionsQueue . q ,
25
- ] ;
26
-
27
- createBullBoard ( {
28
- queues : queues . map ( ( q ) => new BullMQAdapter ( q ) ) ,
29
- serverAdapter,
31
+ export const withAdminRoutes = async ( fastify : FastifyInstance ) => {
32
+ // Configure basic auth.
33
+ await fastify . register ( fastifyBasicAuth , {
34
+ validate : ( username , password , req , reply , done ) => {
35
+ if ( assertAdminBasicAuth ( username , password ) ) {
36
+ done ( ) ;
37
+ return ;
38
+ }
39
+ done ( new Error ( "Unauthorized" ) ) ;
40
+ } ,
41
+ authenticate : true ,
30
42
} ) ;
31
43
32
- const bullboardPath = "/admin/queues" ;
44
+ // Set up routes after Fastify is set up.
45
+ fastify . after ( async ( ) => {
46
+ // Register bullboard UI.
47
+ const serverAdapter = new FastifyAdapter ( ) ;
48
+ serverAdapter . setBasePath ( ADMIN_QUEUES_BASEPATH ) ;
49
+
50
+ createBullBoard ( {
51
+ queues : QUEUES . map ( ( q ) => new BullMQAdapter ( q ) ) ,
52
+ serverAdapter,
53
+ } ) ;
54
+ await fastify . register ( serverAdapter . registerPlugin ( ) , {
55
+ basePath : ADMIN_QUEUES_BASEPATH ,
56
+ prefix : ADMIN_QUEUES_BASEPATH ,
57
+ } ) ;
33
58
34
- serverAdapter . setBasePath ( bullboardPath ) ;
35
- await server . register ( serverAdapter . registerPlugin ( ) , {
36
- basePath : bullboardPath ,
37
- prefix : bullboardPath ,
59
+ // Apply basic auth only to admin routes.
60
+ fastify . addHook ( "onRequest" , ( req , reply , done ) => {
61
+ if ( req . url . startsWith ( ADMIN_QUEUES_BASEPATH ) ) {
62
+ fastify . basicAuth ( req , reply , ( error ) => {
63
+ if ( error ) {
64
+ reply
65
+ . status ( StatusCodes . UNAUTHORIZED )
66
+ . send ( { error : "Unauthorized" } ) ;
67
+ return done ( error ) ;
68
+ }
69
+ } ) ;
70
+ }
71
+ done ( ) ;
72
+ } ) ;
38
73
} ) ;
39
74
} ;
75
+
76
+ const assertAdminBasicAuth = ( username : string , password : string ) => {
77
+ if ( username === "admin" ) {
78
+ try {
79
+ const buf1 = Buffer . from ( password . padEnd ( 100 ) ) ;
80
+ const buf2 = Buffer . from ( ADMIN_ROUTES_PASSWORD . padEnd ( 100 ) ) ;
81
+ return timingSafeEqual ( buf1 , buf2 ) ;
82
+ } catch ( e ) { }
83
+ }
84
+ return false ;
85
+ } ;
0 commit comments