Exemple #1
0
def dataset_commit(request, app, data):
    if not isinstance(data, dict):
        raise SuspiciousOperation('Invalid payload')

    # For backwards compatibility
    if 'changes' in data:
        data['changed'] = list(data['changes'].values())
        # Convert keys back to integers (json doesn't handle integer keys)
        for object_id, change in data['changes'].items():
            change['object_id'] = int(object_id)

    kwargs = {}
    for key, value in data.items():
        validate_func = globals().get('_validate_commit_' + key)
        if validate_func:
            if not isinstance(value, list):
                raise SuspiciousOperation('Invalid commit {}'.format(key))
            for item in value:
                validate_func(item)
            kwargs[key] = value

    try:
        commit_query(app=app, **kwargs)
    except ValidationError as error:
        return {
            'status': 'error',
            'type': error.__class__.__name__,
            'message': str(error),
        }

    return {
        'status': 'success',
    }
Exemple #2
0
def commit(request):
    try:
        commit_obj = json.loads(request.POST['commit'])
    except (KeyError, ValueError) as error:
        result = {
            'status': 'error',
            'message': str(error),
        }
    else:
        changed = []
        if 'changes' in commit_obj:
            for key, value in commit_obj['changes'].items():
                value['object_id'] = int(key)
                changed.append(value)

        deleted = commit_obj.get('deleted', [])
        user = request.user

        try:
            commit_query(changed=changed, deleted=deleted, user=user)
        except (PermissionDenied, ValidationError) as error:
            result = {
                'status': 'error',
                'message': str(error),
            }
        else:
            result = {'status': 'success'}

    return HttpResponse(json.dumps(result), content_type='application/x-json')
Exemple #3
0
def restore_deleted(request, change_commit_id):
    object_id = request.POST.get('object_id')
    deleted = get_object_or_404(
        ChangeDelete,
        server_id=object_id,
        commit__pk=change_commit_id,
    )

    server_obj = deleted.attributes

    # Remove consistent_via_attribute values they are implicit
    consistent_attribute_ids = ServertypeAttribute.objects.filter(
        servertype_id=server_obj['servertype']).exclude(
            consistent_via_attribute_id=None)
    for attribute in consistent_attribute_ids:
        server_obj.pop(attribute.attribute_id)

    try:
        commit = commit_query([server_obj], user=request.user)
        object_id = str(commit.created[0]['object_id'])
    except CommitError as error:
        messages.error(request, str(error))
    else:
        messages.success(request, 'Restored object with new id ' + object_id)

    return redirect(reverse('serverdb_history') + '?object_id=' + object_id)
Exemple #4
0
def restore_deleted(request, change_commit):
    deleted = get_object_or_404(
        ChangeDelete,
        server_id=request.POST.get('server_id'),
        commit__pk=change_commit,
    )

    server_obj = deleted.attributes
    try:
        commit_query([server_obj], user=request.user)
    except CommitError as error:
        messages.error(request, str(error))
    else:
        messages.success(request, 'Server restored.')

    return redirect(
        reverse('serverdb_history') + '?server_id=' +
        str(server_obj['object_id']))
Exemple #5
0
def dataset_create(request, app, data):
    required = [
        'attributes',
    ]
    if not all(key in data for key in required):
        raise SuspiciousOperation('Invalid create request')
    if not isinstance(data['attributes'], dict):
        raise SuspiciousOperation('Attributes must be a dictionary')

    try:
        commit_obj = commit_query([data['attributes']], app=app)
    except ValidationError as error:
        return {
            'status': 'error',
            'type': error.__class__.__name__,
            'message': str(error),
        }

    return {
        'status': 'success',
        'result': commit_obj.created,
    }
