Ejemplo n.º 1
0
def restore_backup_archive(uploaded_archive):
    if os.path.splitext(uploaded_archive.filename)[-1] != '.zip':
        raise PatchArchiveRestoreFailure(
            'The submitted file is not a .zip archive')

    if len(SoftwareTitle.query.all()) != 0:
        raise PatchArchiveRestoreFailure(
            'Definitions already exist on this server')

    definitions_to_restore = list()

    with zipfile.ZipFile(uploaded_archive, 'r') as zip_file:
        for file_ in zip_file.namelist():
            data = json.loads(zip_file.read(file_))

            try:
                validate_json(data, 'patch')
            except InvalidPatchDefinitionError:
                raise PatchArchiveRestoreFailure(
                    'A definition in the archive failed validation')

            definitions_to_restore.append(data)

    saved_definitions = list()

    for definition in definitions_to_restore:
        saved_def = create_title(definition)
        saved_definitions.append({
            "database_id": saved_def.id,
            "id": saved_def.id_name
        })

    return saved_definitions
Ejemplo n.º 2
0
def title_create():
    """Create a new patch definition on the server.

    .. :quickref: Software Title; Create a patch definition.

    **Example Request:**

    .. sourcecode:: http

        POST /api/v1/title HTTP/1.1
        Content-Type: application/json

        {
            "id": "Composer",
            "name": "Composer",
            "publisher": "Jamf",
            "appName": "Composer.app",
            "bundleId": "com.jamfsoftware.Composer",
            "requirements": ["requirementObjects"],
            "patches": ["versionObjects"],
            "extensionAttributes": ["extensionAttributeObjects"]
        }

    .. note::

        The JSON schema for a patch definition can be found in the project
        repository at:
        ``patchserver/routes/validator/schema_full_definition.json``

    **Example Response:**

    A successful response will return a ``201`` status with the numerical
    database ID as well as the definition's ID.

    .. sourcecode:: http

        HTTP/1.1 201 Created
        Content-Type: application/json

        {
            "database_id": 1,
            "id": "Composer"
        }

    **Error Responses**

    A ``409`` status is returned if you attempt to create a patch definition
    using an ID that already exists in the database.

    .. sourcecode:: http

        HTTP/1.1 409 Conflict
        Content-Type: application/json

        {
            "database_conflict": "A software title of the provided name already exists."
        }

    A ``400`` status can be returned if your patch definition fails a
    validation check against the JSON schema. If this occurs, a reason will
    be provided in the JSON response.

    .. sourcecode:: http

        HTTP/1.1 400 Bad Request
        Content-Type: application/json

        {
            "invalid_json": "Validation error encountered with submitted JSON for item: /u'true' is not of type u'boolean'"
        }

    A ``400`` status can be returned if your patch definition fails a
    validation check against the JSON schema. If this occurs, a reason will
    be provided in the JSON response.

    .. sourcecode:: http

        HTTP/1.1 400 Bad Request
        Content-Type: application/json

        {
            "invalid_json": "Validation error encountered with submitted JSON: u'true' is not of type u'boolean' for item: /patches/0/components/0/criteria/0/and"
        }

    """
    data = request.get_json()
    if not data:
        try:
            data = json.load(request.files['file'])
        except ValueError:
            raise InvalidPatchDefinitionError('No JSON data could be found.')

    validate_json(data, 'patch')

    new_title = SoftwareTitle(id_name=data['id'],
                              name=data['name'],
                              publisher=data['publisher'],
                              app_name=data['appName'],
                              bundle_id=data['bundleId'])
    db.session.add(new_title)

    if data.get('requirements'):
        create_criteria_objects(data['requirements'], software_title=new_title)

    if data.get('patches'):
        create_patch_objects(list(reversed(data['patches'])),
                             software_title=new_title)

    if data.get('extensionAttributes'):
        create_extension_attributes(data['extensionAttributes'], new_title)

    db.session.commit()

    g.event_type = 'new_title'
    g.event = new_title.serialize

    if request.args.get('redirect'):
        flash(
            {
                'title':
                'Software title created',
                'message':
                'View at <a href="{0}">{0}</a>'.format(
                    url_for('jamf_pro.patch_by_name_id',
                            name_id=new_title.id_name))
            }, 'success')
        return redirect(url_for('web_ui.index'))
    else:
        return jsonify({
            'id': new_title.id_name,
            'database_id': new_title.id
        }), 201
Ejemplo n.º 3
0
def title_versions(name_id):
    """Create a new patch version for an existing patch definition.

    .. :quickref: Software Title; Create a patch version.

    **Example Request:**

    .. sourcecode:: http

        POST /api/v1/title/Composer/version HTTP/1.1
        Content-Type: application/json

            {
                "version": "10.1.1",
                "releaseDate": "2017-12-20T10:08:38.270Z",
                "standalone": true,
                "minimumOperatingSystem": "10.9",
                "reboot": false,
                "killApps": [
                    {
                        "bundleId": "com.jamfsoftware.Composer",
                        "appName": "Composer.app"
                    }
                ],
                "components": [
                    {
                        "name": "Composer",
                        "version": "10.1.1",
                        "criteria": ["requirementsObjects"]
                    }
                ],
                "capabilities": ["requirementsObjects"],
                "dependencies": []
            }

    .. note::

        The JSON schema for a patch definition can be found in the project
        repository at:
        ``patchserver/routes/validator/schema_version.json``

    **Example Response:**

    A successful response will return a ``201`` status.

    .. sourcecode:: http

        HTTP/1.1 201 Created
        Content-Type: application/json

        {}

    **Error Responses**

    A ``400`` status can be returned if your patch version fails a validation
    check against the JSON schema. If this occurs, a reason will be provided in
    the JSON response.

    .. sourcecode:: http

        HTTP/1.1 400 Bad Request
        Content-Type: application/json

        {
            "invalid_json": "Validation error encountered with submitted JSON: u'true' is not of type u'boolean' for item: /patches/0/components/0/criteria/0/and"
        }

    """
    data = request.get_json()
    if not data:
        try:
            data = json.load(request.files['file'])
        except ValueError:
            raise InvalidPatchDefinitionError('No JSON data could be found.')

    validate_json(data, 'version')

    title = lookup_software_title(name_id)
    if data['version'] in [patch.version for patch in title.patches]:
        return jsonify({
            'database_conflict':
            'The provided version already exists '
            'for this software title.'
        }), 409

    create_patch_objects([data], software_title=title)
    db.session.commit()

    if request.args.get('redirect'):
        flash(
            {
                'title':
                'Software title version updated',
                'message':
                'View at <a href="{0}">{0}</a>'.format(
                    url_for('jamf_pro.patch_by_name_id', name_id=name_id))
            }, 'success')
        return redirect(url_for('web_ui.index'))
    else:
        return jsonify({}), 201