Skip to content

Commit

Permalink
bug 938132: need to be able to delete rules from admin ui. r=nthomas
Browse files Browse the repository at this point in the history
  • Loading branch information
bhearsum committed Mar 6, 2014
1 parent 0b77546 commit 1ae7ace
Show file tree
Hide file tree
Showing 10 changed files with 130 additions and 16 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -5,3 +5,4 @@ test.done
admin.ini
.coverage
htmlcov
cef.log
44 changes: 44 additions & 0 deletions auslib/admin/static/js/jquery.dataTables.fnAddTr.js
@@ -0,0 +1,44 @@
$.fn.dataTableExt.oApi.fnAddTr = function ( oSettings, nTr, bRedraw ) {
if ( typeof bRedraw == 'undefined' )
{
bRedraw = true;
}

var nTds = nTr.getElementsByTagName('td');
if ( nTds.length != oSettings.aoColumns.length )
{
alert( 'Warning: not adding new TR - columns and TD elements must match' );
return;
}

var aData = [];
var aInvisible = [];
for ( var i=0 ; i<nTds.length ; i++ )
{
aData.push( nTds[i].innerHTML );
if (!oSettings.aoColumns[i].bVisible)
{
aInvisible.push( i );
}
}

/* Add the data and then replace DataTable's generated TR with ours */
var iIndex = this.oApi._fnAddData( oSettings, aData );
nTr._DT_RowIndex = iIndex;
oSettings.aoData[ iIndex ].nTr = nTr;

oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();

// Hidding invisible columns
for ( var i = (aInvisible.length - 1) ; i >= 0 ; i-- )
{
oSettings.aoData[iIndex]._anHidden[ i ] = nTds[aInvisible[i]];
nTr.removeChild( nTds[aInvisible[i]] );
}

// Redraw
if ( bRedraw )
{
this.oApi._fnReDraw( oSettings );
}
};
23 changes: 20 additions & 3 deletions auslib/admin/static/js/rules.js
Expand Up @@ -197,11 +197,29 @@ function submitRuleForm(rule_id){

}

function deleteRule(rule_id){
var ruleForm = $('#rules_form');
var data = $.param({
'data_version': $('[name='+rule_id+'-data_version]', ruleForm).val(),
'csrf_token': $('[name='+rule_id+'-csrf_token]', ruleForm).val()
});
var url = getRuleUrl(rule_id) + '?' + data;

return $.ajax(url, {'type': 'delete', 'data': data, 'dataType': 'json'})
.error(handleError)
.success(function(data) {
table = $('#rules_table').dataTable();
row = $('#rule_' + rule_id).get(0);
table.fnDeleteRow(row);
alertify.success('Rule deleted!');
});

}

function submitNewRuleForm(ruleForm, table) {
url = getRuleAPIUrl();
data = getData('new_rule', ruleForm);

//console.log(data);
preAJAXLoad(ruleForm);

$.ajax(url, {'type': 'post', 'data': data})
Expand All @@ -212,8 +230,7 @@ function submitNewRuleForm(ruleForm, table) {
.success(function(data) {
postAJAXLoad(ruleForm);
alertify.success('Rule added!');
table.append(data);
table.dataTable().fnDraw();
table.dataTable().fnAddTr($(data)[0]);
});
});
}
Expand Down
19 changes: 10 additions & 9 deletions auslib/admin/templates/fragments/rules.html
Expand Up @@ -32,8 +32,7 @@
</form>


{% if rules %}
Below is a complete list of all of the rules
Below is a complete list of all of the rules:
<form id='rules_form'>
<table id='rules_table'>
<thead> <tr>
Expand All @@ -53,18 +52,23 @@
<th>Update Type</th>
<th>Header Architecture</th>
<th>Update</th>
<th>Delete</th>
<th>Clone</th>
<th>Revisions</th>
</tr></thead>
<tbody>
{% for row in rules %}
<tr>
{% set rule_id = row['rule_id'] %}
{% set form = forms[rule_id] %}
{% set suffix = '_r'~rule_id %}
{% set rule_id = row['rule_id'] %}
{% set form = forms[rule_id] %}
{% set suffix = '_r'~rule_id %}
<tr id='rule_{{ rule_id }}'>
{% include 'fragments/rule_form_row.html' %}
<td id='Update{{ suffix }}' name='Update{{ suffix }}'>
<input type='submit' name='submit' value='Update' onclick='submitRuleForm({{ rule_id }}); return false;' />
</td>
<td id='Delete{{ suffix }}' name='Delete{{ suffix }}'>
<input type='submit' name='submit' value='Delete' onclick='deleteRule({{ rule_id }}); return false;' />
</td>
<td id='Clone{{ suffix }}' name='Clone{{ suffix }}'>
<input type='button' name='clone' value='Clone' onclick='cloneRule($("#rules_form"), $("#new_rule_form"), "{{ rule_id }}")' />
</td>
Expand All @@ -77,6 +81,3 @@
</tbody>
</table>
</form>
{% else %}
No rules were provided.
{% endif %}
13 changes: 10 additions & 3 deletions auslib/admin/templates/fragments/single_rule.html
@@ -1,13 +1,20 @@
{% if rule and form %}
<tr>
{% set rule_id = rule['rule_id'] %}
{% set suffix = '_r'~rule_id %}
{% set rule_id = rule['rule_id'] %}
{% set suffix = '_r'~rule_id %}
<tr id='rule_{{ rule_id }}'>
{% include 'fragments/rule_form_row.html' %}
<td id='Update{{ suffix }}' name='Update{{ suffix }}'>
<input type='submit' name='submit' value='Update' onclick='submitRuleForm({{ rule_id }}); return false;' />
</td>
<td id='Delete{{ suffix }}' name='Delete{{ suffix }}'>
<input type='submit' name='submit' value='Delete' onclick='deleteRule({{ rule_id }}); return false;' />
</td>
<td id='Clone{{ suffix }}' name='Clone{{ suffix }}'>
<input type='button' name='clone' value='Clone' onclick='cloneRule($("#rules_form"), $("#new_rule_form"), "{{ rule_id }}")' />
</td>
<td id='Revisions{{ suffix }}'>
<input type='button' name='revisions' value='Revisions'
onclick="location.href='/rules/{{ rule_id }}/revisions/'" />
</td>
</tr>
{% endif %}
1 change: 1 addition & 0 deletions auslib/admin/templates/rules.html
Expand Up @@ -13,6 +13,7 @@
{% block bottom %}
{{ super() }}
<script type='text/javascript' src='{{ url_for('static', filename='js/jquery.dataTables.min.js') }}'></script>
<script type='text/javascript' src='{{ url_for('static', filename='js/jquery.dataTables.fnAddTr.js') }}'></script>
<script type='text/javascript' src='{{ url_for('static', filename='js/jquery-ui-1.9.2.custom.min.js') }}'></script>
<script type='text/javascript' src='{{ url_for('static', filename='js/rules.js') }}'></script>
{% endblock %}
Expand Down
33 changes: 32 additions & 1 deletion auslib/admin/views/rules.py
Expand Up @@ -182,7 +182,6 @@ def _post(self, rule_id, transaction, changed_by):
if form.header_arch.data:
what['headerArchitecture'] = form.header_arch.data

