868a336f27a1539113b3b167b7f44f3e436462ee
[ccsdk/oran.git] /
1 /*-
2  * ========================LICENSE_START=================================
3  * ONAP : ccsdk oran
4  * ======================================================================
5  * Copyright (C) 2024 OpenInfra Foundation Europe. 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.ccsdk.oran.a1policymanagementservice.service.v3;
22
23 import com.google.gson.Gson;
24 import lombok.RequiredArgsConstructor;
25 import org.onap.ccsdk.oran.a1policymanagementservice.clients.A1ClientFactory;
26 import org.onap.ccsdk.oran.a1policymanagementservice.controllers.authorization.PolicyAuthorizationRequest.Input.AccessType;
27 import org.onap.ccsdk.oran.a1policymanagementservice.controllers.v2.Consts;
28 import org.onap.ccsdk.oran.a1policymanagementservice.exceptions.EntityNotFoundException;
29 import org.onap.ccsdk.oran.a1policymanagementservice.exceptions.ServiceException;
30 import org.onap.ccsdk.oran.a1policymanagementservice.models.v3.PolicyInformation;
31 import org.onap.ccsdk.oran.a1policymanagementservice.models.v3.PolicyObjectInformation;
32 import org.onap.ccsdk.oran.a1policymanagementservice.models.v3.PolicyTypeInformation;
33 import org.onap.ccsdk.oran.a1policymanagementservice.repository.*;
34 import org.onap.ccsdk.oran.a1policymanagementservice.util.v3.Helper;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
37 import org.springframework.http.HttpStatus;
38 import org.springframework.http.ResponseEntity;
39 import org.springframework.stereotype.Service;
40 import org.springframework.web.server.ServerWebExchange;
41 import reactor.core.publisher.Flux;
42 import reactor.core.publisher.Mono;
43
44 import java.lang.invoke.MethodHandles;
45 import java.util.ArrayList;
46 import java.util.Collection;
47 import java.util.Map;
48
49 @Service
50 @RequiredArgsConstructor
51 public class PolicyService {
52
53     private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
54     private final Helper helper;
55     private final Rics rics;
56     private final PolicyTypes policyTypes;
57     private final Policies policies;
58     private final AuthorizationService authorizationService;
59     private final A1ClientFactory a1ClientFactory;
60     private final ErrorHandlingService errorHandlingService;
61     private final Gson gson;
62
63     public Mono<ResponseEntity<PolicyObjectInformation>> createPolicyService
64             (PolicyObjectInformation policyObjectInfo, ServerWebExchange serverWebExchange) {
65         try {
66             if (!helper.jsonSchemaValidation(gson.toJson(policyObjectInfo.getPolicyObject(), Map.class)))
67                 return Mono.error(new ServiceException("Schema validation failed", HttpStatus.BAD_REQUEST));
68             Ric ric = rics.getRic(policyObjectInfo.getNearRtRicId());
69             PolicyType policyType = policyTypes.getType(policyObjectInfo.getPolicyTypeId());
70             Policy policy = helper.buildPolicy(policyObjectInfo, policyType, ric, helper.policyIdGeneration(policyObjectInfo));
71             return helper.isPolicyAlreadyCreated(policy,policies)
72                     .doOnError(errorHandlingService::handleError)
73                     .flatMap(policyBuilt -> authorizationService.authCheck(serverWebExchange, policy, AccessType.WRITE)
74                     .doOnError(errorHandlingService::handleError)
75                     .flatMap(policyNotUsed -> ric.getLock().lock(Lock.LockType.SHARED, "createPolicy"))
76                     .flatMap(grant -> postPolicy(policy, grant))
77                     .map(locationHeaderValue ->
78                             new ResponseEntity<PolicyObjectInformation>(policyObjectInfo,helper.createHttpHeaders(
79                                     "location",helper.buildURI(policy.getId(), serverWebExchange)), HttpStatus.CREATED))
80                     .doOnError(errorHandlingService::handleError));
81         } catch (Exception ex) {
82             return Mono.error(ex);
83         }
84
85     }
86
87     private Mono<String> postPolicy(Policy policy, Lock.Grant grant) {
88         return  helper.checkRicStateIdle(policy.getRic())
89                 .doOnError(errorHandlingService::handleError)
90                 .flatMap(ric -> helper.checkSupportedType(ric, policy.getType()))
91                 .doOnError(errorHandlingService::handleError)
92                 .flatMap(a1ClientFactory::createA1Client)
93                 .flatMap(a1Client -> a1Client.putPolicy(policy))
94                 .doOnError(errorHandlingService::handleError)
95                 .doOnNext(policyString -> policies.put(policy))
96                 .doFinally(releaseLock -> grant.unlockBlocking())
97                 .doOnError(errorHandlingService::handleError);
98     }
99
100     public Mono<ResponseEntity<Object>> putPolicyService(String policyId, Object body, ServerWebExchange exchange) {
101         try {
102             Policy existingPolicy = policies.getPolicy(policyId);
103             PolicyObjectInformation pos =
104                     new PolicyObjectInformation(existingPolicy.getRic().getConfig().getRicId(), body, existingPolicy.getType().getId());
105             Policy updatedPolicy = helper.buildPolicy(pos, existingPolicy.getType(), existingPolicy.getRic(), policyId);
106             Ric ric = existingPolicy.getRic();
107             return authorizationService.authCheck(exchange, updatedPolicy, AccessType.WRITE)
108                     .doOnError(errorHandlingService::handleError)
109                     .flatMap(policy -> ric.getLock().lock(Lock.LockType.SHARED, "updatePolicy"))
110                     .doOnError(errorHandlingService::handleError)
111                     .flatMap(grant -> postPolicy(updatedPolicy, grant))
112                     .map(header -> new ResponseEntity<Object>(policies.get(updatedPolicy.getId()).getJson(), HttpStatus.OK))
113                     .doOnError(errorHandlingService::handleError);
114         } catch(Exception ex) {
115             return Mono.error(ex);
116         }
117     }
118
119     public Mono<ResponseEntity<Flux<PolicyTypeInformation>>> getPolicyTypesService(String nearRtRicId, String typeName,
120                                                                                    String compatibleWithVersion,
121                                                                                    ServerWebExchange webExchange) throws Exception {
122         if (compatibleWithVersion != null && typeName == null) {
123             throw new ServiceException("Parameter " + Consts.COMPATIBLE_WITH_VERSION_PARAM + " can only be used when "
124                     + Consts.TYPE_NAME_PARAM + " is given", HttpStatus.BAD_REQUEST);
125         }
126         Collection<PolicyTypeInformation> listOfPolicyTypes = new ArrayList<>();
127         if (nearRtRicId == null || nearRtRicId.isEmpty() || nearRtRicId.isBlank()) {
128             for(Ric ric : rics.getRics()) {
129                 Collection<PolicyType> policyTypes = PolicyTypes.filterTypes(ric.getSupportedPolicyTypes(), typeName,
130                         compatibleWithVersion);
131                 listOfPolicyTypes.addAll(helper.toPolicyTypeInfoCollection(policyTypes, ric));
132             }
133         } else {
134             Ric ric = rics.get(nearRtRicId);
135             if (ric == null)
136                 throw new EntityNotFoundException("Near-RT RIC not Found using ID: " +nearRtRicId);
137             Collection<PolicyType> policyTypes = PolicyTypes.filterTypes(ric.getSupportedPolicyTypes(), typeName,
138                     compatibleWithVersion);
139             listOfPolicyTypes.addAll(helper.toPolicyTypeInfoCollection(policyTypes, ric));
140         }
141         return Mono.just(new ResponseEntity<>(Flux.fromIterable(listOfPolicyTypes), HttpStatus.OK));
142     }
143
144     public Mono<ResponseEntity<Flux<PolicyInformation>>> getPolicyIdsService(String policyTypeId, String nearRtRicId,
145                                                                              String serviceId, String typeName,
146                                                                              ServerWebExchange exchange) throws EntityNotFoundException {
147         if ((policyTypeId != null && this.policyTypes.get(policyTypeId) == null))
148             throw new EntityNotFoundException("Policy type not found using ID: " +policyTypeId);
149         if ((nearRtRicId != null && this.rics.get(nearRtRicId) == null))
150             throw new EntityNotFoundException("Near-RT RIC not found using ID: " +nearRtRicId);
151
152         Collection<Policy> filtered = policies.filterPolicies(policyTypeId, nearRtRicId, serviceId, typeName);
153         return Flux.fromIterable(filtered)
154                 .flatMap(policy -> authorizationService.authCheck(exchange, policy, AccessType.READ))
155                 .onErrorContinue((error,item) -> logger.warn("Error occurred during authorization check for " +
156                         "policy {}: {}", item, error.getMessage()))
157                 .collectList()
158                 .map(authPolicies -> new ResponseEntity<>(helper.toFluxPolicyInformation(authPolicies), HttpStatus.OK))
159                 .doOnError(error -> logger.error(error.getMessage()));
160     }
161
162     public Mono<ResponseEntity<Object>> getPolicyService(String policyId, ServerWebExchange serverWebExchange)
163             throws EntityNotFoundException{
164             Policy policy = policies.getPolicy(policyId);
165         return authorizationService.authCheck(serverWebExchange, policy, AccessType.READ)
166                 .map(x -> new ResponseEntity<Object>(policy.getJson(), HttpStatus.OK))
167                 .doOnError(errorHandlingService::handleError);
168     }
169
170     public Mono<ResponseEntity<Object>> getPolicyTypeDefinitionService(String policyTypeId)
171             throws EntityNotFoundException{
172         PolicyType singlePolicyType = policyTypes.get(policyTypeId);
173         if (singlePolicyType == null)
174             throw new EntityNotFoundException("PolicyType not found with ID: " + policyTypeId);
175         return Mono.just(new ResponseEntity<Object>(singlePolicyType.getSchema(), HttpStatus.OK));
176     }
177
178     public Mono<ResponseEntity<Void>> deletePolicyService(String policyId, ServerWebExchange serverWebExchange)
179             throws EntityNotFoundException {
180         Policy singlePolicy = policies.getPolicy(policyId);
181         return authorizationService.authCheck(serverWebExchange, singlePolicy, AccessType.WRITE)
182                 .doOnError(errorHandlingService::handleError)
183                 .flatMap(policy -> policy.getRic().getLock().lock(Lock.LockType.SHARED, "deletePolicy"))
184                 .flatMap(grant -> deletePolicy(singlePolicy, grant))
185                 .doOnError(errorHandlingService::handleError);
186     }
187
188     private Mono<ResponseEntity<Void>> deletePolicy(Policy policy, Lock.Grant grant) {
189         return  helper.checkRicStateIdle(policy.getRic())
190                 .doOnError(errorHandlingService::handleError)
191                 .flatMap(ric -> helper.checkSupportedType(ric, policy.getType()))
192                 .doOnError(errorHandlingService::handleError)
193                 .flatMap(a1ClientFactory::createA1Client)
194                 .doOnError(errorHandlingService::handleError)
195                 .flatMap(a1Client -> a1Client.deletePolicy(policy))
196                 .doOnError(errorHandlingService::handleError)
197                 .doOnNext(policyString -> policies.remove(policy))
198                 .doFinally(releaseLock -> grant.unlockBlocking())
199                 .map(successResponse -> new ResponseEntity<Void>(HttpStatus.NO_CONTENT))
200                 .doOnError(errorHandlingService::handleError);
201     }
202 }