def untag_asset(tag_id, asset_id, asset_type, organization_id, commit=True): """ Remove the tag with the tag_id and organization_id from the asset with the given asset_type ("device" or "gateway") and asset_id (device_id or gateway_id). """ if not is_from_organization(tag_id, organization_id): raise Error.Forbidden( "Trying to delete a tag from other organization.") if asset_type == "device": if not DeviceRepository.is_from_organization(asset_id, organization_id): raise Error.Forbidden( "Trying to untag a device from other organization") asset_tag = db.session.query(DeviceToTag).\ filter(DeviceToTag.tag_id==tag_id, DeviceToTag.device_id==asset_id).first() if asset_tag: db.session.delete(asset_tag) elif asset_type == "gateway": if not GatewayRepository.is_from_organization(asset_id, organization_id): raise Error.Forbidden( "Trying to untag a gateway from other organization") asset_tag = db.session.query(GatewayToTag).\ filter(GatewayToTag.tag_id==tag_id, GatewayToTag.gateway_id==asset_id).first() if asset_tag: db.session.delete(asset_tag) else: raise Error.BadRequest(f"Invalid asset_type: {asset_type}") if commit: db.session.commit()
def tag_asset(tag_id, asset_id, asset_type, organization_id, commit=True): """ Tag the asset with the given asset_type ("device" or "gateway") and asset_id (device_id or gateway_id) with the tag with tag_id and organization_id. """ if not is_from_organization(tag_id, organization_id): raise Error.Forbidden("Trying to use a tag from other organization.") if is_tagged(tag_id, asset_id, asset_type): return if asset_type == "device": if not DeviceRepository.is_from_organization(asset_id, organization_id): raise Error.Forbidden( "Trying to tag a device from other organization") asset_tag = DeviceToTag(tag_id=tag_id, device_id=asset_id) db.session.add(asset_tag) elif asset_type == "gateway": if not GatewayRepository.is_from_organization(asset_id, organization_id): raise Error.Forbidden( "Trying to tag a gateway from other organization") asset_tag = GatewayToTag(tag_id=tag_id, gateway_id=asset_id) db.session.add(asset_tag) else: raise Error.BadRequest(f"Invalid asset_type: {asset_type}") if commit: db.session.commit()
def wrapper(*args,**kwargs): verify_jwt_in_request() claims = get_jwt_claims() try: user_roles = [UserRole.find_by_id(user_role_id).role_name for user_role_id in claims.get('user_roles_id')] except AttributeError: raise Error.Forbidden("Couldn't load user roles") if RoleTypes.System.value in user_roles: raise Error.Forbidden("User must have regular or admin role to access this endpoint") else: return fn(*args,**kwargs)
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 create(keys_list, organization_id): """ Create a new app_key for every key in keys_list that is not already part of this organizantion's set of keys. """ global MAX_PER_ORGANIZATION already_in_db = set(row.key for row in get_with(organization_id=organization_id, keys_list=keys_list)) added_keys = [] for key in keys_list: if key not in already_in_db: db.session.add(AppKey(key=key, organization_id=organization_id)) already_in_db.add(key) added_keys.append(key) db.session.commit() created = len(added_keys) total = count_with(organization_id=organization_id) if total > MAX_PER_ORGANIZATION: try: delete(keys_list=added_keys, organization_id=organization_id) except Exception as e: log.warning( f"Error {e} on delete added keys after max app keys limit exceeded for organization with id {organization_id}" ) return created raise Error.Forbidden( "Creating these app keys would exceed the limit per organization") return created
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 list_asset_tags(asset_id, asset_type, organization_id): if asset_type == "device": if not DeviceRepository.is_from_organization(asset_id, organization_id): raise Error.Forbidden( "Trying to list tags from a device from other organization") return db.session.query(Tag).\ join(DeviceToTag).\ filter(DeviceToTag.device_id == asset_id).all() elif asset_type == "gateway": if not GatewayRepository.is_from_organization(asset_id, organization_id): raise Error.Forbidden( "Trying to list tags from a gateway from other organization") return db.session.query(Tag).\ join(GatewayToTag).\ filter(GatewayToTag.gateway_id == asset_id).all() else: raise Error.BadRequest(f"Invalid asset_type: {asset_type}")
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 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 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 = 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 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 get_with(asset_id, asset_type, organization_id=None): """ Gets an asset from database Request parameters: - asset_id: database id of the asset - asset_type: type of the requested asset, can be "device" or "gateway". - organization_id (optional): when given, asserts that received organization matchs the asset's organization Returns: - Model object of requested asset """ if asset_type == "device": asset = Device.query.get(asset_id) if not asset: raise Error.NotFound( f"Asset with id {asset_id} and type {asset_type} not found") device_session = db.session.query(DeviceSession).\ filter(DeviceSession.device_id==asset_id).\ order_by(DeviceSession.last_activity.desc()).\ first() asset.dev_addr = device_session.dev_addr if device_session else None asset.hex_id = asset.dev_eui elif asset_type == "gateway": asset = db.session.query(Gateway).\ filter(Gateway.id == asset_id).\ first() if not asset: raise Error.NotFound( f"Asset with id {asset_id} and type {asset_type} not found") asset.hex_id = asset.gw_hex_id else: raise Error.BadRequest( f"Invalid asset_type: {asset_type}. Valid values are \'device\' or \'gateway\'" ) if organization_id and asset.organization_id != organization_id: raise Error.Forbidden( "User's organization's different from asset organization") asset.type = asset_type return asset
def get_with(asset_id, asset_type, organization_id=None): """ Gets an asset from database Request parameters: - asset_id: database id of the asset - asset_type: type of the requested asset, can be "device" or "gateway". - organization_id (optional): when given, asserts that received organization matchs the asset's organization Returns: - Model object of requested asset """ if asset_type == "device": asset_query = db.session.query( Device.id, Device.organization_id, Device.dev_eui.label('hex_id'), expression.literal_column('\'Device\'').label('type'), Device.name, Device.app_name, DataCollector.name.label('data_collector'), PolicyItem.parameters.label('policy_parameters'), Device.connected.label('connected'), Device.last_activity, Device.activity_freq, Device.activity_freq_variance, Device.npackets_up, Device.npackets_down, Device.npackets_lost.label('packet_loss'), Device.max_rssi, Device.max_lsnr, Device.ngateways_connected_to, Device.payload_size, Device.last_packets_list ).filter(Device.id == asset_id).\ join(DataCollector, Device.data_collector_id == DataCollector.id).\ join(Policy, Policy.id == DataCollector.policy_id).\ join(PolicyItem, and_(Policy.id == PolicyItem.policy_id, PolicyItem.alert_type_code == 'LAF-401')).\ join(RowProcessed, RowProcessed.analyzer == 'packet_analyzer').\ join(Packet, Packet.id == RowProcessed.last_row).\ join(DeviceCounters, and_( DeviceCounters.device_id == Device.id, DeviceCounters.counter_type.in_(dev_wanted_counters), DeviceCounters.last_update + func.make_interval(0,0,0,1) > Packet.date ), isouter=True).\ group_by(Device.id, DataCollector.name, PolicyItem.parameters) asset_query = add_counters_columns(asset_query, dev_wanted_counters, DeviceCounters) asset = asset_query.first() elif asset_type == "gateway": asset_query = db.session.query( Gateway.id, Gateway.organization_id, Gateway.gw_hex_id.label('hex_id'), expression.literal_column('\'Gateway\'').label('type'), Gateway.name, expression.null().label('app_name'), DataCollector.name.label('data_collector'), expression.null().label('policy_parameters'), Gateway.connected.label('connected'), Gateway.last_activity, Gateway.activity_freq, cast(expression.null(), Float).label('activity_freq_variance'), Gateway.npackets_up, Gateway.npackets_down, cast(expression.null(), Float).label('packet_loss'), cast(expression.null(), Float).label('max_rssi'), cast(expression.null(), Float).label('max_lsnr'), cast(expression.null(), Float).label('ngateways_connected_to'), cast(expression.null(), Float).label('payload_size'), expression.null().label('last_packets_list') ).filter(Gateway.id == asset_id).\ join(DataCollector, Gateway.data_collector_id == DataCollector.id).\ join(RowProcessed, RowProcessed.analyzer == 'packet_analyzer').\ join(Packet, Packet.id == RowProcessed.last_row).\ join(GatewayCounters, and_( GatewayCounters.gateway_id == Gateway.id, GatewayCounters.counter_type.in_(gtw_wanted_counters), GatewayCounters.last_update + func.make_interval(0,0,0,1) > Packet.date ), isouter=True).\ group_by(Gateway.id, DataCollector.name) asset_query = add_counters_columns(asset_query, gtw_wanted_counters, GatewayCounters) asset = asset_query.first() else: raise Error.BadRequest( f"Invalid asset_type: {asset_type}. Valid values are \'device\' or \'gateway\'" ) if not asset: raise Error.NotFound( f"Asset with id {asset_id} and type {asset_type} not found") if organization_id and asset.organization_id != organization_id: raise Error.Forbidden( "User's organization's different from asset organization") return asset