11package org .swisspush .gateleen .security .authorization ;
22
3+ import io .vertx .core .Future ;
34import io .vertx .core .Promise ;
45import io .vertx .core .buffer .Buffer ;
56import io .vertx .core .http .HttpServerRequest ;
1617
1718import java .util .*;
1819import java .util .Map .Entry ;
20+ import java .util .concurrent .atomic .AtomicBoolean ;
1921import java .util .regex .Matcher ;
2022
2123
@@ -40,6 +42,7 @@ public class RoleAuthorizer implements ConfigurationResource {
4042 private final RoleExtractor roleExtractor ;
4143 private final Map <PatternHolder , Map <String , Set <String >>> initialGrantedRoles ;
4244 private final boolean grantAccessWithoutRoles ;
45+ private final AtomicBoolean initialized = new AtomicBoolean (false );
4346
4447 // URI -> Method -> Roles
4548 private Map <PatternHolder , Map <String , Set <String >>> grantedRoles = new HashMap <>();
@@ -75,8 +78,13 @@ public class RoleAuthorizer implements ConfigurationResource {
7578 initialGrantedRoles .get (aclUriPattern ).get ("PUT" ).add (adminRole );
7679 initialGrantedRoles .get (aclUriPattern ).get ("GET" ).add (adminRole );
7780 initialGrantedRoles .get (aclUriPattern ).get ("DELETE" ).add (adminRole );
81+ }
7882
79- configUpdate ();
83+ public Future <Void > init () {
84+ if (initialized .compareAndSet (false , true )) {
85+ return configUpdateInternal ();
86+ }
87+ return Future .failedFuture ("RoleAuthorizer already initialized" );
8088 }
8189
8290 public void handleIsAuthorized (final HttpServerRequest request , Promise <Boolean > promise ) {
@@ -96,21 +104,35 @@ public void checkConfigResource(Buffer buffer) throws ValidationException {
96104
97105 @ Override
98106 public void configUpdate () {
107+ configUpdateInternal ();
108+ }
109+
110+ private Future <Void > configUpdateInternal () {
111+ final Promise <Void > promise = Promise .promise ();
99112 storage .get (aclRoot , buffer -> {
113+ final List <Future <Void >> futures = new ArrayList <>();
100114 if (buffer != null ) {
101115 grantedRoles = new HashMap <>();
102116 for (Object roleObject : new JsonObject (buffer ).getJsonArray (aclKey )) {
103117 String role = (String ) roleObject ;
104- updateAcl (role );
118+ futures . add ( updateAcl (role ) );
105119 }
106120 } else {
107121 log .warn ("No ACLs in storage, using initial authorization." );
108122 grantedRoles = initialGrantedRoles ;
123+ futures .add (Future .succeededFuture ());
109124 }
125+ Future .all (futures ).onComplete (event -> {
126+ if (event .failed ()) {
127+ promise .fail (event .cause ());
128+ } else {
129+ promise .complete ();
130+ }
131+ });
110132 });
133+ return promise .future ();
111134 }
112135
113-
114136 /**
115137 * Extracts the Users Roles from the Request and further validates if the user is allowed to access
116138 * the URL according to the ACL
@@ -211,19 +233,23 @@ private boolean checkRole(Map<String, RoleMapper.MappedRole> roles, HttpServerRe
211233 return authorized ;
212234 }
213235
214- private void updateAcl (final String role ) {
236+ private Future <Void > updateAcl (final String role ) {
237+ final Promise <Void > promise = Promise .promise ();
215238 storage .get (aclRoot + role , buffer -> {
216239 if (buffer != null ) {
217240 try {
218241 log .info ("Applying acl for {}" , role );
219242 mergeAcl (role , buffer );
243+ promise .complete (null );
220244 } catch (ValidationException validationException ) {
221- log .error ("Could not parse acls: {}" , validationException .toString ());
245+ log .error ("Could not parse acls: {}" , role , validationException );
246+ promise .fail (validationException );
222247 }
223248 } else {
224- log . error ("No acl for role {} found in storage" , role );
249+ promise . fail ("No acl for role " + role + " found in storage" );
225250 }
226251 });
252+ return promise .future ();
227253 }
228254
229255 private void mergeAcl (String role , Buffer buffer ) throws ValidationException {
0 commit comments