def post(self) -> (str, int):
        """
        Save or Update a Widget
        Parameters can be passed using a POST request.
        POST request JSON body parameters:
            :param data:  Widget JSON data
            :param widgetID: Widget Id
            :param x: x coordinate of the widget layout
            :param y: y coordinate of the widget layout
            :param h: height of the widget layout
            :param w: width of the widget layout
            :param static: layout static property
        :returns : A response message and an appropriate HTTP status code
        """
        args = self.reqparse_post.parse_args()

        current_user = Users.find_by_email(get_jwt_identity())
        curr_widget = None

        if "widget_id" in args:
            curr_widget = WidgetModel.get_widget_by_id_and_user_id(
                args["widget_id"], current_user.id)

            if curr_widget:
                curr_widget.data = args["data"]
            else:
                abort(HTTPStatus.NOT_FOUND,
                      error="Widget with Id {} not found".format(
                          args["widget_id"]))

        else:
            # Create a layout for the new widget
            layout = Layouts(1, 0, 0, args['height'], args['width'], False)
            curr_widget = WidgetModel(current_user.id, layout, args["data"])

        try:
            db.session.add(curr_widget)
            # flush session to get new widgetID to assign to layout
            db.session.flush()
            self.update_layout(curr_widget, args)
            db.session.commit()
        except exc.SQLAlchemyError as e:
            logger.error(e.with_traceback(e.__traceback__))
            abort(HTTPStatus.BAD_REQUEST.value,
                  error="exc.SQLAlchemyError: create_widget")
        response = self.get_reponse_template(curr_widget,
                                             updated="widget_id" in args)
        return response, HTTPStatus.OK
Beispiel #2
0
    def post(self) -> ([WidgetModel], int):
        """
        Get one or more widgets from the database with a userID
        Parameters can be passed using a POST request that contains a JSON with the following fields:
        :param  userID: Unique user identification number
        :param  limit: the max count of widgets to be returned

        :type userID: int
        :type limit: int

        :returns [widget]: A list of widgets with a maximum length of limit and a status code 200
        """
        args = self.reqparser_get.parse_args()
        # Fetch the widget instances related to the userID passed
        widgets = WidgetModel.query.filter_by(user_id=args["userID"]).limit(
            args["limit"]).all()

        # Were widget instances returned
        if not widgets:
            # No widgets found for userID
            return [], 200

        # Store widgets to be returned
        widget_list = []

        for widget in widgets:
            widget = WidgetModel.get_widget_by_id(widget.id)
            # Format widget data for response
            widget_list.append(widget.json())

        return widget_list, HTTPStatus.OK.value
Beispiel #3
0
def test_widget_model() -> NoReturn:
    """
    Tests that widget data can be persisted and fetched from the database
    """
    # Create a Layout instance required for Widget
    dummy_layout = Layouts(-1, 5, 4, 3, 2, True)
    # Persist a Widget to the database
    new_widget = WidgetModel(dependencies.user.id, dummy_layout,
                             dependencies.get_widget_data())
    db.session.add(new_widget)
    # Flush session to get Widgets Id for the layout
    db.session.flush()
    dummy_layout.widget_id = new_widget.id
    db.session.commit()
    # Fetch widget from database and check they are the same instance
    fetched_widget = WidgetModel.get_widget_by_id(new_widget.id)
    assert fetched_widget is new_widget
    assert fetched_widget.layout is new_widget.layout
Beispiel #4
0
    def post(self) -> (str, int):
        """
        Creates a Widget layout to the database table 'layouts'
        Parameters can be passed using a POST request that contains a JSON with the following fields:
        :param widgetID: The widget identification the layout belongs to
        :param x: x coordinate of the widget layout
        :param y: y coordinate of the widget layout
        :param h: height of the widget layout
        :param w: width of the widget layout
        :param static: layout static property

        :type widgetID: str
        :type x: int
        :type y: int
        :type h: int
        :type w: int
        :type static: str

        :returns:  on success a HTTP status code 200, otherwiseif the layout instance is not found a HTTP status
        code 404, Not Found with json with a key "error" containing a message "layout object not found"
        """
        # Fetch layout values from post content
        args = self.post_reqparser.parse_args()
        # Fetch the instance of the widget to assign new layout
        widget = WidgetModel.get_widget_by_id(args["widgetID"])

        # does the widget with the passed widgetID exist?
        if not widget.layout:
            # No widget return with the passed widgetID
            logging.debug("CreateWidgetLayout(): ",
                          status_code=HTTPStatus.NOT_FOUND.value,
                          error="layout object not found")
            abort(HTTPStatus.NOT_FOUND.value, error="layout object not found")

        # Modify layout instance for widget
        widget.layout.widgetID = int(args["widgetID"])
        widget.layout.x_coord = args["x"]
        widget.layout.y_coord = args["y"]
        widget.layout.height = args["h"]
        widget.layout.width = args["w"]
        widget.layout.static = args["static"]

        # Commit changes to the database
        widget.save()
        widget.commit()

        return "Widget crearted", 200
    def make_dummy_widgets(self, number_of_widgets: int = 1) -> [int]:
        """
        Creates widgets for tests
        :param number_of_widgets: the number of widgets to create
        :type number_of_widgets:    int
        :return: A list of the widget ids created
        """
        widget_ids = []
        for _ in range(number_of_widgets):
            new_widget = WidgetModel(self.user.id, Layouts(-1, 0, 0, 5, 5, False), self.get_widget_data())
            db.session.add(new_widget)
            db.session.flush()
            # new_widget.layout.layout.widget_id = new_widget.id
            db.session.commit()
            widget_ids.append(new_widget.id)

        return widget_ids
 def remove_all_widgets(self) -> NoReturn:
     """
     Removes all widgets created for the tests
     """
     # Get all widgets with the admin user id
     response = self.client.post('/widgets/load_widgets',
                                 json=dict(userID=self.user.id, limit="1000"),
                                 headers=self.auth_header, follow_redirects=True)
     json_response = response.get_json()
     # check the type of reponse recieved
     if isinstance(json_response, dict):
         if response.get_json()['error'] == 'no widgets found for userID {}'.format(self.user.id):
             # No widgets were found so return
             return
     # Widgets were found, cleanup by removing them
     for widget in response.get_json():
         if widget["userID"] == self.user.id:
             widget_instance = WidgetModel.get_widget_by_id(widget["id"])
             print("Deleting dummy widget: {}".format(widget_instance.id))
             db.session.delete(widget_instance)
             db.session.commit()
