Skip to content
This repository has been archived by the owner on Mar 5, 2020. It is now read-only.

Commit

Permalink
Browse files Browse the repository at this point in the history
First implementation of auditing
* some extensions to acts_as_audited
* don't audit SOA serial number changes
* keep full record details when records are destroy
* basic view of domain history
Other spec improvements and new pendings
Minor style tweaks
  • Loading branch information
kennethkalmer committed Sep 24, 2008
1 parent 8a26e0b commit 7066b3c
Show file tree
Hide file tree
Showing 20 changed files with 198 additions and 48 deletions.
7 changes: 4 additions & 3 deletions app/controllers/application.rb
Expand Up @@ -9,10 +9,11 @@ class ApplicationController < ActionController::Base
# You can move this into a different controller, if you wish. This module
# gives you the require_role helpers, and others.
include RoleRequirementSystem

# Enable audits
audit Domain, Record

# Enable audits
audit Domain, Record, :parents => { Record => :domain }
Record.configure_audits

helper :all # include all helpers, all the time

# See ActionController::RequestForgeryProtection for details Uncomment the
Expand Down
17 changes: 17 additions & 0 deletions app/controllers/audits_controller.rb
@@ -0,0 +1,17 @@
class AuditsController < ApplicationController

require_role "admin"

def index

end

# Retrieve the audit details for a domain
def domain
@domain = Domain.find(
params[:id],
:user => current_user
)
end

end
29 changes: 29 additions & 0 deletions app/helpers/audits_helper.rb
@@ -0,0 +1,29 @@
module AuditsHelper

def parenthesize( text )
"(#{text})"
end

def link_to_domain_audit( audit )
caption = "#{audit.version} #{audit.action} by "
caption << (audit.user ? audit.user.login : audit.username)
link_to_function caption, "toggleDomainAudit(#{audit.id})"
end

def link_to_record_audit( audit )
caption = audit.changes['type']
caption += " (#{audit.changes['name']})" unless audit.changes['name'].nil?
caption += " #{audit.version} #{audit.action} by "
caption += (audit.user ? audit.user.login : audit.username)
link_to_function caption, "toggleRecordAudit(#{audit.id})"
end

def display_hash( hash )
hash.map { |k,v| v ? "<em>#{k}</em>: #{v}" : nil }.compact.join('<br />')
end

def sort_audits_by_date( collection )
collection.sort_by(&:created_at).reverse
end

end
13 changes: 13 additions & 0 deletions app/models/record.rb
Expand Up @@ -37,6 +37,14 @@ def batch
self.batch_soa_updates = nil
end

# Make some ammendments to the acts_as_audited assumptions
def configure_audits
defaults = [ non_audited_columns ].flatten
defaults.delete( inheritance_column )
defaults.push( :change_date )
write_inheritable_attribute :non_audited_columns, defaults.flatten.map(&:to_s)
end

end

def shortname
Expand Down Expand Up @@ -67,6 +75,11 @@ def update_soa_serial #:nodoc:
end
end

# Force acts_as_audited to record all attributes when a record is destroyed
def audit_destroy(user = nil)
write_audit(:action => 'destroy', :auditable_parent => auditable_parent, :changes => audited_attributes, :user => user)
end

private

# Append the domain name to the +name+ field if missing
Expand Down
6 changes: 4 additions & 2 deletions app/models/soa.rb
Expand Up @@ -76,8 +76,10 @@ def update_serial

# Same as #update_serial and saves the record
def update_serial!
update_serial
save
without_auditing do
update_serial
save
end
end

def before_update #:nodoc:
Expand Down
2 changes: 1 addition & 1 deletion app/models/user.rb
Expand Up @@ -118,7 +118,7 @@ def admin=( value )
value
end
end

protected
# before filter
def encrypt_password
Expand Down
9 changes: 9 additions & 0 deletions app/views/audits/_domain_audit.html.haml
@@ -0,0 +1,9 @@
%li
= link_to_domain_audit( domain_audit )
%div[ domain_audit ]{ :style => 'display: none' }
%strong Time:
= domain_audit.created_at
%br
%strong Changes:
%br
= display_hash domain_audit.changes
10 changes: 10 additions & 0 deletions app/views/audits/_record_audit.html.haml
@@ -0,0 +1,10 @@
%li
= link_to_record_audit( record_audit )
%div[ record_audit ]{ :style => 'display: none' }
%strong Time:
= record_audit.created_at
%br
%strong Changes:
%br
= display_hash record_audit.changes

35 changes: 35 additions & 0 deletions app/views/audits/domain.html.haml
@@ -0,0 +1,35 @@
%h1.underline
Audit information for
= link_to @domain.name, domain_path(@domain)

%p
You can click on any revision number on the lists below to see the details
of the revision

%h2.underline Domain Revisions

- if @domain.audits.size > 0
%ul
= render :partial => 'domain_audit', :collection => sort_audits_by_date( @domain.audits )
- else
%p
%em No revisions found for the domain.

%h2.underline RR Revisions

- if @domain.record_audits.size > 0
%p Revisions below sorted in reverse chronoligical order.

%ul
= render :partial => 'record_audit', :collection => sort_audits_by_date( @domain.record_audits )
- else
%p
%em No revisions found for any resource records of the domain.