self.log.debug("old_data_version: %s", form.data_version.data)
db.rules.updateRule(changed_by=changed_by, rule_id=rule_id, what=what,
old_data_version=form.data_version.data, transaction=transaction)
# find out what the next data version is
Expand All @@ -192,6 +191,38 @@ def _post(self, rule_id, transaction, changed_by):
response.headers['Content-Type'] = 'application/json'
return response

@requirelogin
def _delete(self, rule_id, transaction, changed_by):
# Verify that the rule_id exists.
rule = db.rules.getRuleById(rule_id, transaction=transaction)
if not rule:
return Response(status=404)
# Bodies are ignored for DELETE requests, so we need to force WTForms
# to look at the arguments instead.
# Even though we aren't going to use most of the form fields (just
# rule_id and data_version), we still want to create and validate the
# form to make sure that the CSRF token is checked.
form = EditRuleForm(request.args)

releaseNames = db.releases.getReleaseNames()

form.mapping.choices = [(item['name'],item['name']) for item in releaseNames]
form.mapping.choices.insert(0, ('', 'NULL' ))

if not form.validate():
cef_event("Bad input", CEF_WARN, errors=form.errors)
return Response(status=400, response=form.errors)

if not db.permissions.hasUrlPermission(changed_by, '/rules/:id', 'DELETE', urlOptions={'product': rule['product']}):
msg = "%s is not allowed to alter rules that affect %s" % (changed_by, rule['product'])
cef_event('Unauthorized access attempt', CEF_ALERT, msg=msg)
return Response(status=401, response=msg)

db.rules.deleteRule(changed_by=changed_by, rule_id=rule_id,
old_data_version=form.data_version.data, transaction=transaction)

return Response(status=200)


class RuleHistoryView(HistoryAdminView):
""" /rules/<rule_id>/revisions """
Expand Down
3 changes: 3 additions & 0 deletions auslib/db.py
Expand Up @@ -761,6 +761,9 @@ def updateRule(self, changed_by, rule_id, what, old_data_version, transaction=No
where = [self.rule_id==rule_id]
self.update(changed_by=changed_by, where=where, what=what, old_data_version=old_data_version, transaction=transaction)

def deleteRule(self, changed_by, rule_id, old_data_version, transaction=None):
where = [self.rule_id==rule_id]
self.delete(changed_by=changed_by, where=where, old_data_version=old_data_version, transaction=transaction)

class Releases(AUSTable):
def __init__(self, metadata, dialect):
Expand Down
4 changes: 4 additions & 0 deletions auslib/test/admin/views/test_rules.py
Expand Up @@ -85,6 +85,10 @@ def testGetSingleRule(self):
for h in ("X-CSRF-Token", "X-Data-Version"):
self.assertTrue(h in ret.headers, msg=ret.headers)

def testDeleteRule(self):
ret = self._delete('/rules/1', qs=dict(data_version=1))
self.assertEquals(ret.status_code, 200, msg=ret.data)


class TestRulesView_HTML(ViewTest, HTMLTestMixin):
def testGetRules(self):
Expand Down
5 changes: 5 additions & 0 deletions auslib/test/test_db.py
Expand Up @@ -699,6 +699,11 @@ def testUpdateRule(self):
expected = [dict(rule_id=1, priority=100, backgroundRate=100, version='3.5', buildTarget='d', mapping='d', update_type='z', data_version=1)]
self.assertEquals(rule, expected)

def testDeleteRule(self):
self.paths.deleteRule(changed_by='bill', rule_id=2, old_data_version=1)
rule = self.paths.t.select().where(self.paths.rule_id==2).execute().fetchall()
self.assertEquals(rule, [])

def testGetNumberOfRules(self):
self.assertEquals(self.paths.countRules(), 7)

Expand Down

0 comments on commit 1ae7ace

Please sign in to comment.