Beispiel #7
0
def test_save_layouts_endpoints() -> NoReturn:
    """
    Tests the '/widgets/save_layouts' endpoint. The test checks the end point modifies the layout in the database
    """
    global dependencies
    # Create dummy widgets for test
    number_of_widgets = 5
    widget_ids = dependencies.make_dummy_widgets(number_of_widgets)
    # Create templates for new layout data
    layouts_data = {"layouts": []}
    layout_template = {"id": -1, "x": 0, "y": 0, "h": 0, "w": 0, "static": ""}

    # Bind the user to the database session but storing an instance of the user to keep user object from expiring
    dependencies.user.id
    for widget_id in widget_ids:
        new_layout = copy.deepcopy(layout_template)
        new_layout["id"] = widget_id
        new_layout["x"] = widget_id
        new_layout["y"] = widget_id
        new_layout["h"] = widget_id
        new_layout["w"] = widget_id
        new_layout["static"] = "true"
        layouts_data["layouts"].append(new_layout)
    json_layout = json.dumps(layouts_data)
    response = dependencies.client.post('/widgets/save_layouts',
                                        json=json.loads(json_layout),
                                        headers=dependencies.auth_header,
                                        follow_redirects=True)

    assert response.status_code == 200
    # Check layout changed for each widget
    for widget_id in widget_ids:
        widget = WidgetModel.get_widget_by_id(widget_id)
        if widget:
            layout = widget.layout
            assert layout.x_coord == widget_id
            assert layout.y_coord == widget_id
            assert layout.height == widget_id
            assert layout.width == widget_id
            assert layout.static
Beispiel #8
0
    def post(self) -> ([str], int):
        """
        Fetches all layouts for the widgets with a specific userID

        :param  userID: Unique user identification number
        :param  limit:  maximum count of widgets to be returned (optional)

        :type userID: int
        :type limit: int

        :returns: on success a list of all the widget layouts related to the userID are returned. If no
                  widget are found for the userID a HTTP status code 404, Not Found is returned with an
                  error message "no widgets found".
        """
        # Fetch the userID from post content ( limit is optional )
        args = self.reqparser.parse_args()
        # Fetch the instances of the widgets to assign the new layouts
        widgets = WidgetModel.query.filter_by(user_id=args["userID"]).limit(
            args["limit"]).all()

        # Where widgets returned
        if not widgets:
            # no widgets related to the userID supplied
            return [], 200

        # Store layout instances to be returned
        layout_list = []

        # Get all layout instances for the widgets
        for widget in widgets:
            widget = WidgetModel.get_widget_by_id(widget.id)
            widget.layout.widgetID = widget.id
            # Format layouts to be return
            layout_list.append(widget.layout.json())

        return layout_list, HTTPStatus.OK.value
Beispiel #9
0
    def post(self) -> (str, int):
        """
        Pesists widget layout to the database
        Parameters can be passed using a POST request that contains a JSON with the following fields:
        :param layouts: layouts to be saved
        :type layouts: str
        :param id: Related widget identification number
        :type id:   str
        :param x: x coordinate of widget
        :type x:   int
        :param y: y coordinate of widget
        :type y:   int
        :param h: height of widget
        :type h:   int
        :param w: width of widget
        :type w:   int
        :param static: static state
        :type static:   str

        :return: On success a HTTP status code 200, executed successfully with no content is return
                 otherwise, a HTTP status code 404, not found with content containing JSON objects
        """
        # Keep track of widgetIDs that are not found to inform user
        widgets_not_found = []
        # Keep track of widgetIDs that are updated to inform user
        widgets_updated = []
        # Get layout data passed in post request
        args = self.post_reqparser.parse_args()

        # Cycle throught the layout/s recieved in post request (there may be multiple layouts)
        for layout in args['layouts']:
            # Sanitize the layout data to be loaded into JSON ( eg. replace single quote with double quotes)
            layout = layout.replace("'", "\"")
            # Change sanitized layout data into json format
            layout_json = json.loads(layout)
            # Fetch the widget instance
            widget = WidgetModel.get_widget_by_id(int(layout_json["id"]))
            # does the widget exist?
            if not widget:
                # widget with the widgetID received does not exist so log it for the response
                widgets_not_found.append(layout_json["id"])
            else:
                # Got a widget. Update its layout
                widget.layout.widget_id = int(layout_json['id'])
                widget.layout.x_coord = layout_json['x']
                widget.layout.y_coord = layout_json['y']
                widget.layout.height = layout_json['h']
                widget.layout.width = layout_json['w']
                widget.layout.static = bool(layout_json['static'])
                widgets_updated.append(int(layout_json["id"]))
                # Save changes to the widget
                widget.save()
                widget.commit()

        # Where all widget layouts updated?
        if len(widgets_not_found) >= 1:
            abort(404,
                  error="Widgets not found",
                  widgets_not_found=len(widgets_not_found),
                  widget_ids=json.dumps(widgets_not_found),
                  widgets_updated=json.dumps(widgets_updated))

        return "", 200