show only devices wb via api

This commit is contained in:
Cayo Puigdefabregas 2022-07-18 17:56:54 +02:00
parent a6c84ae588
commit 31abdf55e2
1 changed files with 72 additions and 41 deletions

View File

@ -3,28 +3,33 @@ import uuid
from itertools import filterfalse from itertools import filterfalse
import marshmallow import marshmallow
from flask import g, current_app as app, render_template, request, Response from flask import Response
from flask import current_app as app
from flask import g, render_template, request
from flask.json import jsonify from flask.json import jsonify
from flask_sqlalchemy import Pagination from flask_sqlalchemy import Pagination
from marshmallow import Schema as MarshmallowSchema
from marshmallow import fields
from marshmallow import fields as f
from marshmallow import validate as v
from sqlalchemy.util import OrderedSet from sqlalchemy.util import OrderedSet
from marshmallow import fields, fields as f, validate as v, Schema as MarshmallowSchema
from teal import query from teal import query
from teal.db import ResourceNotFound
from teal.cache import cache from teal.cache import cache
from teal.resource import View from teal.db import ResourceNotFound
from teal.marshmallow import ValidationError from teal.marshmallow import ValidationError
from teal.resource import View
from ereuse_devicehub import auth from ereuse_devicehub import auth
from ereuse_devicehub.db import db from ereuse_devicehub.db import db
from ereuse_devicehub.query import SearchQueryParser, things_response from ereuse_devicehub.query import SearchQueryParser, things_response
from ereuse_devicehub.resources import search from ereuse_devicehub.resources import search
from ereuse_devicehub.resources.action import models as actions from ereuse_devicehub.resources.action import models as actions
from ereuse_devicehub.resources.action.models import Trade
from ereuse_devicehub.resources.device import states from ereuse_devicehub.resources.device import states
from ereuse_devicehub.resources.device.models import Device, Manufacturer, Computer from ereuse_devicehub.resources.device.models import Computer, Device, Manufacturer
from ereuse_devicehub.resources.device.search import DeviceSearch from ereuse_devicehub.resources.device.search import DeviceSearch
from ereuse_devicehub.resources.enums import SnapshotSoftware from ereuse_devicehub.resources.enums import SnapshotSoftware
from ereuse_devicehub.resources.lot.models import LotDeviceDescendants from ereuse_devicehub.resources.lot.models import LotDeviceDescendants
from ereuse_devicehub.resources.action.models import Trade
from ereuse_devicehub.resources.tag.model import Tag from ereuse_devicehub.resources.tag.model import Tag
@ -61,15 +66,16 @@ class Filters(query.Query):
manufacturer = query.ILike(Device.manufacturer) manufacturer = query.ILike(Device.manufacturer)
serialNumber = query.ILike(Device.serial_number) serialNumber = query.ILike(Device.serial_number)
# todo test query for rating (and possibly other filters) # todo test query for rating (and possibly other filters)
rating = query.Join((Device.id == actions.ActionWithOneDevice.device_id) rating = query.Join(
& (actions.ActionWithOneDevice.id == actions.Rate.id), (Device.id == actions.ActionWithOneDevice.device_id)
RateQ) & (actions.ActionWithOneDevice.id == actions.Rate.id),
RateQ,
)
tag = query.Join(Device.id == Tag.device_id, TagQ) tag = query.Join(Device.id == Tag.device_id, TagQ)
# todo This part of the query is really slow # todo This part of the query is really slow
# And forces usage of distinct, as it returns many rows # And forces usage of distinct, as it returns many rows
# due to having multiple paths to the same # due to having multiple paths to the same
lot = query.Join((Device.id == LotDeviceDescendants.device_id), lot = query.Join((Device.id == LotDeviceDescendants.device_id), LotQ)
LotQ)
class Sorting(query.Sort): class Sorting(query.Sort):
@ -104,12 +110,15 @@ class DeviceView(View):
return super().get(id) return super().get(id)
def patch(self, id): def patch(self, id):
dev = Device.query.filter_by(id=id, owner_id=g.user.id, active=True).one() dev = Device.query.filter_by(
id=id, owner_id=g.user.id, active=True, placeholder=None
).one()
if isinstance(dev, Computer): if isinstance(dev, Computer):
resource_def = app.resources['Computer'] resource_def = app.resources['Computer']
# TODO check how to handle the 'actions_one' # TODO check how to handle the 'actions_one'
patch_schema = resource_def.SCHEMA( patch_schema = resource_def.SCHEMA(
only=['transfer_state', 'actions_one'], partial=True) only=['transfer_state', 'actions_one'], partial=True
)
json = request.get_json(schema=patch_schema) json = request.get_json(schema=patch_schema)
# TODO check how to handle the 'actions_one' # TODO check how to handle the 'actions_one'
json.pop('actions_one') json.pop('actions_one')
@ -129,12 +138,16 @@ class DeviceView(View):
return self.one_private(id) return self.one_private(id)
def one_public(self, id: int): def one_public(self, id: int):
device = Device.query.filter_by(devicehub_id=id, active=True).one() device = Device.query.filter_by(
devicehub_id=id, active=True, placeholder=None
).one()
return render_template('devices/layout.html', device=device, states=states) return render_template('devices/layout.html', device=device, states=states)
@auth.Auth.requires_auth @auth.Auth.requires_auth
def one_private(self, id: str): def one_private(self, id: str):
device = Device.query.filter_by(devicehub_id=id, owner_id=g.user.id, active=True).first() device = Device.query.filter_by(
devicehub_id=id, owner_id=g.user.id, active=True, placeholder=None
).first()
if not device: if not device:
return self.one_public(id) return self.one_public(id)
return self.schema.jsonify(device) return self.schema.jsonify(device)
@ -148,7 +161,11 @@ class DeviceView(View):
devices = query.paginate(page=args['page'], per_page=30) # type: Pagination devices = query.paginate(page=args['page'], per_page=30) # type: Pagination
return things_response( return things_response(
self.schema.dump(devices.items, many=True, nested=1), self.schema.dump(devices.items, many=True, nested=1),
devices.page, devices.per_page, devices.total, devices.prev_num, devices.next_num devices.page,
devices.per_page,
devices.total,
devices.prev_num,
devices.next_num,
) )
def query(self, args): def query(self, args):
@ -158,9 +175,11 @@ class DeviceView(View):
trades_dev_ids = {d.id for t in trades for d in t.devices} trades_dev_ids = {d.id for t in trades for d in t.devices}
query = Device.query.filter(Device.active == True).filter( query = (
(Device.owner_id == g.user.id) | (Device.id.in_(trades_dev_ids)) Device.query.filter(Device.active == True, Device.placeholder == None)
).distinct() .filter((Device.owner_id == g.user.id) | (Device.id.in_(trades_dev_ids)))
.distinct()
)
unassign = args.get('unassign', None) unassign = args.get('unassign', None)
search_p = args.get('search', None) search_p = args.get('search', None)
@ -168,18 +187,22 @@ class DeviceView(View):
properties = DeviceSearch.properties properties = DeviceSearch.properties
tags = DeviceSearch.tags tags = DeviceSearch.tags
devicehub_ids = DeviceSearch.devicehub_ids devicehub_ids = DeviceSearch.devicehub_ids
query = query.join(DeviceSearch).filter( query = (
search.Search.match(properties, search_p) | query.join(DeviceSearch)
search.Search.match(tags, search_p) | .filter(
search.Search.match(devicehub_ids, search_p) search.Search.match(properties, search_p)
).order_by( | search.Search.match(tags, search_p)
search.Search.rank(properties, search_p) + | search.Search.match(devicehub_ids, search_p)
search.Search.rank(tags, search_p) + )
search.Search.rank(devicehub_ids, search_p) .order_by(
search.Search.rank(properties, search_p)
+ search.Search.rank(tags, search_p)
+ search.Search.rank(devicehub_ids, search_p)
)
) )
if unassign: if unassign:
subquery = LotDeviceDescendants.query.with_entities( subquery = LotDeviceDescendants.query.with_entities(
LotDeviceDescendants.device_id LotDeviceDescendants.device_id
) )
query = query.filter(Device.id.notin_(subquery)) query = query.filter(Device.id.notin_(subquery))
return query.filter(*args['filter']).order_by(*args['sort']) return query.filter(*args['filter']).order_by(*args['sort'])
@ -221,10 +244,16 @@ class DeviceMergeView(View):
raise ValidationError('The devices is not the same type.') raise ValidationError('The devices is not the same type.')
# Adding actions of self.with_device # Adding actions of self.with_device
with_actions_one = [a for a in self.with_device.actions with_actions_one = [
if isinstance(a, actions.ActionWithOneDevice)] a
with_actions_multiple = [a for a in self.with_device.actions for a in self.with_device.actions
if isinstance(a, actions.ActionWithMultipleDevices)] if isinstance(a, actions.ActionWithOneDevice)
]
with_actions_multiple = [
a
for a in self.with_device.actions
if isinstance(a, actions.ActionWithMultipleDevices)
]
# Moving the tags from `with_device` to `base_device` # Moving the tags from `with_device` to `base_device`
# Union of tags the device had plus the (potentially) new ones # Union of tags the device had plus the (potentially) new ones
@ -269,20 +298,22 @@ class DeviceMergeView(View):
class ManufacturerView(View): class ManufacturerView(View):
class FindArgs(marshmallow.Schema): class FindArgs(marshmallow.Schema):
search = marshmallow.fields.Str(required=True, search = marshmallow.fields.Str(
# Disallow like operators required=True,
validate=lambda x: '%' not in x and '_' not in x) # Disallow like operators
validate=lambda x: '%' not in x and '_' not in x,
)
@cache(datetime.timedelta(days=1)) @cache(datetime.timedelta(days=1))
def find(self, args: dict): def find(self, args: dict):
search = args['search'] search = args['search']
manufacturers = Manufacturer.query \ manufacturers = Manufacturer.query.filter(
.filter(Manufacturer.name.ilike(search + '%')) \ Manufacturer.name.ilike(search + '%')
.paginate(page=1, per_page=6) # type: Pagination ).paginate(
page=1, per_page=6
) # type: Pagination
return jsonify( return jsonify(
items=app.resources[Manufacturer.t].schema.dump( items=app.resources[Manufacturer.t].schema.dump(
manufacturers.items, manufacturers.items, many=True, nested=1
many=True,
nested=1
) )
) )