Beispiel #1
0
    def add_control_add_equipment(self, user):
        '''
        Builds the control for adding an equipment resource.
        '''

        self.add_control("cyequ:add-equipment",
                         href=url_for("api.equipmentbyuser", user=user),
                         method="POST",
                         encoding="json",
                         title="Adds a new equipment for the user.",
                         schema=equipment_schema())
Beispiel #2
0
    def add_control_add_component(self, user, equipment):
        '''
        Builds the control for adding a component resource.
        '''

        self.add_control(
            "cyequ:add-component",
            href=url_for("api.equipmentitem", user=user, equipment=equipment),
            method="POST",
            encoding="json",
            title="Adds a new component to the associated equipment.",
            schema=equipment_schema())
Beispiel #3
0
    def add_control_edit_equipment(self, user, equipment):
        '''
        Builds the control for editing an equipment resource.
        '''

        self.add_control("edit",
                         href=url_for("api.equipmentitem",
                                      user=user,
                                      equipment=equipment),
                         method="PUT",
                         encoding="json",
                         title="Edits equipment's information",
                         schema=equipment_schema())
Beispiel #4
0
    def put(self, user, equipment):
        '''
        PUT-method definition.
        Checks for appropriate request body and modifies an equipment resource
        in the API.

        Exceptions.
        jsonschema.ValidationError. If request is not
            a valid JSON document.
        sqlalchemy.exc.IntegrityError. Violation of SQLite database
            integrity.

        Returns flask Response object.
        '''

        # Check for json. If fails, respond with error 415
        if request.json is None:
            return create_error_response(415, "Unsupported media type",
                                         "Requests must be JSON")
        # Validate request against the schema. If fails, respond with error 400
        try:
            validate(request.json, equipment_schema())
        except ValidationError as err:
            return create_error_response(400, "Invalid JSON "
                                         "document", str(err))
        # Find user by name in database. If not found, respond with error 404
        if User.query.filter_by(uri=user).first() is None:
            return create_error_response(
                404, "Not found", "No user was found with URI {}".format(user))
        # Find equipment by name in database.
        # If not found, respond with error 404
        db_equip = Equipment.query.filter_by(uri=equipment).first()
        if db_equip is None:
            return create_error_response(
                404, "Not found",
                "No equipment was found with URI {}".format(equipment))
        # Convert %Y-%m-%d %H:%M:%S dates to Python datetime format
        p_date_added = convert_req_date(request.json.get("date_added"))
        p_date_retired = convert_req_date(request.json.get("date_retired"))
        # Update equipment data
        db_equip.name = request.json["name"]
        db_equip.category = request.json["category"]
        db_equip.brand = request.json["brand"]
        db_equip.model = request.json["model"]
        # Make sure equipment date_added cannot be moved forward in time if
        # equipment has associated components
        if db_equip.date_added >= p_date_added:
            db_equip.date_added = p_date_added
        elif not Component.query.filter_by(equipment_id=db_equip.id).first():
            db_equip.date_added = p_date_added
        else:
            return create_error_response(
                409, "Inconsistent dates",
                "New added date {} must not be in the"
                "future of current added date {} if "
                "equipment has components associated"
                " with it".format(p_date_added, db_equip.date_added))
        # When retiring equipment, also retire associated components
        # Check if date_retired given for equipment
        if request.json.get("date_retired") is not None:
            # Check if date_retired is later than date_added
            if p_date_added >= p_date_retired:
                return create_error_response(
                    409, "Inconsistent dates", "Retire date {} must be in the "
                    "future with respect to"
                    " added date {}".format(p_date_retired, p_date_added))
            # Update equipment date_retired
            db_equip.date_retired = p_date_retired
            # Loop all associated components for equipment
            for component in Component.query.filter_by(
                    equipment_id=db_equip.id).all():  # noqa: 501
                # Update component date_retired
                component.date_retired = p_date_retired
        try:
            db.session.commit()
        except IntegrityError:
            # In case of database error
            db.session.rollback()
            return create_error_response(
                409, "Already exists", "Equipment with name '{}' already "
                "exists for user.".format(request.json["name"]))
        return Response(status=204)
Beispiel #5
0
    def post(self, user, equipment):
        '''
        POST-method definition.
        Checks for appropriate request body and creates a new component
        resource in the API.

        Exceptions.
        jsonschema.ValidationError. If request is not
            a valid JSON document.
        sqlalchemy.exc.IntegrityError. Violation of SQLite database
            integrity.

        Returns flask Response object.
        '''

        # Check for json. If fails, respond with error 415
        if request.json is None:
            return create_error_response(415, "Unsupported media type",
                                         "Requests must be JSON")
        # Validate request against the schema. If fails, respond with error 400
        try:
            validate(request.json, equipment_schema())
        except ValidationError as err:
            return create_error_response(400, "Invalid JSON "
                                         "document", str(err))
        # Find user by name in database. If not found, respond with error 404
        if User.query.filter_by(uri=user).first() is None:
            return create_error_response(
                404, "Not found", "No user was found with URI {}".format(user))
        # Find equipment by name in database.
        # If not found, respond with error 404
        db_equip = Equipment.query.filter_by(uri=equipment).first()
        if db_equip is None:
            return create_error_response(
                404, "Not found",
                "No equipment was found with URI {}".format(equipment))
        # Check if equipment is already retired
        if db_equip.date_retired is not None:
            return create_error_response(
                409, "Already retired", "Equipment of URI '{}' is retired."
                " Cannot add component {}.".format(db_equip.uri,
                                                   request.json["category"]))
        # Date checks
        # Convert %Y-%m-%d %H:%M:%S dates to Python datetime format
        p_date_added = convert_req_date(request.json.get("date_added"))
        # Check that component date added is not before
        # associated equipment's date added
        if p_date_added < db_equip.date_added:
            return create_error_response(
                409, "Inconsistent dates", "Components's date added {} must be"
                " after associated equipment's "
                "date added {}".format(db_equip.date_added, p_date_added))
        # Check if date_retired given and convert
        p_date_retired = convert_req_date(request.json.get("date_retired"))
        if p_date_retired is not None:
            if p_date_added >= p_date_retired:
                return create_error_response(
                    409, "Inconsistent dates", "Retire date {} must be in the "
                    "future with respect to"
                    " added date {}".format(p_date_retired, p_date_added))
        else:
            # If not given, set to faaar in the future.
            # Meaning component is currently installed to equipment
            p_date_retired = convert_req_date("9999-12-31 23:59:59")
        # Add a new component to db for equipment
        new_comp = Component(name=request.json["name"],
                             category=request.json["category"],
                             brand=request.json["brand"],
                             model=request.json["model"],
                             date_added=p_date_added,
                             date_retired=p_date_retired,
                             equipment_id=db_equip.id)
        try:
            db.session.add(new_comp)
            db.session.commit()
        except IntegrityError:
            # In case of database error
            db.session.rollback()
            # Currently doesn't work.
            # No functioning constraint for unique "active component".
            return create_error_response(
                409, "Already in service", "Unretired component of category"
                " '{}' already exists.".format(request.json["category"]))
        # Find new component by category & date_retired in database.
        db_comp = Component.query.filter_by(
            category=request.json["category"],
            date_retired=p_date_retired).first()
        # Create URI for user
        db_comp.uri = db_comp.name + str(db_comp.id)
        db.session.commit()
        # Respond with location of new resource
        return Response(status=201,
                        headers={
                            "Location":
                            url_for("api.componentitem",
                                    user=user,
                                    equipment=equipment,
                                    component=db_comp.uri)
                        })