1 # Copyright (C) 2019 Verizon. All Rights Reserved
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
21 from collections import Counter
23 from rest_framework import status
25 from catalog.packages import const
26 from catalog.pub.database.models import NsdmSubscriptionModel
27 from catalog.pub.exceptions import CatalogException, \
28 ResourceNotFoundException, \
29 NsdmBadRequestException, NsdmDuplicateSubscriptionException
30 from catalog.pub.utils.values import ignore_case_get
32 logger = logging.getLogger(__name__)
34 PARAMSBASICKEYS = ["userName", "password"]
36 PARAMSOAUTH2CLIENTCREDENTIALSKEYS = ["clientId", "clientPassword",
40 def is_filter_type_equal(new_filter, existing_filter):
41 return Counter(list(set(new_filter))) == Counter(existing_filter)
44 class NsdmSubscription:
49 def query_single_subscription(self, subscription_id):
50 logger.debug("Start Query Subscription... ")
52 NsdmSubscriptionModel.objects.filter(
53 subscriptionid=subscription_id)
54 if not subscription.exists():
55 raise ResourceNotFoundException(
56 "Subscription(%s) doesn't exists" % subscription_id)
57 logger.debug("Subscription found... ")
58 return self.fill_resp_data(subscription[0])
60 def delete_single_subscription(self, subscription_id):
61 logger.debug("Start Delete Subscription... ")
63 NsdmSubscriptionModel.objects.filter(
64 subscriptionid=subscription_id)
65 if not subscription.exists():
66 raise ResourceNotFoundException(
67 "Subscription(%s) doesn't exists" % subscription_id)
69 logger.debug("Deleted Subscription... ")
71 def query_multi_subscriptions(self, query_params):
72 self.params = query_params
74 logger.debug("Start QueryMultiSubscriptions get --> "
75 "Check for filters in query params" % self.params)
76 for query, value in list(self.params.items()):
77 if query in const.NSDM_NOTIFICATION_FILTERS and value:
78 query_data[query + '__icontains'] = json.dumps(list(set(value)))
79 # Query the database with filters if the request
80 # has fields in request params, else fetch all records
82 subscriptions = NsdmSubscriptionModel.objects.filter(**query_data)
84 subscriptions = NsdmSubscriptionModel.objects.all()
85 if not subscriptions.exists():
86 raise ResourceNotFoundException("Subscriptions doesn't exist")
87 return [self.fill_resp_data(subscription)
88 for subscription in subscriptions]
90 def check_callbackuri_connection(self):
91 logger.debug("Create Subscription --> Test Callback URI --"
92 "Sending GET request to %s" % self.callback_uri)
94 response = requests.get(self.callback_uri, timeout=2)
95 if response.status_code != status.HTTP_204_NO_CONTENT:
96 raise CatalogException("callbackUri %s returns %s status "
97 "code." % (self.callback_uri,
98 response.status_code))
100 raise CatalogException("callbackUri %s didn't return 204 status"
101 "code." % self.callback_uri)
103 def fill_resp_data(self, subscription):
104 subscription_filter = dict()
105 for filter_type in const.NSDM_NOTIFICATION_FILTERS:
106 if subscription.__dict__[filter_type]:
107 subscription_filter[filter_type] = \
108 ast.literal_eval(subscription.__dict__[filter_type])
110 'id': subscription.subscriptionid,
111 'callbackUri': subscription.callback_uri,
112 'filter': subscription_filter,
113 '_links': json.loads(subscription.links)
117 def create(self, data):
118 logger.debug("Start Create Subscription... ")
119 self.filter = ignore_case_get(data, "filter", {})
120 self.callback_uri = ignore_case_get(data, "callbackUri")
121 self.authentication = ignore_case_get(data, "authentication", {})
122 self.subscription_id = str(uuid.uuid4())
123 self.check_callbackuri_connection()
124 self.check_valid_auth_info()
125 self.check_filter_types()
129 NsdmSubscriptionModel.objects.get(
130 subscriptionid=self.subscription_id)
131 return self.fill_resp_data(subscription)
133 def check_filter_types(self):
134 # Check if both nsdId and nsdInfoId
135 # or pnfdId and pnfdInfoId are present
136 logger.debug("Create Subscription --> Validating Filters... ")
138 self.filter.get("nsdId", "") and \
139 self.filter.get("nsdInfoId", ""):
140 raise NsdmBadRequestException("Notification Filter should contain"
141 " either nsdId or nsdInfoId")
143 self.filter.get("pnfdId", "") and \
144 self.filter.get("pnfdInfoIds", ""):
145 raise NsdmBadRequestException("Notification Filter should contain"
146 " either pnfdId or pnfdInfoIds")
148 def check_valid_auth_info(self):
149 logger.debug("Create Subscription --> Validating Auth "
150 "details if provided... ")
151 if self.authentication.get("paramsBasic", {}) and \
152 const.BASIC not in self.authentication.get("authType", ''):
153 raise NsdmBadRequestException('Auth type should be ' + const.BASIC)
154 if self.authentication.get("paramsOauth2ClientCredentials", {}) and \
155 const.OAUTH2_CLIENT_CREDENTIALS not in \
156 self.authentication.get("authType", ''):
157 raise NsdmBadRequestException('Auth type should '
158 'be ' + const.OAUTH2_CLIENT_CREDENTIALS)
159 if const.BASIC in self.authentication.get("authType", '') and \
160 "paramsBasic" in list(self.authentication.keys()) and \
161 not is_filter_type_equal(PARAMSBASICKEYS, list(
162 self.authentication.get("paramsBasic").keys())):
163 raise NsdmBadRequestException('userName and password needed '
164 'for ' + const.BASIC)
165 if const.OAUTH2_CLIENT_CREDENTIALS in \
166 self.authentication.get("authType", '') and \
167 "paramsOauth2ClientCredentials" in \
168 list(self.authentication.keys()) and \
169 not is_filter_type_equal(PARAMSOAUTH2CLIENTCREDENTIALSKEYS, list(
170 self.authentication.get("paramsOauth2ClientCredentials").keys())):
171 raise NsdmBadRequestException('clientId, clientPassword and '
172 'tokenEndpoint required '
173 'for ' + const.OAUTH2_CLIENT_CREDENTIALS)
175 def check_filter_exists(self, subscription):
176 for filter_type in const.NSDM_NOTIFICATION_FILTERS:
177 if not is_filter_type_equal(self.filter.get(filter_type, []),
179 getattr(subscription,
184 def check_valid(self):
185 logger.debug("Create Subscription --> Checking DB if "
186 "same subscription exists already exists... ")
188 NsdmSubscriptionModel.objects.filter(
189 callback_uri=self.callback_uri)
190 if not subscriptions.exists():
192 for subscription in subscriptions:
193 if self.check_filter_exists(subscription):
194 raise NsdmDuplicateSubscriptionException(
195 "Already Subscription exists with the "
196 "same callbackUri and filter")
199 logger.debug("Create Subscription --> Saving the subscription "
200 "%s to the database" % self.subscription_id)
204 const.NSDM_SUBSCRIPTION_ROOT_URI + self.subscription_id
207 subscription_save_db = {
208 "subscriptionid": self.subscription_id,
209 "callback_uri": self.callback_uri,
210 "auth_info": self.authentication,
211 "links": json.dumps(links)
213 for filter_type in const.NSDM_NOTIFICATION_FILTERS:
215 subscription_save_db[filter_type] = json.dumps(
216 list(set(self.filter.get(filter_type, []))))
217 NsdmSubscriptionModel.objects.create(**subscription_save_db)
218 logger.debug('Create Subscription[%s] success', self.subscription_id)