def delete(self): user = User.find_by_username(get_jwt_identity()) if not user or is_system(user.id): raise Error.Forbidden("User not allowed") organization_id = user.organization_id body = json.loads(request.data) parsed_result = AppKeysSchema().load(body).data app_keys = parsed_result.get('keys') if app_keys is None: raise Error.BadRequest( f"AppKeysAPI POST request body must contain a non-empty list of keys with at most {MAX_PER_ORGANIZATION} keys" ) app_keys = [key.upper() for key in app_keys] total = len(app_keys) app_keys = list(set(app_keys)) not_duplicated = len(app_keys) validate_keys(app_keys) deleted = AppKeysRepository.delete(keys_list=app_keys, organization_id=organization_id) return { "message": f"{deleted} app keys deleted, {total-not_duplicated} were duplicated and {not_duplicated-deleted} were not present in user's organization" }, 200
def patch(self, tag_id): user = User.find_by_username(get_jwt_identity()) if not user or is_system(user.id): raise Error.Forbidden("User not allowed") organization_id = user.organization_id name = request.args.get('name', type=str, default=None) color = request.args.get('color', type=str, default=None) previous_tag = TagRepository.get_with(tag_id, organization_id) tag_list = TagRepository.list_all( organization_id=organization_id ) if name in (tag.name for tag in tag_list) and name != previous_tag.name: return [{'code': 'EXISTING_NAME', 'message': 'Existing tag with that name'}], 400 TagRepository.update( tag_id=tag_id, name=name, color=color, organization_id=organization_id) return {"message": "Tag updated"}, 200
def get(self): user_identity = get_jwt_identity() user = User.find_by_username(user_identity) organization_id = user.organization_id if not user or not organization_id or not is_admin_user( user.id) and not is_regular_user(user.id): return {}, 403 page = request.args.get('page', default=1, type=int) size = request.args.get('size', default=20, type=int) result = Policy.find(organization_id, None, None, page, size) headers = {'total-pages': result.pages, 'total-items': result.total} for policy in result.items: PolicyRepository.update_items(policy) existing_type_codes = [ item.alert_type_code for item in policy.items ] PolicyRepository.add_missing_items(policy.id, existing_type_codes) Policy.add_data_collectors(organization_id=organization_id, policies=result.items) policies = [policy.to_dict() for policy in result.items] return policies, 200, headers
def delete(self, id): user_identity = get_jwt_identity() user = User.find_by_username(user_identity) organization_id = user.organization_id if not user or not organization_id or not is_admin_user(user.id): return [], 403 policy = Policy.find_one(id) if not policy: return None, 404 if policy.is_default: return [{ 'code': 'DEFAULT_POLICY', 'message': 'Can\'t delete default policy.' }], 403 if policy.organization_id != organization_id: return [{ 'code': 'FORBIDDEN', 'message': 'Can\'t delete the policy.' }], 403 if DataCollector.count(organization_id, policy.id) > 0: return [{ 'code': 'POLICY_WITH_DATA_COLLECTORS', 'message': 'Can\'t delete policy with data collectors.' }], 403 policy.delete() emit_policy_event('DELETED', {'id': id}) return {}, 204
def delete(self, id): user_identity = get_jwt_identity() user = User.find_by_username(user_identity) notification = Notification.find_one(id) if notification.user_id != user.id: return None, 403 notification.delete() return None, 204
def delete(self, tag_id): user = User.find_by_username(get_jwt_identity()) if not user or is_system(user.id): raise Error.Forbidden("User not allowed") organization_id = user.organization_id TagRepository.delete( tag_id=tag_id, organization_id=organization_id ) return {"message": "Tag deleted"}, 200
def handle_authorization(message): token = message.get('token') decoded_token = decode_token(token, allow_expired=True) identity = decoded_token.get('identity') user = User.find_by_username(identity) organization = user.organization_id join_room(organization) data = NotificationData.find_one(user.id) if data: data.ws_sid = request.sid data.update()
def get(self, tag_id): user = User.find_by_username(get_jwt_identity()) if not user or is_system(user.id): raise Error.Forbidden("User not allowed") organization_id = user.organization_id tag = TagRepository.get_with( tag_id=tag_id, organization_id=organization_id ) return {"id": tag.id, "name": tag.name, "color": tag.color}, 200
def get(self): user_identity = get_jwt_identity() user = User.find_by_username(user_identity) notification_data = NotificationData.find_one(user.id) if notification_data: _from = notification_data.last_read else: _from = None count = Notification.count(user.id, _from) return {'count': count}
def get(self): user = User.find_by_username(get_jwt_identity()) if not user or is_system(user.id): raise Error.Forbidden("User not allowed") organization_id = user.organization_id tag_list = TagRepository.list_all( organization_id=organization_id ) return [{ "id" : tag.id, "name" : tag.name, "color": tag.color } for tag in tag_list], 200
def get(self): user_identity = get_jwt_identity() user = User.find_by_username(user_identity) organization_id = user.organization_id if not user or not organization_id or not is_admin_user( user.id) and not is_regular_user(user.id): return None, 403 min_date = datetime.today() - timedelta(hours=4) result = Packet.find_max_by_organization_id(organization_id, min_date) response = list( map( lambda item: { 'dataCollectorId': item.data_collector_id, 'maxDate': "{}".format(item.date) }, result)) return response, 200
def get(self): user = User.find_by_username(get_jwt_identity()) if not user or is_system(user.id): raise Error.Forbidden("User not allowed") organization_id = user.organization_id app_keys = AppKeysRepository.get_with(organization_id=organization_id) return { "limit": MAX_PER_ORGANIZATION, "count": len(app_keys), "keys": [{ "id": app_key.id, "key": app_key.key, "organization_id": app_key.organization_id } for app_key in app_keys] }, 200
def patch(self, id): user_identity = get_jwt_identity() user = User.find_by_username(user_identity) notification = Notification.find_one(id) if notification.user_id != user.id: return None, 403 body = json.loads(request.data) read_at = None if body.get('readAt') is not None: try: read_at = dateparser.parse(body.get('readAt')) except Exception: return {'error': 'Bad value for readAt field'}, 400 notification.read_at = read_at Notification.commit() return notification.to_dict(), 200
def delete(self, tag_id): user = User.find_by_username(get_jwt_identity()) if not user or is_system(user.id): return abort(403, error='forbidden access') organization_id = user.organization_id asset_list = TagAssetsAPI.parser.parse_args()["asset_list"] for asset in asset_list: asset = json.loads(asset.replace("\'", "\"")) TagRepository.untag_asset( tag_id=tag_id, asset_id=int(asset["asset_id"]), asset_type=asset["asset_type"], organization_id=organization_id, commit=False ) db.session.commit() return {"message": "Asset untagged"}, 200
def get(self, data_collector_id): user_identity = get_jwt_identity() user = User.find_by_username(user_identity) data_collector = DataCollector.find_by_id(data_collector_id) if not data_collector: return None, 404 if not user or data_collector.organization_id != user.organization_id or not is_admin_user( user.id) and not is_regular_user(user.id): return [], 403 page = request.args.get('page', default=1, type=int) size = request.args.get('size', default=20, type=int) result = DataCollectorLogEvent.find(data_collector_id, page, size) headers = {'total-pages': result.pages, 'total-items': result.total} events = [event.to_dict() for event in result.items] return events, 200, headers
def get(self, id): user_identity = get_jwt_identity() user = User.find_by_username(user_identity) organization_id = user.organization_id if not user or not organization_id or not is_admin_user( user.id) and not is_regular_user(user.id): return [], 403 policy = Policy.find_one(id, organization_id) if not policy: return None, 404 if policy.organization_id is not None and policy.organization_id != organization_id: return [{ 'code': 'FORBIDDEN', 'message': 'Can\'t fetch the policy.' }], 403 return policy.to_dict()
def get(self): user_identity = get_jwt_identity() user = User.find_by_username(user_identity) if not user: return None, 403 page = request.args.get('page', default=1, type=int) size = request.args.get('size', default=20, type=int) result = Notification.find(user.id, page, size) headers = {'total-pages': result.pages, 'total-items': result.total} notifications = [notification.to_dict() for notification in result.items] notification_data = NotificationData.find_one(user.id) if notification_data: notification_data.last_read = datetime.now() notification_data.update() else: NotificationData(user_id = user.id, last_read = datetime.now()).save() return notifications, 200, headers
def post(self): user = User.find_by_username(get_jwt_identity()) if not user or is_system(user.id): raise Error.Forbidden("User not allowed") organization_id = user.organization_id name = request.args.get('name', type=str) color = request.args.get('color', type=str) tag_list = TagRepository.list_all( organization_id=organization_id ) if name in (tag.name for tag in tag_list): return [{'code': 'EXISTING_NAME', 'message': 'Existing tag with that name'}], 400 tag = TagRepository.create( name=name, color=color, organization_id=organization_id ) return {"id": tag.id, "name": tag.name, "color": tag.color}, 200
def post(self): user = User.find_by_username(get_jwt_identity()) if not user or is_system(user.id): raise Error.Forbidden("User not allowed") organization_id = user.organization_id args = self.parser.parse_args() asset_list = args["asset_list"] importance = args["importance"] if importance not in ['LOW', 'MEDIUM', 'HIGH']: raise Exception(f'"{importance}" is not a valid importance value') for asset_id in asset_list: asset_id = json.loads(asset_id.replace("\'", "\"")) asset = AssetRepository.get_with(asset_id=int( asset_id["asset_id"]), asset_type=asset_id["asset_type"], organization_id=organization_id) asset.importance = importance db.session.commit() return {"message": "Assets importance set"}, 200
def handle_alert_events(ch, method, properties, body): event = None try: event = json.loads(body) except Exception: LOG.error("Couldn't deserialize event") if not event: return alert_id = event.get('alert_id') organization_id = event.get('organization_id') data_collector_id = event.get('data_collector_id') event_type = event.get('event_type') alert_type_code = event.get('alert_type') phones = [] emails = [] if event_type == 'NEW': alert_type = AlertType.find_one(alert_type_code) users = User.find_all_user_by_organization_id(organization_id) users = list( filter( lambda x: (x.blocked == False and x.deleted == False and x. active == True), users)) emit_alert_event({'alert_id': alert_id}, organization_id) try: alert = Alert.find_one(alert_id) device = None gateway = None if alert and alert.device_id: device = AssetRepository.get_with(alert.device_id, "device") if alert and alert.gateway_id: gateway = AssetRepository.get_with(alert.gateway_id, "gateway") except Exception as e: LOG.error( f"Error {e} on alert assets search {alert}. Ignoring device/gateway related preferences" ) device = None gateway = None for user in users: alert_settings = NotificationAlertSettings.find_one(user.id) dc_settings = NotificationDataCollectorSettings.find_one( user_id=user.id, data_collector_id=data_collector_id) preferences = NotificationPreferences.find_one(user.id) # Check whether the alert assets are important for the user or not try: asset_importance = NotificationAssetImportance.get_with( user.id) is_important_for_user = False if asset_importance and device is not None: is_important_for_user = getattr( asset_importance, device.importance.value.lower()) elif asset_importance: is_important_for_user = getattr( asset_importance, gateway.importance.value.lower()) except Exception as e: LOG.error( f"Error {e} on NotificationAssetImportance search for user {user.id}. Ignoring asset_importance preference" ) is_important_for_user = True # Check whether the alert assets contain all the tags in user notification preferences or not try: asset_tags = NotificationAssetTag.find_all_with( user_id=user.id) tag_id_list = [asset_tag.tag_id for asset_tag in asset_tags] if device: has_all_tags = DeviceRepository.has_all_tags( device.id, tag_id_list) elif gateway: has_all_tags = GatewayRepository.has_all_tags( gateway.id, tag_id_list) except Exception as e: LOG.error( f"Error {e} on handling NotificationAssetTag preferences for user {user.id}. Ignoring this preference" ) has_all_tags = True if alert_settings and getattr( alert_settings, alert_type.risk.lower() ) and is_important_for_user and has_all_tags and dc_settings and dc_settings.enabled: data = NotificationData.find_one(user.id) notification = Notification(type='NEW_ALERT', alert_id=alert_id, user_id=user.id, created_at=datetime.now()) notification.save() if data and data.ws_sid and preferences and preferences.push: emit_notification_event(notification.to_dict(), data.ws_sid) if preferences: if preferences.sms: if user.phone and not user.phone in phones: phones.append(user.phone) additional = NotificationAdditionalTelephoneNumber.find( user_id=user.id) for item in additional: if item.active and not item.phone in phones: phones.append(item.phone) if preferences.email: if user.email and not user.email in emails: emails.append(user.email) additional = NotificationAdditionalEmail.find( user_id=user.id) for item in additional: if item.active and not item.email in emails: emails.append(item.email) # Send a SMS message to the specified phone number for phone in phones: if config.SEND_SMS: sns.publish( PhoneNumber=phone, Message= f'New notification from {config.BRAND_NAME}. There\'s a new alert: {alert_type.name}. You can check this accessing to {config.BRAND_URL}', ) if len(emails) > 0: with app.app_context(): msg = MIMEMultipart('alternative') msg['Subject'] = f"New {config.BRAND_NAME} Notification" msg['From'] = email.utils.formataddr( (config.SMTP_SENDER_NAME, config.SMTP_SENDER)) part = MIMEText( render_template('notification.html', brand_name=config.BRAND_NAME, full_url=config.BRAND_URL, alert_type=alert_type.name), 'html') msg.attach(part) server = smtplib.SMTP(config.SMTP_HOST, config.SMTP_PORT) #server.set_debuglevel(1) server.ehlo() server.starttls() #stmplib docs recommend calling ehlo() before & after starttls() server.ehlo() server.login(config.SMTP_USERNAME, config.SMTP_PASSWORD) for email_user in emails: try: msg['To'] = email_user server.sendmail(config.SMTP_SENDER, email_user, msg.as_string()) except Exception as exc: server.close() print(exc) server.close()
def post(self): user_identity = get_jwt_identity() user = User.find_by_username(user_identity) organization_id = user.organization_id if not user or not organization_id or not is_admin_user(user.id): return {}, 403 body = json.loads(request.data) parsed_result = None try: parsed_result = PolicySchema().load(body) except ValidationError as err: return err.messages, 400 if len(parsed_result.errors.keys()) > 0: errors = [] for key in parsed_result.errors.keys(): errors.append(parsed_result.errors.get(key)) return errors, 400 # TODO Replace fetching the entity by something that issues an 'exists' query. if Policy.find(organization_id, parsed_result.data.get('name'), None).total > 0: return [{ 'code': 'EXISTING_NAME', 'message': 'Existing policy with that name' }], 400 items = parsed_result.data.get('items') # This validation is disabled temporarily - https://trello.com/c/QFsIQ7Yw # Bring validation back as part of https://trello.com/c/0VnmKErd # alert_types = AlertType.find_all() # errors = validate_items(alert_types, items) # if len(errors) > 0: # return errors, 400 try: policy = Policy(name=parsed_result.data.get('name'), organization_id=organization_id, is_default=False) policy.save() for item in items: policy_item = PolicyItem( alert_type_code=item.get('alert_type_code'), policy_id=policy.id, parameters=json.dumps(item.get('parameters')), enabled=item.get('enabled')) policy_item.save() Policy.commit() except Exception as exc: Policy.rollback() LOG.error( 'Something went wrong trying to add the policy.{0}'.format( exc)) return { 'message': 'Something went wrong trying to add the policy.' }, 500 res_body = policy.to_dict() emit_policy_event('CREATED', {'id': policy.id}) return res_body, 201
def put(self, id): user_identity = get_jwt_identity() user = User.find_by_username(user_identity) organization_id = user.organization_id if not user or not organization_id or not is_admin_user(user.id): return [], 403 policy = Policy.find_one(id) if not policy: return None, 404 if policy.is_default: return [{ 'code': 'DEFAULT_POLICY', 'message': 'Can\'t update default policy.' }], 403 if policy.organization_id != organization_id: return [{ 'code': 'FORBIDDEN', 'message': 'Can\'t delete the policy.' }], 403 body = json.loads(request.data) parsed_result = None try: parsed_result = UpdatedPolicySchema().load(body) except ValidationError as err: return err.messages, 400 if len(parsed_result.errors.keys()) > 0: return [parsed_result.errors], 400 # TODO Replace fetching the entity by something that issues an 'exists' query. if Policy.find(organization_id, parsed_result.data.get('name'), id).total > 0: return [{ 'code': 'EXISTING_NAME', 'message': 'Existing policy with that name' }], 400 items = parsed_result.data.get('items') # This validation is disabled temporarily - https://trello.com/c/QFsIQ7Yw # Bring validation back as part of https://trello.com/c/0VnmKErd # alert_types = AlertType.find_all() # errors = validate_items(alert_types, items) # if len(errors) > 0: # return errors, 400 try: policy.name = parsed_result.data.get('name') for item in items: policy_item = PolicyItem.find_one(item.get('id')) if policy_item.policy_id != id: raise Exception('An item does not belong to this policy') policy_item.alert_type_code = item.get('alert_type_code'), policy_item.parameters = json.dumps(item.get('parameters')), policy_item.enabled = item.get('enabled') Policy.commit() except Exception as exc: Policy.rollback() LOG.error( 'Something went wrong trying to add the policy.{0}'.format( exc)) return { 'message': 'Something went wrong trying to add the policy.' }, 500 res_body = policy.to_dict() emit_policy_event('UPDATED', {'id': id}) return res_body, 200