AafService - interface was introduced
[dmaap/dbcapi.git] / src / main / java / org / onap / dmaap / dbcapi / service / MR_ClientService.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * org.onap.dmaap
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  *
7  * Modifications Copyright (C) 2019 IBM.
8  * ================================================================================
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  * ============LICENSE_END=========================================================
21  */
22
23 package org.onap.dmaap.dbcapi.service;
24
25 import org.onap.dmaap.dbcapi.aaf.AafService;
26 import org.onap.dmaap.dbcapi.aaf.AafService.ServiceType;
27 import org.onap.dmaap.dbcapi.aaf.AafServiceImpl;
28 import org.onap.dmaap.dbcapi.aaf.AafUserRole;
29 import org.onap.dmaap.dbcapi.aaf.DmaapGrant;
30 import org.onap.dmaap.dbcapi.aaf.DmaapPerm;
31 import org.onap.dmaap.dbcapi.client.MrProvConnection;
32 import org.onap.dmaap.dbcapi.database.DatabaseClass;
33 import org.onap.dmaap.dbcapi.logging.BaseLoggingClass;
34 import org.onap.dmaap.dbcapi.model.ApiError;
35 import org.onap.dmaap.dbcapi.model.DcaeLocation;
36 import org.onap.dmaap.dbcapi.model.DmaapObject.DmaapObject_Status;
37 import org.onap.dmaap.dbcapi.model.MR_Client;
38 import org.onap.dmaap.dbcapi.model.MR_Cluster;
39 import org.onap.dmaap.dbcapi.model.Topic;
40 import org.onap.dmaap.dbcapi.util.DmaapConfig;
41
42 import javax.ws.rs.core.Response.Status;
43 import java.util.ArrayList;
44 import java.util.List;
45 import java.util.Map;
46
47 public class MR_ClientService extends BaseLoggingClass {
48
49     private static final String MR_CLIENT_ID = "mrClientId";
50     private int deleteLevel;
51     private Map<String, MR_Client> mr_clients = DatabaseClass.getMr_clients();
52     private Map<String, MR_Cluster> clusters = DatabaseClass.getMr_clusters();
53     private Map<String, DcaeLocation> locations = DatabaseClass.getDcaeLocations();
54     private DmaapService dmaap = new DmaapService();
55     private String centralCname;
56
57     public MR_ClientService() {
58         DmaapConfig p = (DmaapConfig) DmaapConfig.getConfig();
59
60         centralCname = p.getProperty("MR.CentralCname", "MRcname.not.set");
61         deleteLevel = Integer.valueOf(p.getProperty("MR.ClientDeleteLevel", "0"));
62     }
63
64     public List<MR_Client> getAllMr_Clients() {
65         return new ArrayList<>(mr_clients.values());
66     }
67
68     List<MR_Client> getAllMrClients(String fqtn) {
69         ArrayList<MR_Client> results = new ArrayList<>();
70         for (Map.Entry<String, MR_Client> entry : mr_clients.entrySet()) {
71             MR_Client client = entry.getValue();
72             if (fqtn.equals(client.getFqtn())) {
73                 results.add(client);
74             }
75         }
76         return results;
77     }
78
79     List<MR_Client> getClientsByLocation(String location) {
80         List<MR_Client> results = new ArrayList<>();
81         for (Map.Entry<String, MR_Client> entry : mr_clients.entrySet()) {
82             MR_Client client = entry.getValue();
83             if (location.equals(client.getDcaeLocationName())) {
84                 results.add(client);
85             }
86         }
87         return results;
88     }
89
90
91     public MR_Client getMr_Client(String key, ApiError apiError) {
92         MR_Client c = mr_clients.get(key);
93         if (c == null) {
94             apiError.setCode(Status.NOT_FOUND.getStatusCode());
95             apiError.setFields(MR_CLIENT_ID);
96             apiError.setMessage(MR_CLIENT_ID + " " + key + " not found");
97         } else {
98             apiError.setCode(200);
99         }
100         return c;
101     }
102
103     public MR_Client addMr_Client(MR_Client client, Topic topic, ApiError err) {
104         if (client.getDcaeLocationName().isEmpty()) {
105             logger.info("Client  dcaeLocation that doesn't exist or not specified");
106             return null;
107         }
108         // original style: clients specified Role.  This has precedence for backwards
109         //                 compatibility.
110         // ONAP style: clients specify Identity to be assigned to generated Role
111         String role = client.getClientRole();
112         if (role != null) {
113             grantClientRolePerms(client, err);
114         } else if (client.hasClientIdentity()) {
115             if (client.isSubscriber()) {
116                 role = topic.getSubscriberRole();
117                 assignIdentityToRole(client, role, err);
118             }
119             if (client.isPublisher()) {
120                 role = topic.getPublisherRole();
121                 assignIdentityToRole(client, role, err);
122             }
123         }
124         if (!client.isStatusValid()) {
125             return null;
126         }
127         String centralFqdn = null;
128         DcaeLocation candidate = locations.get(client.getDcaeLocationName());
129
130         MR_Cluster cluster = clusters.get(client.getDcaeLocationName());
131         if (cluster != null && candidate != null) {
132             if (candidate.isCentral() && !topic.getReplicationCase().involvesFQDN()) {
133                 centralFqdn = centralCname;
134             }
135             client.setTopicURL(cluster.genTopicURL(centralFqdn, client.getFqtn()));
136             if (centralFqdn == null) {
137                 client.setStatus(addTopicToCluster(cluster, topic, err));
138                 if (!err.is2xx() && err.getCode() != 409) {
139                     topic.setFqtn(err.getMessage());
140                     return null;
141                 }
142
143             } else {
144                 MR_ClusterService clusters = new MR_ClusterService();
145                 //  MM should only exist for edge-to-central
146                 //  we use a cname for the central target (default resiliency with no replicationGroup set)
147                 // but still need to provision topics on all central MRs
148                 for (MR_Cluster central : clusters.getCentralClusters()) {
149                     client.setStatus(addTopicToCluster(central, topic, err));
150                     if (!err.is2xx() && err.getCode() != 409) {
151                         topic.setFqtn(err.getMessage());
152                         return null;
153                     }
154                 }
155             }
156
157         } else {
158             logger.warn("Client references a dcaeLocation that doesn't exist:" + client.getDcaeLocationName());
159             client.setStatus(DmaapObject_Status.STAGED);
160         }
161
162         mr_clients.put(client.getMrClientId(), client);
163
164         err.setCode(200);
165
166         return client;
167     }
168
169     private DmaapObject_Status addTopicToCluster(MR_Cluster cluster, Topic topic, ApiError err) {
170
171         MrProvConnection prov = new MrProvConnection();
172         logger.info("POST topic " + topic.getFqtn() + " to cluster " + cluster.getFqdn() + " in loc " + cluster.getDcaeLocationName());
173         if (prov.makeTopicConnection(cluster)) {
174             prov.doPostTopic(topic, err);
175             logger.info("response code: " + err.getCode());
176             if (err.is2xx() || err.getCode() == 409) {
177                 return DmaapObject_Status.VALID;
178             }
179         }
180         return DmaapObject_Status.INVALID;
181     }
182
183     private void grantClientRolePerms(MR_Client client, ApiError err) {
184         AafService aaf = new AafServiceImpl(ServiceType.AAF_TopicMgr);
185
186         String instance = ":topic." + client.getFqtn();
187         client.setStatus(DmaapObject_Status.VALID);
188         String role = client.getClientRole();
189         for (String want : client.getAction()) {
190             int rc;
191             DmaapPerm perm = new DmaapPerm(dmaap.getTopicPerm(), instance, want);
192             if (role != null) {
193                 DmaapGrant g = new DmaapGrant(perm, role);
194                 rc = aaf.addGrant(g);
195                 if (rc != 201 && rc != 409) {
196                     client.setStatus(DmaapObject_Status.INVALID);
197                     err.setCode(rc);
198                     err.setMessage("Grant of " + dmaap.getTopicPerm() + "|" + instance + "|" + want + " failed for " + role);
199                     logger.warn(err.getMessage());
200                     return;
201                 }
202             } else {
203                 logger.warn("No Grant of " + dmaap.getTopicPerm() + "|" + instance + "|" + want + " because role is null ");
204             }
205         }
206     }
207
208     private void assignIdentityToRole(MR_Client client, String role, ApiError err) {
209         AafService aaf = new AafServiceImpl(ServiceType.AAF_TopicMgr);
210
211         AafUserRole ur = new AafUserRole(client.getClientIdentity(), role);
212         int rc = aaf.addUserRole(ur);
213         if (rc != 201 && rc != 409) {
214             client.setStatus(DmaapObject_Status.INVALID);
215             err.setCode(rc);
216             err.setMessage("Failed to add user " + client.getClientIdentity() + "  to " + role);
217             logger.warn(err.getMessage());
218             return;
219         }
220         client.setStatus(DmaapObject_Status.VALID);
221
222     }
223
224     private void revokeClientPerms(MR_Client client, ApiError err) {
225         AafService aaf = new AafServiceImpl(ServiceType.AAF_TopicMgr);
226
227         String instance = ":topic." + client.getFqtn();
228         client.setStatus(DmaapObject_Status.VALID);
229         for (String want : client.getAction()) {
230             int rc;
231             DmaapPerm perm = new DmaapPerm(dmaap.getTopicPerm(), instance, want);
232             DmaapGrant g = new DmaapGrant(perm, client.getClientRole());
233             rc = aaf.delGrant(g);
234             if (rc != 200 && rc != 404) {
235                 client.setStatus(DmaapObject_Status.INVALID);
236                 err.setCode(rc);
237                 err.setMessage("Revoke of " + dmaap.getTopicPerm() + "|" + instance + "|" + want + " failed for " + client.getClientRole());
238                 logger.warn(err.getMessage());
239                 return;
240             }
241         }
242     }
243
244     public MR_Client updateMr_Client(MR_Client client, ApiError apiError) {
245         MR_Client c = mr_clients.get(client.getMrClientId());
246         if (c == null) {
247             apiError.setCode(Status.NOT_FOUND.getStatusCode());
248             apiError.setFields(MR_CLIENT_ID);
249             apiError.setMessage("mrClientId " + client.getMrClientId() + " not found");
250         } else {
251             apiError.setCode(200);
252         }
253         mr_clients.put(client.getMrClientId(), client);
254         return client;
255     }
256
257     public void removeMr_Client(String key, boolean updateTopicView, ApiError apiError) {
258         MR_Client client = mr_clients.get(key);
259         if (client == null) {
260             apiError.setCode(Status.NOT_FOUND.getStatusCode());
261             apiError.setFields(MR_CLIENT_ID);
262             apiError.setMessage("mrClientId " + key + " not found");
263             return;
264         } else {
265             apiError.setCode(200);
266         }
267
268         if (updateTopicView) {
269
270             TopicService topics = new TopicService();
271
272             Topic t = topics.getTopic(client.getFqtn(), apiError);
273             if (t != null) {
274                 List<MR_Client> tc = t.getClients();
275                 for (MR_Client c : tc) {
276                     if (c.getMrClientId().equals(client.getMrClientId())) {
277                         tc.remove(c);
278                         break;
279                     }
280                 }
281                 t.setClients(tc);
282                 topics.updateTopic(t, apiError);
283             }
284
285         }
286
287         // remove from AAF
288         if (deleteLevel >= 2) {
289             revokeClientPerms(client, apiError);
290             if (!apiError.is2xx()) {
291                 return;
292             }
293         }
294         // remove from DB
295         if (deleteLevel >= 1) {
296             mr_clients.remove(key);
297         }
298     }
299
300 }