Exemple #6
0
def _edit(request, server, edit_mode=False, template='edit'):  # NOQA: C901
    invalid_attrs = set()
    if edit_mode and request.POST:
        attribute_lookup = {
            a.pk: a
            for a in Attribute.objects.filter(
                attribute_id__in=(k[len('attr_'):]
                                  for k in request.POST.keys()))
        }
        attribute_lookup.update(Attribute.specials)
        for key, value in request.POST.items():
            if not key.startswith('attr_'):
                continue
            attribute_id = key[len('attr_'):]
            attribute = attribute_lookup[attribute_id]
            value = value.strip()
            if attribute.multi:
                values = [v.strip() for v in value.splitlines()]
                try:
                    value = attribute.from_str(values)
                except ValidationError:
                    invalid_attrs.add(attribute_id)
                    value = set(values)
            elif value == '':
                value = None
            else:
                try:
                    value = attribute.from_str(value)
                except ValidationError:
                    invalid_attrs.add(attribute_id)

            server[attribute_id] = value

        if not invalid_attrs:
            if server.object_id:
                action = 'edited'
                created = []
                changed = [server._serialize_changes()]
            else:
                action = 'created'
                created = [server]
                changed = []

            try:
                commit_obj = commit_query(created, changed, user=request.user)
            except (PermissionDenied, ValidationError) as err:
                messages.error(request, str(err))
            else:
                messages.success(request, 'Server successfully ' + action)
                if action == 'created':
                    server = commit_obj.created[0]

                url = '{0}?object_id={1}'.format(
                    reverse('servershell_inspect'),
                    server.object_id,
                )
                return HttpResponseRedirect(url)

        if invalid_attrs:
            messages.error(request, 'Attributes contain invalid values')

    servertype = Servertype.objects.get(pk=server['servertype'])
    attribute_lookup = {
        a.pk: a
        for a in Attribute.objects.filter(attribute_id__in=(server.keys()))
    }
    attribute_lookup.update(Attribute.specials)
    servertype_attributes = {
        sa.attribute_id: sa
        for sa in (ServertypeAttribute.objects.filter(
            servertype_id=server['servertype']))
    }

    fields = []
    fields_set = set()
    for key, value in server.items():
        if (key == 'object_id'
                or key == 'intern_ip' and servertype.ip_addr_type == 'null'):
            continue

        attribute = attribute_lookup[key]
        servertype_attribute = servertype_attributes.get(key)
        if servertype_attribute and servertype_attribute.related_via_attribute:
            continue

        fields_set.add(key)
        fields.append({
            'key':
            key,
            'value':
            value,
            'type':
            attribute.type,
            'multi':
            attribute.multi,
            'required': (servertype_attribute and servertype_attribute.required
                         or key in Attribute.specials.keys()),
            'regexp_display':
            _prepare_regexp_html(attribute.regexp),
            'regexp': (
                # XXX: HTML5 input patterns do not support these
                None if not attribute.regexp else attribute.regexp.replace(
                    '\\A', '^').replace('\\Z', '$')),
            'default': (servertype_attribute
                        and servertype_attribute.default_value),
            'readonly':
            attribute.readonly,
            'error':
            key in invalid_attrs,
        })

    fields.sort(key=lambda k: (not k['required'], k['key']))
    return TemplateResponse(
        request, 'servershell/{}.html'.format(template), {
            'object_id': server.object_id,
            'fields': fields,
            'is_ajax': request.is_ajax(),
            'base_template':
            'empty.html' if request.is_ajax() else 'base.html',
            'link': request.get_full_path(),
        })
Exemple #7
0
 def commit(self, app=None, user=None):
     commit_obj = self._build_commit_object()
     commit_query(app=app, user=user, **commit_obj)
     self._confirm_changes()
