2020import org .slf4j .LoggerFactory ;
2121
2222import java .util .*;
23+ import java .util .regex .Pattern ;
24+ import java .util .regex .PatternSyntaxException ;
2325import java .util .stream .Collectors ;
2426
2527import static com .uid2 .admin .vertx .Endpoints .*;
@@ -67,6 +69,11 @@ public void setupRoutes(Router router) {
6769 this .handleDelete (ctx );
6870 }
6971 }, new AuditParams (Collections .emptyList (), List .of ("service_id" )), Role .SUPER_USER ));
72+ router .post (API_SERVICE_REMOVE_LINK_ID_REGEX .toString ()).blockingHandler (auth .handle ((ctx ) -> {
73+ synchronized (writeLock ) {
74+ this .handleRemoveLinkIdRegex (ctx );
75+ }
76+ }, new AuditParams (Collections .emptyList (), List .of ("service_id" )), Role .PRIVILEGED ));
7077 }
7178
7279 private void handleServiceListAll (RoutingContext rc ) {
@@ -113,6 +120,7 @@ private void handleServiceAdd(RoutingContext rc) {
113120 Integer siteId = body .getInteger ("site_id" );
114121 String name = body .getString ("name" );
115122 JsonArray rolesSpec = body .getJsonArray ("roles" );
123+ String linkIdRegex = body .getString ("link_id_regex" );
116124 if (siteId == null || name == null || rolesSpec == null || rolesSpec .isEmpty ()) {
117125 ResponseUtil .error (rc , 400 , "required parameters: site_id, name, roles" );
118126 return ;
@@ -147,11 +155,20 @@ private void handleServiceAdd(RoutingContext rc) {
147155 return ;
148156 }
149157
158+ if (linkIdRegex != null && !linkIdRegex .isBlank ()) {
159+ if (!isValidRegex (linkIdRegex )) {
160+ ResponseUtil .error (rc , 400 , "invalid parameter: link_id_regex; not a valid regex" );
161+ return ;
162+ }
163+ } else {
164+ linkIdRegex = null ;
165+ }
166+
150167 final List <Service > services = this .serviceProvider .getAllServices ()
151168 .stream ().sorted (Comparator .comparingInt (Service ::getServiceId ))
152169 .collect (Collectors .toList ());
153170 final int serviceId = 1 + services .stream ().mapToInt (Service ::getServiceId ).max ().orElse (0 );
154- Service service = new Service (serviceId , siteId , name , roles );
171+ Service service = new Service (serviceId , siteId , name , roles , linkIdRegex );
155172
156173 services .add (service );
157174
@@ -163,17 +180,17 @@ private void handleServiceAdd(RoutingContext rc) {
163180 }
164181 }
165182
166- // Can update the site_id, name and roles
183+ // Can update the site_id, name, roles, and link_id_regex
167184 private void handleUpdate (RoutingContext rc ) {
168185 try {
186+ serviceProvider .loadContent ();
187+ Service service = findServiceFromRequest (rc );
188+ if (service == null ) return ; // error already handled
189+
169190 JsonObject body = rc .body ().asJsonObject ();
170- if (body == null ) {
171- ResponseUtil .error (rc , 400 , "json payload required but not provided" );
172- return ;
173- }
174- Integer serviceId = body .getInteger ("service_id" );
175191 Integer siteId = body .getInteger ("site_id" );
176192 String name = body .getString ("name" );
193+ String linkIdRegex = body .getString ("link_id_regex" );
177194
178195 JsonArray rolesSpec = null ;
179196 if (body .getString ("roles" ) != null && !body .getString ("roles" ).isEmpty ()) {
@@ -185,16 +202,7 @@ private void handleUpdate(RoutingContext rc) {
185202 }
186203 }
187204
188- if (serviceId == null ) {
189- ResponseUtil .error (rc , 400 , "required parameters: service_id" );
190- return ;
191- }
192-
193- final Service service = serviceProvider .getService (serviceId );
194- if (service == null ) {
195- ResponseUtil .error (rc , 404 , "failed to find a service for service_id: " + serviceId );
196- return ;
197- }
205+ int serviceId = service .getServiceId ();
198206
199207 // check that this does not create a duplicate service
200208 if (siteHasService (siteId , name , serviceId )) {
@@ -226,6 +234,14 @@ private void handleUpdate(RoutingContext rc) {
226234 service .setRoles (roles );
227235 }
228236
237+ if (linkIdRegex != null && !linkIdRegex .isBlank ()) {
238+ if (!isValidRegex (linkIdRegex )) {
239+ ResponseUtil .error (rc , 400 , "invalid parameter: link_id_regex; not a valid regex" );
240+ return ;
241+ }
242+ service .setLinkIdRegex (linkIdRegex );
243+ }
244+
229245 if (siteId != null && siteId != 0 ) {
230246 service .setSiteId (siteId );
231247 }
@@ -234,10 +250,7 @@ private void handleUpdate(RoutingContext rc) {
234250 service .setName (name );
235251 }
236252
237- final List <Service > services = this .serviceProvider .getAllServices ()
238- .stream ().sorted (Comparator .comparingInt (Service ::getServiceId ))
239- .collect (Collectors .toList ());
240-
253+ List <Service > services = getSortedServices ();
241254
242255 storeWriter .upload (services , null );
243256
@@ -248,40 +261,31 @@ private void handleUpdate(RoutingContext rc) {
248261 }
249262
250263 private void handleDelete (RoutingContext rc ) {
251- final int serviceId ;
252- JsonObject body = rc .body () != null ? rc .body ().asJsonObject () : null ;
253- if (body == null ) {
254- ResponseUtil .error (rc , 400 , "json payload required but not provided" );
255- return ;
256- }
257- serviceId = body .getInteger ("service_id" , -1 );
258- if (serviceId == -1 ) {
259- ResponseUtil .error (rc , 400 , "required parameters: service_id" );
260- return ;
261- }
262-
263264 try {
264265 serviceProvider .loadContent ();
265-
266- Service service = serviceProvider .getService (serviceId );
267- if (service == null ) {
268- ResponseUtil .error (rc , 404 , "failed to find a service for service_id: " + serviceId );
269- return ;
270- }
271-
272- final List <Service > services = this .serviceProvider .getAllServices ()
273- .stream ().sorted (Comparator .comparingInt (Service ::getServiceId ))
274- .collect (Collectors .toList ());
275-
266+ Service service = findServiceFromRequest (rc );
267+ if (service == null ) return ; // error already handled
268+ List <Service > services = getSortedServices ();
276269 services .remove (service );
277-
278270 storeWriter .upload (services , null );
279-
280271 rc .response ().end (toJson (service ).encodePrettily ());
281272 } catch (Exception e ) {
282273 ResponseUtil .errorInternal (rc , "Internal Server Error" , e );
283274 }
275+ }
284276
277+ private void handleRemoveLinkIdRegex (RoutingContext rc ) {
278+ try {
279+ serviceProvider .loadContent ();
280+ Service service = findServiceFromRequest (rc );
281+ if (service == null ) return ; // error already handled
282+ service .setLinkIdRegex (null );
283+ List <Service > services = getSortedServices ();
284+ storeWriter .upload (services , null );
285+ rc .response ().end (toJson (service ).encodePrettily ());
286+ } catch (Exception e ) {
287+ ResponseUtil .errorInternal (rc , "Internal Server Error" , e );
288+ }
285289 }
286290
287291 private JsonObject toJson (Service s ) {
@@ -290,6 +294,7 @@ private JsonObject toJson(Service s) {
290294 jsonObject .put ("site_id" , s .getSiteId ());
291295 jsonObject .put ("name" , s .getName ());
292296 jsonObject .put ("roles" , s .getRoles ());
297+ jsonObject .put ("link_id_regex" , s .getLinkIdRegex ());
293298 return jsonObject ;
294299 }
295300
@@ -302,4 +307,42 @@ private boolean siteHasService(Integer siteId, String name, int serviceId) {
302307 && serviceProvider .getAllServices ().stream ().anyMatch (s -> s .getServiceId () != serviceId
303308 && s .getSiteId () == siteId && s .getName ().equals (name ));
304309 }
310+
311+
312+ private Service findServiceFromRequest (RoutingContext rc ) {
313+ JsonObject body = rc .body () != null ? rc .body ().asJsonObject () : null ;
314+ if (body == null ) {
315+ ResponseUtil .error (rc , 400 , "json payload required but not provided" );
316+ return null ;
317+ }
318+
319+ int serviceId = body .getInteger ("service_id" , -1 );
320+ if (serviceId == -1 ) {
321+ ResponseUtil .error (rc , 400 , "required parameters: service_id" );
322+ return null ;
323+ }
324+
325+ Service service = serviceProvider .getService (serviceId );
326+ if (service == null ) {
327+ ResponseUtil .error (rc , 404 , "failed to find a service for service_id: " + serviceId );
328+ return null ;
329+ }
330+ return service ;
331+ }
332+
333+ private List <Service > getSortedServices () {
334+ return serviceProvider .getAllServices ()
335+ .stream ()
336+ .sorted (Comparator .comparingInt (Service ::getServiceId ))
337+ .collect (Collectors .toList ());
338+ }
339+
340+ private boolean isValidRegex (String regex ) {
341+ try {
342+ Pattern .compile (regex );
343+ return true ;
344+ } catch (PatternSyntaxException e ) {
345+ return false ;
346+ }
347+ }
305348}
0 commit comments