1- import express from ' express' ;
2- import listEndpoints from ' express-list-endpoints' ;
3- import { fileURLToPath } from ' url' ;
4- import path , { dirname } from ' path' ;
5- import cors from ' cors' ;
6- import * as bcrypt from ' bcrypt' ;
7- import swaggerUi from ' swagger-ui-express' ;
8- import rateLimit from ' express-rate-limit' ;
9- import MemoryCache from ' memory-cache' ;
10- import favicon from ' serve-favicon' ;
11- import { createRequire } from ' module' ;
1+ import express from " express" ;
2+ import listEndpoints from " express-list-endpoints" ;
3+ import { fileURLToPath } from " url" ;
4+ import path , { dirname } from " path" ;
5+ import cors from " cors" ;
6+ import * as bcrypt from " bcrypt" ;
7+ import swaggerUi from " swagger-ui-express" ;
8+ import rateLimit from " express-rate-limit" ;
9+ import MemoryCache from " memory-cache" ;
10+ import favicon from " serve-favicon" ;
11+ import { createRequire } from " module" ;
1212const require = createRequire ( import . meta. url ) ;
13- const data = require ( ' ../utils/swagger-docs.json' ) ;
14- import dotenv from ' dotenv' ;
13+ const data = require ( " ../utils/swagger-docs.json" ) ;
14+ import dotenv from " dotenv" ;
1515dotenv . config ( ) ;
1616
17- import Constants from '../constants/dbConstants.js' ;
18- import HealthCheckManager from './HealthCheckManager.js' ;
19- import router from '../routes/router.js' ;
20- import { renderHome , renderDocs } from '../controllers/indexController.js' ;
21- import { listCollections } from '../config/db.js' ;
22- import LOGGER from '../utils/logger.js' ;
23- import { Actions } from '../config/dbActions.js' ;
24- import { performCoreAdminAction } from '../config/db.js' ;
25-
17+ import Constants from "../constants/dbConstants.js" ;
18+ import HealthCheckManager from "./HealthCheckManager.js" ;
19+ import router from "../routes/router.js" ;
20+ import { renderHome , renderDocs } from "../controllers/indexController.js" ;
21+ import { listCollections } from "../config/db.js" ;
22+ import LOGGER from "../utils/logger.js" ;
23+ import { Actions } from "../config/dbActions.js" ;
24+ import { performCoreAdminAction } from "../config/db.js" ;
2625
2726const cache = new MemoryCache . Cache ( ) ;
2827const __dirname = dirname ( fileURLToPath ( import . meta. url ) ) ;
2928const healthCheckManager = new HealthCheckManager ( ) ;
30- const { CORE_DB , JSR_DB , JSRF_DB } = Constants ;
29+ const { CORE_DB , JSR_DB , JSRF_DB , BRC_DB } = Constants ;
3130
3231class MiddlewareManager {
33-
3432 setMiddleware ( app ) {
35- app . set ( ' views' , path . join ( __dirname , '..' , ' views' ) ) ;
36- app . set ( ' view engine' , ' ejs' ) ;
37-
33+ app . set ( " views" , path . join ( __dirname , ".." , " views" ) ) ;
34+ app . set ( " view engine" , " ejs" ) ;
35+
3836 app . use ( cors ( ) ) ;
39- app . use ( express . static ( path . join ( __dirname , '..' , ' public' ) ) ) ;
40- app . use ( express . urlencoded ( { extended : true } ) ) ;
37+ app . use ( express . static ( path . join ( __dirname , ".." , " public" ) ) ) ;
38+ app . use ( express . urlencoded ( { extended : true } ) ) ;
4139 app . use ( express . json ( ) ) ;
42- app . use ( favicon ( path . join ( __dirname , '..' , 'public' , 'img' , 'favicon.ico' ) ) ) ;
43-
44- app . get ( '/' , ( req , res ) => renderHome ( req , res ) ) ;
45- app . get ( '/docs' , ( req , res ) => renderDocs ( req , res ) ) ;
46- app . get ( '/health' , ( req , res ) => res . send ( healthCheckManager . getAppHealth ( ) ) ) ;
47- app . get ( '/endpoints' , async ( req , res ) => res . send ( await filterPipeRoutes ( req , listEndpoints ( app ) ) ) ) ;
48- app . post ( '/cache/clear' , async ( req , res ) => await clearCache ( req , res ) ) ;
49- app . use ( '/v1/api' , [ limiter , cacheMiddleware ] , router ) ;
50- app . use ( '/api-docs' , swaggerUi . serve , swaggerUi . setup ( data ) )
40+ app . use (
41+ favicon ( path . join ( __dirname , ".." , "public" , "img" , "favicon.ico" ) )
42+ ) ;
43+
44+ app . get ( "/" , ( req , res ) => renderHome ( req , res ) ) ;
45+ app . get ( "/docs" , ( req , res ) => renderDocs ( req , res ) ) ;
46+ app . get ( "/health" , ( req , res ) =>
47+ res . send ( healthCheckManager . getAppHealth ( ) )
48+ ) ;
49+ app . get ( "/endpoints" , async ( req , res ) =>
50+ res . send ( await filterPipeRoutes ( req , listEndpoints ( app ) ) )
51+ ) ;
52+ app . post ( "/cache/clear" , async ( req , res ) => await clearCache ( req , res ) ) ;
53+ app . use ( "/v1/api" , [ limiter , cacheMiddleware ] , router ) ;
54+ app . use ( "/api-docs" , swaggerUi . serve , swaggerUi . setup ( data ) ) ;
5155 }
52-
5356}
5457
5558/**
5659 * Return a list of Available Endpoints
5760 * Pass pipe=true to filter the results to just the routes needed to populate a development database
58- *
61+ *
5962 * @param {* } req : the express request object
6063 * @param {* } endpoints : the unfiltered endpoints object list
61- * @returns
64+ * @returns
6265 */
6366const filterPipeRoutes = async ( req , endpoints ) => {
6467 const pipe = req ?. query ?. pipe ;
6568 const coreCollectionsObj = await listCollections ( CORE_DB ) ;
6669 const jsrCollectionsObj = await listCollections ( JSR_DB ) ;
6770 const jsrfCollectionsObj = await listCollections ( JSRF_DB ) ;
68- const coreCollections = coreCollectionsObj . map ( col => { return `${ col . name . toLowerCase ( ) } s` } ) ;
69- const jsrCollections = jsrCollectionsObj . map ( col => { return `${ col . name . toLowerCase ( ) } s` } ) ;
70- const jsrfCollections = jsrfCollectionsObj . map ( col => { return `${ col . name . toLowerCase ( ) } s` } ) ;
71+ const brcCollectionsObj = await listCollections ( BRC_DB ) ;
72+
73+ const coreCollections = coreCollectionsObj . map ( ( col ) => {
74+ return `${ col . name . toLowerCase ( ) } s` ;
75+ } ) ;
76+ const jsrCollections = jsrCollectionsObj . map ( ( col ) => {
77+ return `${ col . name . toLowerCase ( ) } s` ;
78+ } ) ;
79+ const jsrfCollections = jsrfCollectionsObj . map ( ( col ) => {
80+ return `${ col . name . toLowerCase ( ) } s` ;
81+ } ) ;
82+ const brcCollections = brcCollectionsObj . map ( ( col ) => {
83+ return `${ col . name . toLowerCase ( ) } s` ;
84+ } ) ;
7185
7286 endpoints = endpoints
73- . filter ( endpoint => pipe
74- ? ! endpoint . path . includes ( ':' ) && endpoint . path . includes ( '/v1/api' )
75- : endpoint )
76- . map ( endpoint => { return endpoint . path } )
87+ . filter ( ( endpoint ) =>
88+ pipe
89+ ? ! endpoint . path . includes ( ":" ) && endpoint . path . includes ( "/v1/api" )
90+ : endpoint
91+ )
92+ . map ( ( endpoint ) => {
93+ return endpoint . path ;
94+ } ) ;
7795
7896 if ( pipe ) {
7997 const filteredEndpoints = [ ] ;
8098 for ( const endpoint of endpoints ) {
81- const model = endpoint . split ( '/' ) [ 3 ] . replace ( '-' , '' ) ;
99+ const model = endpoint . split ( "/" ) [ 3 ] . replace ( "-" , "" ) ;
100+ console . log ( "processing model: " , model , " and endpoint: " , endpoint ) ;
82101 if ( coreCollections . includes ( model ) ) {
83102 filteredEndpoints . push ( endpoint ) ;
84103 }
85- if ( jsrCollections . includes ( model ) && endpoint . includes ( ' jsr' ) ) {
104+ if ( jsrCollections . includes ( model ) && endpoint . includes ( " jsr" ) ) {
86105 filteredEndpoints . push ( endpoint ) ;
87106 }
88- if ( jsrfCollections . includes ( model ) && endpoint . includes ( 'jsrf' ) ) {
107+ if ( jsrfCollections . includes ( model ) && endpoint . includes ( "jsrf" ) ) {
108+ filteredEndpoints . push ( endpoint ) ;
109+ }
110+ if (
111+ brcCollections . includes ( model ) &&
112+ ( endpoint . includes ( "brc" ) || endpoint . includes ( "collectibles" ) )
113+ ) {
89114 filteredEndpoints . push ( endpoint ) ;
90115 }
91116 }
92117 endpoints = filteredEndpoints ;
93118 }
94119 return [ ...new Set ( endpoints ) ] ;
95- }
120+ } ;
96121
122+ /* Rate Limiting */
97123const limiter = rateLimit ( {
98124 windowMs : 60 * 60 * 1000 , // 1 hour time range
99125 max : 1000 , // 1000 requests limit
100- keyGenerator : ( req ) => {
126+ keyGenerator : ( req ) => {
101127 return req . ip ;
102128 } ,
103129} ) ;
104130
131+ /* Set Cache */
105132const cacheMiddleware = ( req , res , next ) => {
106- const clientIp = req . ip ;
133+ const clientIp = req . ip ;
107134 const cacheKey = `cache_${ clientIp } _${ req . originalUrl || req . url } ` ;
108135
136+ /* Don't cache 'Random' routes */
137+ if ( req ?. path . includes ( "random" ) ) {
138+ return next ( ) ;
139+ }
140+
109141 const cachedData = cache . get ( cacheKey ) ;
110142 if ( cachedData ) {
111143 LOGGER . info ( `Cache hit for url ${ req . url } ` ) ;
@@ -128,33 +160,34 @@ const cacheMiddleware = (req, res, next) => {
128160 next ( ) ;
129161} ;
130162
163+ /* Clear Cache */
131164const clearCache = async ( req , res ) => {
132165 const username = req ?. body ?. username ;
133166 const password = req ?. body ?. password ;
134167 const adminUser = await performCoreAdminAction ( Actions . fetchAdmin , username ) ;
135168 if ( ! adminUser ) {
136- LOGGER . error ( ' Admin User Not Found' ) ;
137- return res . status ( 400 ) . send ( )
169+ LOGGER . error ( " Admin User Not Found" ) ;
170+ return res . status ( 400 ) . send ( ) ;
138171 }
139172 const authenticated = await validatePassword ( password , adminUser ?. password ) ;
140173 if ( ! authenticated ) {
141- LOGGER . error ( ' Invalid Admin Creds!' ) ;
142- return res . status ( 401 ) . send ( ' Unauthorized' ) ;
174+ LOGGER . error ( " Invalid Admin Creds!" ) ;
175+ return res . status ( 401 ) . send ( " Unauthorized" ) ;
143176 }
144177 if ( adminUser && authenticated ) {
145178 cache . clear ( ) ;
146- LOGGER . info ( ' All Caches Cleared' ) ;
147- return res . send ( ' Cache Cleared' ) ;
179+ LOGGER . info ( " All Caches Cleared" ) ;
180+ return res . send ( " Cache Cleared" ) ;
148181 }
149- res . status ( 500 ) . send ( ' Unexpected Behavior' ) ;
150- }
182+ res . status ( 500 ) . send ( " Unexpected Behavior" ) ;
183+ } ;
151184
152185const validatePassword = async ( password , hashedPassword ) => {
153186 try {
154187 return await bcrypt . compare ( password , hashedPassword ) ;
155188 } catch ( err ) {
156189 LOGGER . warn ( `Error validating Admin password ${ err } ` ) ;
157190 }
158- }
191+ } ;
159192
160- export default MiddlewareManager ;
193+ export default MiddlewareManager ;
0 commit comments