From abd281568bf333c1f8a8b016c3ac524a02da5df6 Mon Sep 17 00:00:00 2001 From: Brayden Tan Date: Mon, 18 Sep 2023 18:35:12 +0800 Subject: [PATCH] PRESIDECMS-2709 preside utils rest api feature endpoint --- system/config/Config.cfc | 8 +++++ .../rest-apis/presideUtils/feature.cfc | 14 ++++++++ .../rest-apis/presideUtils/features.cfc | 16 +++++++++ system/handlers/rest/auth/PresideApi.cfc | 26 +++++++++++++++ system/services/features/FeatureService.cfc | 33 +++++++++++++++++++ 5 files changed, 97 insertions(+) create mode 100644 system/handlers/rest-apis/presideUtils/feature.cfc create mode 100644 system/handlers/rest-apis/presideUtils/features.cfc create mode 100644 system/handlers/rest/auth/PresideApi.cfc diff --git a/system/config/Config.cfc b/system/config/Config.cfc index 1730676806..12b40bcc38 100644 --- a/system/config/Config.cfc +++ b/system/config/Config.cfc @@ -980,6 +980,14 @@ component { }; settings.rest.authProviders.token = { feature = "restTokenAuth" }; + + settings.rest.apis[ "/presideUtils" ] = { + authProvider = "presideApi" + , description = "Utility REST API for external systems to interact with Preside" + , dataApiQueueEnabled = false + }; + + settings.preside.restauthtoken = settings.env.preside_rest_auth_token ?: ""; } private void function __setupMultilingualDefaults() { diff --git a/system/handlers/rest-apis/presideUtils/feature.cfc b/system/handlers/rest-apis/presideUtils/feature.cfc new file mode 100644 index 0000000000..d93bbe0bd2 --- /dev/null +++ b/system/handlers/rest-apis/presideUtils/feature.cfc @@ -0,0 +1,14 @@ +/** + * @restUri /features/{feature}/ + */ +component { + property name="features" inject="coldbox:setting:features"; + + private void function get( required string feature ) { + if ( StructKeyExists( features, arguments.feature ) ) { + restResponse.setData( features[ arguments.feature ] ); + } else { + restResponse.setData( { enabled=false } ); + } + } +} \ No newline at end of file diff --git a/system/handlers/rest-apis/presideUtils/features.cfc b/system/handlers/rest-apis/presideUtils/features.cfc new file mode 100644 index 0000000000..3fabaca2c6 --- /dev/null +++ b/system/handlers/rest-apis/presideUtils/features.cfc @@ -0,0 +1,16 @@ +/** + * @restUri /features/ + */ +component { + property name="featureService" inject="featureService"; + + private void function get() { + var allFeatures = {}; + + for ( var feature in featureService.getAllEnabledFeatures() ) { + allFeatures[ feature ] = true; + } + + restResponse.setData( allFeatures ); + } +} \ No newline at end of file diff --git a/system/handlers/rest/auth/PresideApi.cfc b/system/handlers/rest/auth/PresideApi.cfc new file mode 100644 index 0000000000..1f8d1982d0 --- /dev/null +++ b/system/handlers/rest/auth/PresideApi.cfc @@ -0,0 +1,26 @@ +component { + property name="configuredToken" inject="coldbox:setting:preside.restauthtoken"; + + private string function authenticate() { + var headers = getHTTPRequestData( false ).headers; + var authHeader = headers.Authorization ?: ""; + var token = ""; + + try { + authHeader = toString( toBinary( listRest( authHeader, ' ' ) ) ); + token = ListFirst( authHeader, ":" ); + + if ( !token.trim().len() ) { + throw( type="missing.token" ); + } + } catch( any e ) { + return ""; + } + + if ( token == configuredToken ) { + return token; + } + + return ""; + } +} \ No newline at end of file diff --git a/system/services/features/FeatureService.cfc b/system/services/features/FeatureService.cfc index 0036a3c1d4..a1cb47a901 100644 --- a/system/services/features/FeatureService.cfc +++ b/system/services/features/FeatureService.cfc @@ -13,6 +13,7 @@ component singleton=true autodoc=true displayName="Feature service" { */ public any function init( required struct configuredFeatures ) { _setConfiguredFeatures( arguments.configuredFeatures ); + _setLocalCache( {} ); return this; } @@ -74,6 +75,31 @@ component singleton=true autodoc=true displayName="Feature service" { return ""; } + public array function getAllEnabledFeatures() { + return _simpleLocalCache( "getAllEnabledFeatures", function() { + var allEnabledFeatures = []; + + for ( var feature in _getConfiguredFeatures() ) { + if ( isFeatureEnabled( feature=feature ) ) { + ArrayAppend( allEnabledFeatures, feature ); + } + } + + return allEnabledFeatures; + } ); + } + +// PRIVATE HELPERS + private any function _simpleLocalCache( required string cacheKey, required any generator ) { + var cache = _getLocalCache(); + + if ( !StructKeyExists( cache, cacheKey ) ) { + cache[ cacheKey ] = generator(); + } + + return cache[ cacheKey ] ?: NullValue(); + } + // GETTERS AND SETTERS private struct function _getConfiguredFeatures() { return _configuredFeatures; @@ -81,4 +107,11 @@ component singleton=true autodoc=true displayName="Feature service" { private void function _setConfiguredFeatures( required struct configuredFeatures ) { _configuredFeatures = arguments.configuredFeatures; } + + private struct function _getLocalCache() { + return _localCache; + } + private void function _setLocalCache( required struct localCache ) { + _localCache = arguments.localCache; + } } \ No newline at end of file