:javascript
function toggleDomainAudit(id){
$('audit_' + id).toggle();
}
function toggleRecordAudit(id){
$('audit_' + id).toggle();
}
3 changes: 3 additions & 0 deletions app/views/audits/index.html.haml
@@ -0,0 +1,3 @@
%h1.underline Search audit logs

%em Coming soon!
4 changes: 2 additions & 2 deletions app/views/dashboard/index.html.haml
Expand Up @@ -6,11 +6,11 @@
&nbsp;
%h1 Search

- form_tag( { :controller => :search, :action => :results }, { :method => :get } ) do |f|
- form_tag( { :controller => :search, :action => :results }, { :method => :get } ) do
= text_field_tag :q
= submit_tag "Search"

&nbsp;
%h1.underline New domain

= render :partial => '/domains/new'
= render :partial => '/domains/new'
6 changes: 5 additions & 1 deletion app/views/domains/show.html.haml
Expand Up @@ -13,6 +13,8 @@
Edit the domains's current note
#delete-zone
Permantly remove this domain from the system
#audits
Views the audits/history for this domain
#change-owner
Change or remove the owner of this domain
#help-primary-ns
Expand Down Expand Up @@ -49,7 +51,9 @@
%tr
%td Domain
%td= @domain.name
%td= link_to prototip_info_icon('database_delete.png', 'delete-zone'), domain_path( @domain ), :method => :delete, :confirm => "Are you sure you want to remove #{@domain.name}?"
%td
= link_to prototip_info_icon('report_magnify.png', 'audits'), audits_path(:action => :domain, :id => @domain)
= link_to prototip_info_icon('database_delete.png', 'delete-zone'), domain_path( @domain ), :method => :delete, :confirm => "Are you sure you want to remove #{@domain.name}?"
- if current_user.admin?
%tr
%td Owner
Expand Down
22 changes: 8 additions & 14 deletions app/views/layouts/application.html.haml
@@ -1,32 +1,26 @@
!!!
%html{ "xml:lang" => "en", :lang => "en", :xmlns => "http://www.w3.org/1999/xhtml" }
%head
%title
= page_title
%title= page_title
= stylesheet_link_tag 'application', 'prototip'
= javascript_include_tag :defaults, 'prototip'
%body
#Container
#Header
%h1
PowerDNS on Rails
%h1 PowerDNS on Rails
- if current_user
#search-bar{:style => "display: inline; float: right;"}
- form_tag( { :controller => :search, :action => :results }, { :method => :get } ) do
= text_field_tag :q
= submit_tag "Search"
#Nav
%ul
%li
= link_to "Home", root_url
%li
= link_to "Domains", domains_path
%li
= link_to "Templates", zone_templates_path
%li
= link_to "Users", users_path
%li
= link_to "Logout", logout_path
%li= link_to "Home", root_url
%li= link_to "Domains", domains_path
%li= link_to "Templates", zone_templates_path
%li= link_to "Logs", audits_path
%li= link_to "Users", users_path
%li= link_to "Logout", logout_path

#Body
= show_flash
Expand Down
3 changes: 3 additions & 0 deletions config/routes.rb
Expand Up @@ -42,6 +42,9 @@
map.resources :zone_templates, :controller => 'templates'
map.resources :record_templates

# Audits
map.audits '/audits/:action/:id', :controller => 'audits', :action => 'index'

# Authentication routes
map.resources :users, :member => { :suspend => :put,
:unsuspend => :put,
Expand Down
5 changes: 4 additions & 1 deletion db/schema.rb
Expand Up @@ -14,16 +14,19 @@
create_table "audits", :force => true do |t|
t.integer "auditable_id"
t.string "auditable_type"
t.integer "auditable_parent_id"
t.string "auditable_parent_type"
t.integer "user_id"
t.string "user_type"
t.string "username"
t.string "action"
t.text "changes"
t.integer "version", :default => 0
t.integer "version", :default => 0
t.datetime "created_at"
end

add_index "audits", ["auditable_id", "auditable_type"], :name => "auditable_index"
add_index "audits", ["auditable_parent_id", "auditable_parent_type"], :name => "auditable_parent_index"
add_index "audits", ["user_id", "user_type"], :name => "user_index"
add_index "audits", ["created_at"], :name => "index_audits_on_created_at"

Expand Down
Binary file added public/images/report_magnify.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion public/stylesheets/application.css
Expand Up @@ -65,7 +65,7 @@ body {
font-size: 14px;
}
p {
margin: 0;
margin: 5px 0;
}
label {
width: 200px;
Expand Down
23 changes: 23 additions & 0 deletions spec/controllers/audits_controller_spec.rb
@@ -0,0 +1,23 @@
require File.dirname(__FILE__) + '/../spec_helper'

describe AuditsController do
fixtures :users, :domains, :records

before(:each) do
login_as(:admin)
end

it "should have a search form" do
get :index

pending
end

it "should have a domain details page" do
get :domain, :id => domains(:example_com).id

assigns[:domain].should_not be_nil

response.should render_template('domain')
end
end

0 comments on commit 7066b3c

Please sign in to comment.