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.
19 from collections import Counter
22 from rest_framework import status
24 from catalog.packages import const
25 from catalog.pub.database.models import NsdmSubscriptionModel
26 from catalog.pub.exceptions import CatalogException, \
27 NsdmBadRequestException, NsdmDuplicateSubscriptionException, SubscriptionDoesNotExistsException
28 from catalog.pub.utils.values import ignore_case_get
30 logger = logging.getLogger(__name__)
32 PARAMSBASICKEYS = ["userName", "password"]
34 PARAMSOAUTH2CLIENTCREDENTIALSKEYS = ["clientId", "clientPassword",
38 def is_filter_type_equal(new_filter, existing_filter):
39 return Counter(list(set(new_filter))) == Counter(existing_filter)
42 class NsdmSubscription:
47 def query_single_subscription(self, subscription_id):
48 logger.debug("Start Query Subscription... ")
50 NsdmSubscriptionModel.objects.filter(
51 subscriptionid=subscription_id)
52 if not subscription.exists():
53 raise SubscriptionDoesNotExistsException(
54 "Subscription(%s) doesn't exist" % subscription_id)
55 logger.debug("Subscription found... ")
56 return self.fill_resp_data(subscription[0])
58 def delete_single_subscription(self, subscription_id):
59 logger.debug("Start Delete Subscription... ")
61 NsdmSubscriptionModel.objects.filter(
62 subscriptionid=subscription_id)
63 if not subscription.exists():
64 raise SubscriptionDoesNotExistsException(
65 "Subscription(%s) doesn't exist" % subscription_id)
67 logger.debug("Deleted Subscription... ")
69 def query_multi_subscriptions(self, query_params):
70 self.params = query_params
72 logger.debug("Start QueryMultiSubscriptions get --> "
73 "Check for filters in query params" % self.params)
74 for query, value in list(self.params.items()):
75 if query in const.NSDM_NOTIFICATION_FILTERS and value:
76 query_data[query + '__icontains'] = json.dumps(list(set(value)))
77 # Query the database with filter if the request
78 # has fields in request params, else fetch all records
80 subscriptions = NsdmSubscriptionModel.objects.filter(**query_data)
82 subscriptions = NsdmSubscriptionModel.objects.all()
83 if not subscriptions.exists():
84 raise SubscriptionDoesNotExistsException("Subscriptions doesn't exist")
85 return [self.fill_resp_data(subscription)
86 for subscription in subscriptions]
88 def check_callbackuri_connection(self):
89 logger.debug("Create Subscription --> Test Callback URI --"
90 "Sending GET request to %s" % self.callback_uri)
92 response = requests.get(self.callback_uri, timeout=2, verify=False)
93 if response.status_code != status.HTTP_204_NO_CONTENT:
94 raise CatalogException("callbackUri %s returns %s status "
95 "code." % (self.callback_uri,
96 response.status_code))
98 raise CatalogException("callbackUri %s didn't return 204 status"
99 "code." % self.callback_uri)
101 def fill_resp_data(self, subscription):
102 subscription_filter = dict()
103 for filter_type in const.NSDM_NOTIFICATION_FILTERS:
104 if subscription.__dict__[filter_type]:
105 subscription_filter[filter_type] = \
106 ast.literal_eval(subscription.__dict__[filter_type])
108 'id': subscription.subscriptionid,
109 'callbackUri': subscription.callback_uri,
110 'filter': subscription_filter,
111 '_links': json.loads(subscription.links)
115 def create(self, data):
116 logger.debug("Start Create Subscription... ")
117 self.filter = ignore_case_get(data, "filter", {})
118 self.callback_uri = ignore_case_get(data, "callbackUri")
119 self.authentication = ignore_case_get(data, "authentication", {})
120 self.subscription_id = str(uuid.uuid4())
121 self.check_callbackuri_connection()
122 self.check_valid_auth_info()
123 self.check_filter_types()
127 NsdmSubscriptionModel.objects.get(
128 subscriptionid=self.subscription_id)
129 return self.fill_resp_data(subscription)
131 def check_filter_types(self):
132 # Check if both nsdId and nsdInfoId
133 # or pnfdId and pnfdInfoId are present
134 logger.debug("Create Subscription --> Validating Filters... ")
136 self.filter.get("nsdId", "") and \
137 self.filter.get("nsdInfoId", ""):
138 raise NsdmBadRequestException("Notification Filter should contain"
139 " either nsdId or nsdInfoId")
141 self.filter.get("pnfdId", "") and \
142 self.filter.get("pnfdInfoIds", ""):
143 raise NsdmBadRequestException("Notification Filter should contain"
144 " either pnfdId or pnfdInfoIds")
146 def check_valid_auth_info(self):
147 logger.debug("Create Subscription --> Validating Auth "
148 "details if provided... ")
149 if self.authentication.get("paramsBasic", {}) and \
150 const.BASIC not in self.authentication.get("authType", ''):
151 raise NsdmBadRequestException('Auth type should be ' + const.BASIC)
152 if self.authentication.get("paramsOauth2ClientCredentials", {}) and \
153 const.OAUTH2_CLIENT_CREDENTIALS not in \
154 self.authentication.get("authType", ''):
155 raise NsdmBadRequestException('Auth type should '
156 'be ' + const.OAUTH2_CLIENT_CREDENTIALS)
157 if const.BASIC in self.authentication.get("authType", '') and \
158 "paramsBasic" in list(self.authentication.keys()) and \
159 not is_filter_type_equal(PARAMSBASICKEYS, list(
160 self.authentication.get("paramsBasic").keys())):
161 raise NsdmBadRequestException('userName and password needed '
162 'for ' + const.BASIC)
163 if const.OAUTH2_CLIENT_CREDENTIALS in \
164 self.authentication.get("authType", '') and \
165 "paramsOauth2ClientCredentials" in \
166 list(self.authentication.keys()) and \
167 not is_filter_type_equal(PARAMSOAUTH2CLIENTCREDENTIALSKEYS, list(
168 self.authentication.get("paramsOauth2ClientCredentials").keys())):
169 raise NsdmBadRequestException('clientId, clientPassword and '
170 'tokenEndpoint required '
171 'for ' + const.OAUTH2_CLIENT_CREDENTIALS)
173 def check_filter_exists(self, subscription):
174 for filter_type in const.NSDM_NOTIFICATION_FILTERS:
175 if not is_filter_type_equal(self.filter.get(filter_type, []),
177 getattr(subscription,
182 def check_valid(self):
183 logger.debug("Create Subscription --> Checking DB if "
184 "same subscription has already existed... ")
186 NsdmSubscriptionModel.objects.filter(
187 callback_uri=self.callback_uri)
188 if not subscriptions.exists():
190 for subscription in subscriptions:
191 if self.check_filter_exists(subscription):
192 raise NsdmDuplicateSubscriptionException(
193 "Subscription has already existed with the "
194 "same callbackUri and filter")
197 logger.debug("Create Subscription --> Saving the subscription "
198 "%s to the database" % self.subscription_id)
202 const.NSDM_SUBSCRIPTION_ROOT_URI + self.subscription_id
205 subscription_save_db = {
206 "subscriptionid": self.subscription_id,
207 "callback_uri": self.callback_uri,
208 "auth_info": json.dumps(self.authentication),
209 "links": json.dumps(links)
211 for filter_type in const.NSDM_NOTIFICATION_FILTERS:
213 subscription_save_db[filter_type] = json.dumps(
214 list(set(self.filter.get(filter_type, []))))
215 NsdmSubscriptionModel.objects.create(**subscription_save_db)
216 logger.debug('Create Subscription[%s] success', self.subscription_id)