View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.syncope.client.console.rest;
20  
21  import com.fasterxml.jackson.databind.JsonNode;
22  import com.fasterxml.jackson.databind.json.JsonMapper;
23  import java.io.InputStream;
24  import java.util.ArrayList;
25  import java.util.Comparator;
26  import java.util.Iterator;
27  import java.util.List;
28  import java.util.Map;
29  import java.util.stream.Collectors;
30  import java.util.stream.Stream;
31  import javax.ws.rs.core.MediaType;
32  import javax.ws.rs.core.Response;
33  import org.apache.syncope.client.console.SyncopeWebApplication;
34  import org.apache.syncope.client.lib.WebClientBuilder;
35  import org.apache.syncope.client.ui.commons.rest.RestClient;
36  import org.apache.syncope.common.keymaster.client.api.model.Domain;
37  import org.apache.syncope.common.keymaster.client.api.model.NetworkService;
38  import org.apache.syncope.common.lib.SyncopeConstants;
39  import org.apache.syncope.common.lib.types.AuditLoggerName;
40  import org.slf4j.Logger;
41  import org.slf4j.LoggerFactory;
42  import org.springframework.boot.logging.LogLevel;
43  
44  public class LoggerConfRestClient implements RestClient, LoggerConfOp {
45  
46      private static final long serialVersionUID = 16051907544728L;
47  
48      protected static final Logger LOG = LoggerFactory.getLogger(LoggerConfRestClient.class);
49  
50      protected static final JsonMapper MAPPER = JsonMapper.builder().findAndAddModules().build();
51  
52      private final List<NetworkService> instances;
53  
54      private final List<String> domains;
55  
56      public LoggerConfRestClient(final List<NetworkService> instances, final List<Domain> domains) {
57          this.instances = instances;
58          this.domains = Stream.concat(
59                  Stream.of(SyncopeConstants.MASTER_DOMAIN), domains.stream().map(Domain::getKey)).
60                  collect(Collectors.toList());
61      }
62  
63      protected String getActuatorEndpoint(final NetworkService instance) {
64          String address = instance.getAddress();
65          if (address.contains("/rest")) {
66              address = address.replace("/rest", "");
67          }
68          return address + "actuator/loggers";
69      }
70  
71      @Override
72      public List<LoggerConf> list() {
73          List<LoggerConf> loggerConfs = new ArrayList<>();
74  
75          try {
76              Response response = WebClientBuilder.build(getActuatorEndpoint(instances.get(0)),
77                      SyncopeWebApplication.get().getAnonymousUser(),
78                      SyncopeWebApplication.get().getAnonymousKey(),
79                      List.of()).accept(MediaType.APPLICATION_JSON_TYPE).get();
80              if (response.getStatus() == Response.Status.OK.getStatusCode()) {
81                  JsonNode node = MAPPER.readTree((InputStream) response.getEntity());
82                  if (node.has("loggers")) {
83                      for (Iterator<Map.Entry<String, JsonNode>> itor = node.get("loggers").fields(); itor.hasNext();) {
84                          Map.Entry<String, JsonNode> entry = itor.next();
85  
86                          LoggerConf loggerConf = new LoggerConf();
87                          loggerConf.setKey(entry.getKey());
88                          if (entry.getValue().has("effectiveLevel")) {
89                              loggerConf.setLevel(LogLevel.valueOf(entry.getValue().get("effectiveLevel").asText()));
90                          } else {
91                              loggerConf.setLevel(LogLevel.OFF);
92                          }
93  
94                          if (!loggerConf.getKey().startsWith(AuditLoggerName.AUDIT_PREFIX)
95                                  && domains.stream().noneMatch(domain -> loggerConf.getKey().startsWith(domain))) {
96  
97                              loggerConfs.add(loggerConf);
98                          }
99                      }
100                 }
101             } else {
102                 LOG.error("Unexpected response for loggers from {}: {}",
103                         getActuatorEndpoint(instances.get(0)), response.getStatus());
104             }
105         } catch (Exception e) {
106             LOG.error("Could not fetch loggers from {}", getActuatorEndpoint(instances.get(0)), e);
107         }
108 
109         loggerConfs.sort(Comparator.comparing(LoggerConf::getKey));
110         return loggerConfs;
111     }
112 
113     @Override
114     public void setLevel(final String key, final LogLevel level) {
115         instances.forEach(i -> WebClientBuilder.build(getActuatorEndpoint(i),
116                 SyncopeWebApplication.get().getAnonymousUser(),
117                 SyncopeWebApplication.get().getAnonymousKey(),
118                 List.of()).
119                 accept(MediaType.APPLICATION_JSON_TYPE).
120                 type(MediaType.APPLICATION_JSON_TYPE).
121                 path(key).
122                 post("{\"configuredLevel\": \"" + level.name() + "\"}"));
123     }
124 }