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
Exemple #5
0
    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
Exemple #9
0
    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}
Exemple #10
0
    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
Exemple #13
0
    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
Exemple #14
0
    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
Exemple #15
0
    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()
Exemple #17
0
    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
Exemple #18
0
    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