Extract class StopWatch from ApiService
[dmaap/dbcapi.git] / src / main / java / org / onap / dmaap / dbcapi / service / ApiService.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * org.onap.dmaap
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.dmaap.dbcapi.service;
22
23 import static com.att.eelf.configuration.Configuration.MDC_KEY_REQUEST_ID;
24 import static com.att.eelf.configuration.Configuration.MDC_PARTNER_NAME;
25 import static com.att.eelf.configuration.Configuration.MDC_SERVICE_NAME;
26
27 import java.util.regex.Matcher;
28 import java.util.regex.Pattern;
29 import javax.ws.rs.core.Response.Status;
30 import javax.xml.bind.DatatypeConverter;
31 import org.onap.dmaap.dbcapi.aaf.DmaapPerm;
32 import org.onap.dmaap.dbcapi.authentication.ApiPolicy;
33 import org.onap.dmaap.dbcapi.authentication.AuthenticationErrorException;
34 import org.onap.dmaap.dbcapi.logging.BaseLoggingClass;
35 import org.onap.dmaap.dbcapi.model.ApiError;
36 import org.onap.dmaap.dbcapi.model.Dmaap;
37 import org.onap.dmaap.dbcapi.resources.RequiredFieldException;
38 import org.onap.dmaap.dbcapi.util.DmaapConfig;
39 import org.onap.dmaap.dbcapi.util.RandomString;
40 import org.slf4j.MDC;
41
42 public class ApiService extends BaseLoggingClass {
43
44     private String apiNamespace;
45     private String uri;
46     private String uriPath;
47     private String method;
48     private String authorization;
49     private String requestId;
50     private ApiError err;
51     private ApiPolicy apiPolicy;
52
53     public ApiService() {
54
55         err = new ApiError();
56         requestId = (new RandomString(10)).nextString();
57
58         if (apiNamespace == null) {
59             DmaapConfig p = (DmaapConfig) DmaapConfig.getConfig();
60             apiNamespace = p.getProperty("ApiNamespace", "org.openecomp.dmaapBC.api");
61             logger.info("config param usePE has been deprecated.  Use ApiPermission.Class property instead.");
62         }
63         apiPolicy = new ApiPolicy();
64
65         logger.info("apiNamespace=" + apiNamespace);
66     }
67
68     public ApiService setAuth(String auth) {
69         this.authorization = auth;
70         logger.info("setAuth:  authorization={} ", authorization);
71         return this;
72     }
73
74     private void setServiceName() {
75         String svcRequest = new String(this.method + " " + this.uriPath);
76         MDC.put(MDC_SERVICE_NAME, svcRequest);
77     }
78
79     public ApiService setHttpMethod(String httpMethod) {
80         this.method = httpMethod;
81         logger.info("setHttpMethod: method={} ", method);
82         setServiceName();
83         return this;
84     }
85
86     public ApiService setUriPath(String uriPath) {
87         this.uriPath = uriPath;
88         this.uri = setUriFromPath(uriPath);
89         logger.info("setUriPath: uriPath={} uri={}", uriPath, uri);
90         setServiceName();
91         return this;
92     }
93
94     private String setUriFromPath(String uriPath) {
95         int ch = uriPath.indexOf("/");
96         if (ch > 0) {
97             return ((String) uriPath.subSequence(0, ch));
98         } else {
99             return uriPath;
100         }
101     }
102
103     public ApiError getErr() {
104         return err;
105     }
106
107
108     public void setErr(ApiError err) {
109         this.err = err;
110     }
111
112
113     // test for presence of a required field
114     public void required(String name, Object val, String expr) throws RequiredFieldException {
115         err.setCode(0);
116         if (val == null) {
117             err.setCode(Status.BAD_REQUEST.getStatusCode());
118             err.setMessage("missing required field");
119             err.setFields(name);
120             throw new RequiredFieldException();
121         }
122         if (expr != null && !expr.isEmpty()) {
123             Pattern pattern = Pattern.compile(expr);
124             Matcher matcher = pattern.matcher((CharSequence) val);
125             if (!matcher.find()) {
126                 err.setCode(Status.BAD_REQUEST.getStatusCode());
127                 err.setMessage("value '" + val + "' violates regexp check '" + expr + "'");
128                 err.setFields(name);
129                 throw new RequiredFieldException();
130             }
131         }
132     }
133
134     // utility to serialize ApiErr object
135     public String toString() {
136         return String.format("code=%d msg=%s fields=%s", err.getCode(), err.getMessage(), err.getFields());
137     }
138
139
140     public void setCode(int statusCode) {
141         err.setCode(statusCode);
142     }
143
144
145     public void setMessage(String string) {
146         err.setMessage(string);
147     }
148
149
150     public void setFields(String string) {
151         err.setFields(string);
152     }
153
154     public void checkAuthorization(String auth, String uriPath, String httpMethod)
155         throws AuthenticationErrorException, Exception {
156         authorization = auth;
157         setUriFromPath(uriPath);
158         method = httpMethod;
159
160         checkAuthorization();
161     }
162
163
164     public void checkAuthorization() throws AuthenticationErrorException, Exception {
165
166         MDC.put(MDC_KEY_REQUEST_ID, requestId);
167
168         logger.info("request: uri={} method={} auth={}", uri, method, authorization);
169
170         if (uri == null || uri.isEmpty()) {
171             String errmsg = "No URI value provided ";
172             err.setMessage(errmsg);
173             logger.info(errmsg);
174             throw new AuthenticationErrorException();
175         }
176         if (method == null || method.isEmpty()) {
177             String errmsg = "No method value provided ";
178             err.setMessage(errmsg);
179             logger.info(errmsg);
180             throw new AuthenticationErrorException();
181         }
182         DmaapService dmaapService = new DmaapService();
183         Dmaap dmaap = dmaapService.getDmaap();
184         String env = dmaap.getDmaapName();
185
186         // special case during bootstrap of app when DMaaP environment may not be set.
187         // this allows us to authorize certain APIs used for initialization during this window.
188         if (env == null || env.isEmpty()) {
189             env = "boot";
190         }
191         if (!apiPolicy.getUseAuthClass()) {
192             return;  // skip authorization if not enabled
193         }
194         if (authorization == null || authorization.isEmpty()) {
195             String errmsg = "No basic authorization value provided ";
196             err.setMessage(errmsg);
197             logger.info(errmsg);
198             throw new AuthenticationErrorException();
199         }
200         String credentials = authorization.substring("Basic".length()).trim();
201         byte[] decoded = DatatypeConverter.parseBase64Binary(credentials);
202         String decodedString = new String(decoded);
203         String[] actualCredentials = decodedString.split(":");
204         String ID = actualCredentials[0];
205         String Password = actualCredentials[1];
206         MDC.put(MDC_PARTNER_NAME, ID);
207         try {
208
209             DmaapPerm p = new DmaapPerm(apiNamespace + "." + uri, env, method);
210             apiPolicy.check(ID, Password, p);
211         } catch (AuthenticationErrorException ae) {
212             String errmsg =
213                 "User " + ID + " failed authentication/authorization for " + apiNamespace + "." + uriPath + " " + env
214                     + " " + method;
215             logger.info(errmsg);
216             err.setMessage(errmsg);
217             throw ae;
218
219         }
220
221
222     }
223
224     public String getRequestId() {
225         return requestId;
226     }
227
228     public ApiService setRequestId(String requestId) {
229         if (requestId == null || requestId.isEmpty()) {
230             this.requestId = (new RandomString(10)).nextString();
231             logger.warn("X-ECOMP-RequestID not set in HTTP Header.  Setting RequestId value to: " + this.requestId);
232         } else {
233             this.requestId = requestId;
234         }
235         MDC.put(MDC_KEY_REQUEST_ID, this.requestId);
236         return this;
237     }
238 }