Skip to content
This repository was archived by the owner on Sep 2, 2020. It is now read-only.

Commit 2dbdc53

Browse files
authored
feat(cbguard): Allow for per-module overrides of cbguard settings
If a module specifies a `cbguard` key in its `settings` struct inside `ModuleConfig`, cbguard will use those as overrides to the base module settings for module events.
1 parent 693f6d4 commit 2dbdc53

File tree

12 files changed

+273
-23
lines changed

12 files changed

+273
-23
lines changed

README.md

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,4 +194,27 @@ moduleSettings = {
194194
`relocate` refers to calling `relocate` on the controller. The user will be redirected to the new page.
195195
`override` refers to `event.overrideEvent`. This will not redirect but simply change the running event.
196196

197-
`
197+
198+
### Module Overrides
199+
200+
All of the `cbguard` settings can be overriden inside a module. This allows modules, such as an API module, to provide
201+
their own authentication services as well as redirect events.
202+
203+
To specify some overrides, create a `cbguard` struct in your desired module's `settings` in that module's `ModuleConfig.cfc`.
204+
205+
```cfc
206+
component {
207+
208+
this.name = "myModule";
209+
210+
function configure() {
211+
settings = {
212+
"cbguard" = {
213+
"authenticationOverrideEvent" = "myModule:Main.onAuthenticationFailure",
214+
"authorizationOverrideEvent" = "myModule:Main.onAuthorizationFailure"
215+
}
216+
};
217+
}
218+
219+
}
220+
```

interceptors/SecuredEventInterceptor.cfc

Lines changed: 51 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
component extends="coldbox.system.Interceptor"{
22

3-
property name="handlerService" inject="coldbox:handlerService";
43
property name="coldboxVersion" inject="coldbox:fwSetting:version";
4+
property name="handlerService" inject="coldbox:handlerService";
5+
property name="moduleService" inject="coldbox:moduleService";
56

67
void function configure() {}
78

@@ -16,8 +17,13 @@ component extends="coldbox.system.Interceptor"{
1617
* the event is overridden to the event specified in module settings.
1718
*/
1819
function preProcess( event, rc, prc, interceptData, buffer ) {
19-
if ( isNull( variables.authenticationService ) ) {
20-
variables.authenticationService = wirebox.getInstance( getProperty( "AuthenticationService" ) );
20+
var overrides = {};
21+
if ( event.getCurrentModule() != "" ) {
22+
var moduleConfig = moduleService.getModuleConfigCache()[ event.getCurrentModule() ];
23+
var moduleSettings = moduleConfig.getPropertyMixin( "settings", "variables", {} );
24+
if ( structKeyExists( moduleSettings, "cbguard" ) ) {
25+
overrides = moduleSettings.cbguard;
26+
}
2127
}
2228

2329
if( listFirst( coldboxVersion, "." ) >= 5 ){
@@ -32,8 +38,8 @@ component extends="coldbox.system.Interceptor"{
3238

3339
var handlerMetadata = getMetadata( handler );
3440

35-
return notAuthorizedForHandler( handlerMetadata, event ) ||
36-
notAuthorizedForAction( handlerMetadata, event );
41+
return notAuthorizedForHandler( handlerMetadata, event, overrides ) ||
42+
notAuthorizedForAction( handlerMetadata, event, overrides );
3743
}
3844

3945
/**
@@ -45,7 +51,19 @@ component extends="coldbox.system.Interceptor"{
4551
* If the user is not logged in or does not have one of the required permissions,
4652
* the event is overridden to the event specified in module settings.
4753
*/
48-
private function notAuthorizedForHandler( handlerMetadata, event ) {
54+
private function notAuthorizedForHandler( handlerMetadata, event, overrides = {} ) {
55+
var props = {};
56+
structAppend( props, variables.properties, true );
57+
structAppend( props, overrides, true );
58+
59+
if ( isSimpleValue( props.authenticationService ) ) {
60+
props.authenticationService = wirebox.getInstance( props.authenticationService );
61+
}
62+
param props.authenticationOverrideEvent = "";
63+
param props.authenticationAjaxOverrideEvent = props.authenticationOverrideEvent;
64+
param props.authorizationOverrideEvent = "";
65+
param props.authorizationAjaxOverrideEvent = props.authorizationOverrideEvent;
66+
4967
if ( ! structKeyExists( handlerMetadata, "secured" ) ) {
5068
return false;
5169
}
@@ -54,10 +72,10 @@ component extends="coldbox.system.Interceptor"{
5472
return false;
5573
}
5674

57-
if ( ! invoke( authenticationService, getProperty( "methodNames" )[ "isLoggedIn" ] ) ) {
75+
if ( ! invoke( props.authenticationService, props.methodNames[ "isLoggedIn" ] ) ) {
5876
var eventType = event.isAjax() ? "authenticationAjaxOverrideEvent" : "authenticationOverrideEvent";
59-
var relocateEvent = getProperty( eventType );
60-
var overrideAction = getProperty( "overrideActions" )[ eventType ];
77+
var relocateEvent = props[ eventType ];
78+
var overrideAction = props.overrideActions[ eventType ];
6179
switch ( overrideAction ) {
6280
case "relocate":
6381
relocate( relocateEvent );
@@ -83,17 +101,17 @@ component extends="coldbox.system.Interceptor"{
83101
return false;
84102
}
85103

86-
var loggedInUser = invoke( authenticationService, getProperty( "methodNames" )[ "getUser" ] );
104+
var loggedInUser = invoke( props.authenticationService, props.methodNames[ "getUser" ] );
87105

88106
for ( var permission in neededPermissions ) {
89-
if ( invoke( loggedInUser, getProperty( "methodNames" )[ "hasPermission" ], { permission = permission } ) ) {
107+
if ( invoke( loggedInUser, props.methodNames[ "hasPermission" ], { permission = permission } ) ) {
90108
return false;
91109
}
92110
}
93111

94112
var eventType = event.isAjax() ? "authorizationAjaxOverrideEvent" : "authorizationOverrideEvent";
95-
var relocateEvent = getProperty( eventType );
96-
var overrideAction = getProperty( "overrideActions" )[ eventType ];
113+
var relocateEvent = props[ eventType ];
114+
var overrideAction = props.overrideActions[ eventType ];
97115
switch ( overrideAction ) {
98116
case "relocate":
99117
relocate( relocateEvent );
@@ -119,7 +137,19 @@ component extends="coldbox.system.Interceptor"{
119137
* If the user is not logged in or does not have one of the required permissions,
120138
* the event is overridden to the event specified in module settings.
121139
*/
122-
private function notAuthorizedForAction( handlerMetadata, event ) {
140+
private function notAuthorizedForAction( handlerMetadata, event, overrides = {} ) {
141+
var props = {};
142+
structAppend( props, variables.properties, true );
143+
structAppend( props, overrides, true );
144+
145+
if ( isSimpleValue( props.authenticationService ) ) {
146+
props.authenticationService = wirebox.getInstance( props.authenticationService );
147+
}
148+
param props.authenticationOverrideEvent = "";
149+
param props.authenticationAjaxOverrideEvent = props.authenticationOverrideEvent;
150+
param props.authorizationOverrideEvent = "";
151+
param props.authorizationAjaxOverrideEvent = props.authorizationOverrideEvent;
152+
123153
if ( ! structKeyExists( handlerMetadata, "functions" ) ) {
124154
return false;
125155
}
@@ -137,10 +167,10 @@ component extends="coldbox.system.Interceptor"{
137167
return false;
138168
}
139169

140-
if ( ! invoke( authenticationService, getProperty( "methodNames" )[ "isLoggedIn" ] ) ) {
170+
if ( ! invoke( props.authenticationService, props.methodNames[ "isLoggedIn" ] ) ) {
141171
var eventType = event.isAjax() ? "authenticationAjaxOverrideEvent" : "authenticationOverrideEvent";
142-
var relocateEvent = getProperty( eventType );
143-
var overrideAction = getProperty( "overrideActions" )[ eventType ];
172+
var relocateEvent = props[ eventType ];
173+
var overrideAction = props.overrideActions[ eventType ];
144174
switch ( overrideAction ) {
145175
case "relocate":
146176
relocate( relocateEvent );
@@ -166,17 +196,17 @@ component extends="coldbox.system.Interceptor"{
166196
return false;
167197
}
168198

169-
var loggedInUser = invoke( authenticationService, getProperty( "methodNames" )[ "getUser" ] );
199+
var loggedInUser = invoke( props.authenticationService, props.methodNames[ "getUser" ] );
170200

171201
for ( var permission in neededPermissions ) {
172-
if ( invoke( loggedInUser, getProperty( "methodNames" )[ "hasPermission" ], { permission = permission } ) ) {
202+
if ( invoke( loggedInUser, props.methodNames[ "hasPermission" ], { permission = permission } ) ) {
173203
return false;
174204
}
175205
}
176206

177207
var eventType = event.isAjax() ? "authorizationAjaxOverrideEvent" : "authorizationOverrideEvent";
178-
var relocateEvent = getProperty( eventType );
179-
var overrideAction = getProperty( "overrideActions" )[ eventType ];
208+
var relocateEvent = props[ eventType ];
209+
var overrideAction = props.overrideActions[ eventType ];
180210
switch ( overrideAction ) {
181211
case "relocate":
182212
relocate( relocateEvent );

tests/resources/app/config/Coldbox.cfc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
//Extension Points
2727
applicationHelper = "includes/helpers/ApplicationHelper.cfm",
2828
viewsHelper = "",
29-
modulesExternalLocation = [ "modules_app" ],
29+
modulesExternalLocation = [ "/app/modules_app" ],
3030
viewsExternalLocation = "",
3131
layoutsExternalLocation = "",
3232
handlersExternalLocation = "",

tests/resources/app/modules_app/custom_modules_here.txt

Whitespace-only changes.
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
component {
2+
3+
this.title = "myModule";
4+
this.description = "myModule";
5+
this.version = "1.0.0";
6+
this.cfmapping = "myModule";
7+
this.dependencies = [];
8+
9+
function configure() {
10+
settings = {
11+
"cbguard" = {
12+
"authenticationService" = "SecurityService@myModule",
13+
"authenticationOverrideEvent" = "myModule:Main.onAuthenticationFailure",
14+
"authenticationAjaxOverrideEvent" = "myModule:api.v1.BaseAPIHandler.onAuthenticationFailure",
15+
"authorizationOverrideEvent" = "myModule:Main.onAuthorizationFailure",
16+
"authorizationAjaxOverrideEvent" = "myModule:api.v1.BaseAPIHandler.onAuthorizationFailure"
17+
}
18+
};
19+
20+
routes = [
21+
{ pattern = "/:handler/:action?" }
22+
];
23+
}
24+
25+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
component secured="one" {
2+
3+
function securedAction( event, rc, prc ) secured="two" {
4+
event.noRender();
5+
}
6+
7+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
component {
2+
3+
function onAuthenticationFailure() {
4+
event.noRender();
5+
}
6+
7+
function onAuthorizationFailure() {
8+
event.noRender();
9+
}
10+
11+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
component {
2+
3+
function fooPermissionAction( event, rc, prc ) secured="foo" {
4+
event.noRender();
5+
}
6+
7+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
component secured="foo" {
2+
3+
function fooPermissionAction( event, rc, prc ) {
4+
event.noRender();
5+
}
6+
7+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
component {
2+
3+
function onAuthenticationFailure() {
4+
event.noRender();
5+
}
6+
7+
function onAuthorizationFailure() {
8+
event.noRender();
9+
}
10+
11+
}

0 commit comments

Comments
 (0)