* work on Issue 26: Auditing access to file revisions

* reworked operation logging

git-svn-id: http://redmine-dmsf.googlecode.com/svn/trunk/redmine_dmsf@158 5e329b0b-a2ee-ea63-e329-299493fc886d
This commit is contained in:
vit.jonas@gmail.com 2011-06-15 12:42:04 +00:00
parent ecbc773a55
commit a1f7cc2fa7
8 changed files with 100 additions and 35 deletions

View File

@ -138,13 +138,8 @@ class DmsfController < ApplicationController
flash[:error] = l(:error_user_has_not_right_delete_file)
end
end
unless deleted_folders.empty?
Rails.logger.info "#{Time.now} from #{request.remote_ip}/#{request.env["HTTP_X_FORWARDED_FOR"]}: #{User.current.login} deleted folders from project #{@project.identifier}:"
deleted_folders.each {|f| Rails.logger.info "\t#{f.dmsf_path_str}:"}
end
unless deleted_files.empty?
Rails.logger.info "#{Time.now} from #{request.remote_ip}/#{request.env["HTTP_X_FORWARDED_FOR"]}: #{User.current.login} deleted files from project #{@project.identifier}:"
deleted_files.each {|f| Rails.logger.info "\t#{f.dmsf_path_str}:"}
deleted_files.each {|f| log_activity(f, "deleted")}
DmsfMailer.deliver_files_deleted(User.current, deleted_files)
end
if failed_entries.empty?
@ -171,7 +166,6 @@ class DmsfController < ApplicationController
@folder.user = User.current
if @folder.save
flash[:notice] = l(:notice_folder_created)
Rails.logger.info "#{Time.now} from #{request.remote_ip}/#{request.env["HTTP_X_FORWARDED_FOR"]}: #{User.current.login} created folder #{@project.identifier}://#{@folder.dmsf_path_str}"
redirect_to({:controller => "dmsf", :action => "show", :id => @project, :folder_id => @folder})
else
@pathfolder = @parent
@ -192,7 +186,6 @@ class DmsfController < ApplicationController
@pathfolder = copy_folder(@folder)
@folder.attributes = params[:dmsf_folder]
if @folder.save
Rails.logger.info "#{Time.now} from #{request.remote_ip}/#{request.env["HTTP_X_FORWARDED_FOR"]}: #{User.current.login} updated folder #{@project.identifier}://#{@folder.dmsf_path_str}"
flash[:notice] = l(:notice_folder_details_were_saved)
redirect_to :controller => "dmsf", :action => "show", :id => @project, :folder_id => @folder
else
@ -205,7 +198,6 @@ class DmsfController < ApplicationController
if !@delete_folder.nil?
if @delete_folder.delete
flash[:notice] = l(:notice_folder_deleted)
Rails.logger.info "#{Time.now} from #{request.remote_ip}/#{request.env["HTTP_X_FORWARDED_FOR"]}: #{User.current.login} deleted folder #{@project.identifier}://#{@delete_folder.dmsf_path_str}"
else
flash[:error] = l(:error_folder_is_not_empty)
end
@ -249,6 +241,10 @@ class DmsfController < ApplicationController
private
def log_activity(file, action)
Rails.logger.info "#{Time.now.strftime('%Y-%m-%d %H:%M:%S')} #{User.current.login}@#{request.remote_ip}/#{request.env['HTTP_X_FORWARDED_FOR']}: #{action} dmsf://#{file.project.identifier}/#{file.id}"
end
def email_entries(selected_folders, selected_files)
zip = DmsfZip.new
zip_entries(zip, selected_folders, selected_files)
@ -262,9 +258,12 @@ class DmsfController < ApplicationController
end
end
Rails.logger.info "#{Time.now} from #{request.remote_ip}/#{request.env["HTTP_X_FORWARDED_FOR"]}: #{User.current.login} emailed from project #{@project.identifier}:"
selected_folders.each {|folder| Rails.logger.info "\tFolder #{folder}"} unless selected_folders.nil?
selected_files.each {|file| Rails.logger.info "\tFile #{file}"} unless selected_files.nil?
zip.files.each do |f|
log_activity(f,"emailing zip")
audit = DmsfFileRevisionAccess.new(:user_id => User.current.id, :dmsf_file_revision_id => f.last_revision.id,
:action => DmsfFileRevisionAccess::EmailAction)
audit.save!
end
@email_params = {"zipped_content" => ziped_content}
render :action => "email_entries"
@ -276,9 +275,12 @@ class DmsfController < ApplicationController
zip = DmsfZip.new
zip_entries(zip, selected_folders, selected_files)
Rails.logger.info "#{Time.now} from #{request.remote_ip}/#{request.env["HTTP_X_FORWARDED_FOR"]}: #{User.current.login} downloaded from project #{@project.identifier}:"
selected_folders.each {|folder| Rails.logger.info "\tFolder #{folder}"} unless selected_folders.nil?
selected_files.each {|file| Rails.logger.info "\tFile #{file}"} unless selected_files.nil?
zip.files.each do |f|
log_activity(f,"download zip")
audit = DmsfFileRevisionAccess.new(:user_id => User.current.id, :dmsf_file_revision_id => f.last_revision.id,
:action => DmsfFileRevisionAccess::DownloadAction)
audit.save!
end
send_file(zip.finish,
:filename => filename_for_content_disposition(@project.name + "-" + DateTime.now.strftime("%y%m%d%H%M%S") + ".zip"),
@ -304,8 +306,8 @@ class DmsfController < ApplicationController
max_files = 0
max_files = Setting.plugin_redmine_dmsf["dmsf_max_file_download"].to_i
if max_files > 0 && zip.file_count > max_files
raise ZipMaxFilesError, zip.file_count
if max_files > 0 && zip.files.length > max_files
raise ZipMaxFilesError, zip.files.length
end
zip

View File

@ -45,7 +45,6 @@ class DmsfFilesController < ApplicationController
return
end
end
Rails.logger.info "#{Time.now} from #{request.remote_ip}/#{request.env["HTTP_X_FORWARDED_FOR"]}: #{User.current.login} downloaded #{@project.identifier}://#{@file.dmsf_path_str} revision #{@revision.id}"
check_project(@revision.file)
send_revision
return
@ -113,7 +112,7 @@ class DmsfFilesController < ApplicationController
@file.reload
flash[:notice] = (flash[:notice].nil? ? "" : flash[:notice]) + l(:notice_file_revision_created)
Rails.logger.info "#{Time.now} from #{request.remote_ip}/#{request.env["HTTP_X_FORWARDED_FOR"]}: #{User.current.login} created new revision of file #{@project.identifier}://#{@file.dmsf_path_str}"
log_activity("new revision")
begin
DmsfMailer.deliver_files_updated(User.current, [@file])
rescue ActionView::MissingTemplate => e
@ -130,7 +129,7 @@ class DmsfFilesController < ApplicationController
if !@file.nil?
if @file.delete
flash[:notice] = l(:notice_file_deleted)
Rails.logger.info "#{Time.now} from #{request.remote_ip}/#{request.env["HTTP_X_FORWARDED_FOR"]}: #{User.current.login} deleted file #{@project.identifier}://#{@file.dmsf_path_str}"
log_activity("deleted")
DmsfMailer.deliver_files_deleted(User.current, [@file])
else
flash[:error] = l(:error_file_is_locked)
@ -143,7 +142,7 @@ class DmsfFilesController < ApplicationController
if !@revision.nil? && !@revision.deleted
if @revision.delete
flash[:notice] = l(:notice_revision_deleted)
Rails.logger.info "#{Time.now} from #{request.remote_ip}/#{request.env["HTTP_X_FORWARDED_FOR"]}: #{User.current.login} deleted revision #{@project.identifier}://#{@revision.file.dmsf_path_str}/#{@revision.id}"
log_activity("deleted")
else
# TODO: check this error handling
@revision.errors.each {|e| flash[:error] = e[1]}
@ -202,7 +201,15 @@ class DmsfFilesController < ApplicationController
private
def log_activity(action)
Rails.logger.info "#{Time.now.strftime('%Y-%m-%d %H:%M:%S')} #{User.current.login}@#{request.remote_ip}/#{request.env['HTTP_X_FORWARDED_FOR']}: #{action} dmsf://#{@file.project.identifier}/#{@file.id}/#{@revision.id if @revision}"
end
def send_revision
log_activity("downloaded")
access = DmsfFileRevisionAccess.new(:user_id => User.current.id, :dmsf_file_revision_id => @revision.id,
:action => DmsfFileRevisionAccess::DownloadAction)
access.save!
send_file(@revision.disk_file,
:filename => filename_for_content_disposition(@revision.name),
:type => @revision.detect_content_type,

View File

@ -138,8 +138,7 @@ class DmsfUploadController < ApplicationController
end
end
unless files.empty?
Rails.logger.info "#{Time.now} from #{request.remote_ip}/#{request.env["HTTP_X_FORWARDED_FOR"]}: #{User.current.login} uploaded for project #{@project.identifier}:"
files.each {|file| Rails.logger.info "\t#{file.dmsf_path_str}:"}
files.each {|file| log_activity(file, "uploaded")}
begin
DmsfMailer.deliver_files_updated(User.current, files)
rescue ActionView::MissingTemplate => e
@ -155,6 +154,10 @@ class DmsfUploadController < ApplicationController
private
def log_activity(file, action)
Rails.logger.info "#{Time.now.strftime('%Y-%m-%d %H:%M:%S')} #{User.current.login}@#{request.remote_ip}/#{request.env['HTTP_X_FORWARDED_FOR']}: #{action} dmsf://#{file.project.identifier}/#{file.id}/#{file.last_revision.id}"
end
def find_project
@project = Project.find(params[:id])
end

View File

@ -22,12 +22,12 @@ require 'iconv'
class DmsfZip
attr_reader :file_count
attr_reader :files
def initialize()
@zip = Tempfile.new(["dmsf_zip",".zip"])
@zip_file = Zip::ZipOutputStream.new(@zip.path)
@file_count = 0
@files = []
end
def finish
@ -56,7 +56,7 @@ class DmsfZip
@zip_file.write(buffer)
end
end
@file_count += 1
@files << file
end
def add_folder(folder, root_path = nil)

View File

@ -74,7 +74,8 @@ class DmsfFileRevision < ActiveRecord::Base
if Setting.plugin_redmine_dmsf["dmsf_really_delete_files"]
dependent = DmsfFileRevision.find(:all, :conditions =>
["disk_filename = :filename", {:filename => self.disk_filename}])
File.delete(self.disk_file) if dependent.length <= 1
File.delete(self.disk_file) if dependent.length <= 1 && File.exist?(self.disk_file)
DmsfFileRevisionAccess.find(:all, :conditions => ["dmsf_file_revision_id = ?", self.id]).each {|a| a.destroy}
self.destroy
else
self.deleted = true

View File

@ -0,0 +1,27 @@
# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2011 Vít Jonáš <vit.jonas@gmail.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class DmsfFileRevisionAccess < ActiveRecord::Base
unloadable
belongs_to :revision, :class_name => "DmsfFileRevision", :foreign_key => "dmsf_file_revision_id"
belongs_to :user
DownloadAction = 0
EmailAction = 1
end

View File

@ -19,17 +19,9 @@
class DmsfNormalization < ActiveRecord::Migration
def self.up
rename_column :dmsf_folders, :name, :title
create_table :dmsf_file_revision_audit do |t|
t.references :dmsf_file_revision, :null => false
t.integer :action, :default => 0, :null => false # 0 ... download, 1 ... email
t.references :user, :null => false
t.timestamps
end
end
def self.down
drop_table :dmsf_file_revision_audit
rename_column :dmsf_folders, :title, :name
end

View File

@ -0,0 +1,33 @@
# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2011 Vít Jonáš <vit.jonas@gmail.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Dmsf0901 < ActiveRecord::Migration
def self.up
create_table :dmsf_file_revision_accesses do |t|
t.references :dmsf_file_revision, :null => false
t.integer :action, :default => 0, :null => false # 0 ... download, 1 ... email
t.references :user, :null => false
t.timestamps
end
end
def self.down
drop_table :dmsf_file_revision_accesses
end
end