Exemple #8
0
def _edit(request, server, edit_mode=False, template='edit'):  # NOQA: C901
    # @TODO work with ServerAttribute models here and use Django forms
    invalid_attrs = set()
    if edit_mode and request.POST:
        attribute_lookup = {
            a.pk: a
            for a in Attribute.objects.filter(
                attribute_id__in=(k[len('attr_'):]
                                  for k in request.POST.keys()))
        }
        attribute_lookup.update(Attribute.specials)

        # Get current values to be able to submit only changes
        current = None
        if server['object_id']:
            current = Query({
                'object_id': server['object_id']
            }, list(attribute_lookup.keys())).get()

        for key, value in request.POST.items():
            if not key.startswith('attr_'):
                continue
            attribute_id = key[len('attr_'):]
            attribute = attribute_lookup[attribute_id]
            value = value.strip()
            if attribute.multi:
                values = [v.strip() for v in value.splitlines()]
                try:
                    value = attribute.from_str(values)
                except ValidationError:
                    invalid_attrs.add(attribute_id)
                    value = set(values)
            elif value == '':
                value = None
            else:
                try:
                    value = attribute.from_str(value)
                except ValidationError:
                    invalid_attrs.add(attribute_id)

            if attribute_id not in server.keys():
                messages.error(request,
                               'Unknown attribute {}'.format(attribute_id))
                continue

            if current:
                # TODO: Remove when PR153 is merged
                if type(current[attribute_id]) in (IPv4Address, IPv6Address):
                    current[attribute_id] = ip_interface(current[attribute_id])

                # Submit only changes
                if current[attribute_id] != value:
                    server[attribute_id] = value
            else:
                server[attribute_id] = value

        if not invalid_attrs:
            if server.object_id:
                action = 'edited'
                created = []

                changes = server._serialize_changes()
                if len(changes.keys()) > 1:
                    changed = [changes]
                else:
                    # Only object_id has been passed and we do not support
                    # changing it (yet).
                    changed = []
            else:
                action = 'created'
                created = [server]
                changed = []

            if not created and not changed:
                messages.info(request, str('Nothing has changed.'))
            else:
                try:
                    commit_obj = commit_query(created,
                                              changed,
                                              user=request.user)
                except (PermissionDenied, ValidationError) as err:
                    messages.error(request, str(err))
                else:
                    messages.success(request, 'Server successfully ' + action)
                    if action == 'created':
                        server = commit_obj.created[0]

                    url = '{0}?object_id={1}'.format(
                        reverse('servershell_inspect'),
                        server.object_id,
                    )
                    return HttpResponseRedirect(url)

        if invalid_attrs:
            messages.error(request, 'Attributes contains invalid values')

    servertype = Servertype.objects.get(pk=server['servertype'])
    attribute_lookup = {
        a.pk: a
        for a in Attribute.objects.filter(attribute_id__in=(server.keys()))
    }
    attribute_lookup.update(Attribute.specials)
    servertype_attributes = {
        sa.attribute_id: sa
        for sa in (ServertypeAttribute.objects.filter(
            servertype_id=server['servertype']))
    }

    fields = []
    fields_set = set()
    for key, value in server.items():
        if (key == 'object_id'
                or key == 'intern_ip' and servertype.ip_addr_type == 'null'):
            continue

        attribute = attribute_lookup[key]
        servertype_attribute = servertype_attributes.get(key)
        if servertype_attribute and servertype_attribute.related_via_attribute:
            continue

        fields_set.add(key)
        fields.append({
            'key':
            key,
            'value':
            value,
            'type':
            attribute.type,
            'multi':
            attribute.multi,
            'required': (servertype_attribute and servertype_attribute.required
                         or key in Attribute.specials.keys()),
            'regexp_display':
            _prepare_regexp_html(attribute.regexp),
            'regexp': (
                # XXX: HTML5 input patterns do not support these
                None if not attribute.regexp else attribute.regexp.replace(
                    '\\A', '^').replace('\\Z', '$')),
            'default': (servertype_attribute
                        and servertype_attribute.default_value),
            'readonly':
            attribute.readonly,
            'error':
            key in invalid_attrs,
            'hovertext':
            attribute.hovertext,
        })

    fields.sort(key=lambda k: (not k['required'], k['key']))
    return TemplateResponse(
        request, 'servershell/{}.html'.format(template), {
            'object_id': server.object_id,
            'hostname': server['hostname'],
            'fields': fields,
            'is_ajax': request.is_ajax(),
            'base_template':
            'empty.html' if request.is_ajax() else 'base.html',
            'link': request.get_full_path(),
        })