summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Wintermeyer <stefan.wintermeyer@amooma.de>2013-02-27 12:22:29 +0100
committerStefan Wintermeyer <stefan.wintermeyer@amooma.de>2013-02-27 12:22:29 +0100
commit67c1a0a951403a546250ea860a3e3d199cae2fce (patch)
treef86ec6cedf081a1a57005eca1661e9bead34e4de
parent5d8ce5f4775ac8bc5f523964e6e36f63ff3c4683 (diff)
parent211f558a86ae30cdd5b392ab1376e1393f97e22c (diff)
Merge branch 'develop'5.1-beta6
-rw-r--r--app/assets/javascripts/forms.js.coffee11
-rw-r--r--app/assets/stylesheets/gemeinschaft-generic.css.scss22
-rw-r--r--app/controllers/call_forwards_controller.rb60
-rw-r--r--app/controllers/calls_controller.rb54
-rw-r--r--app/controllers/config_siemens_controller.rb4
-rw-r--r--app/controllers/config_snom_controller.rb2
-rw-r--r--app/controllers/fax_documents_controller.rb18
-rw-r--r--app/controllers/group_memberships_controller.rb53
-rw-r--r--app/controllers/group_permissions_controller.rb51
-rw-r--r--app/controllers/groups_controller.rb52
-rw-r--r--app/controllers/intruders_controller.rb4
-rw-r--r--app/controllers/page_controller.rb2
-rw-r--r--app/controllers/restore_jobs_controller.rb25
-rw-r--r--app/controllers/ringtones_controller.rb12
-rw-r--r--app/controllers/sip_accounts_controller.rb32
-rw-r--r--app/controllers/trigger_controller.rb36
-rw-r--r--app/helpers/group_memberships_helper.rb2
-rw-r--r--app/helpers/group_permissions_helper.rb2
-rw-r--r--app/helpers/groups_helper.rb2
-rw-r--r--app/helpers/restore_jobs_helper.rb2
-rw-r--r--app/models/ability.rb13
-rw-r--r--app/models/backup_job.rb2
-rw-r--r--app/models/call.rb39
-rw-r--r--app/models/call_forward.rb128
-rw-r--r--app/models/fax_document.rb74
-rw-r--r--app/models/group.rb11
-rw-r--r--app/models/group_membership.rb37
-rw-r--r--app/models/group_permission.rb24
-rw-r--r--app/models/gs_parameter.rb8
-rw-r--r--app/models/hunt_group.rb2
-rw-r--r--app/models/intruder.rb35
-rw-r--r--app/models/phone_book_entry.rb2
-rw-r--r--app/models/phone_number.rb2
-rw-r--r--app/models/restore_job.rb24
-rw-r--r--app/models/ringtone.rb14
-rw-r--r--app/models/sip_account.rb45
-rw-r--r--app/models/softkey.rb6
-rw-r--r--app/models/user.rb16
-rw-r--r--app/uploaders/backup_file_uploader.rb6
-rw-r--r--app/uploaders/fax_document_uploader.rb19
-rw-r--r--app/views/backup_jobs/show.html.haml48
-rw-r--r--app/views/call_forwards/_form.html.haml2
-rw-r--r--app/views/call_forwards/_form_core.html.haml6
-rw-r--r--app/views/call_forwards/_index_core.html.haml31
-rw-r--r--app/views/call_forwards/index.html.haml2
-rw-r--r--app/views/call_forwards/show.html.haml26
-rw-r--r--app/views/calls/_form.html.haml7
-rw-r--r--app/views/calls/_form_core.html.haml2
-rw-r--r--app/views/calls/_index_core.html.haml34
-rw-r--r--app/views/calls/index.html.haml6
-rw-r--r--app/views/calls/new.html.haml3
-rw-r--r--app/views/fax_documents/_index_core.html.haml2
-rw-r--r--app/views/fax_documents/show.html.haml2
-rw-r--r--app/views/group_memberships/_form.html.haml7
-rw-r--r--app/views/group_memberships/_form_core.html.haml4
-rw-r--r--app/views/group_memberships/_index_core.html.haml11
-rw-r--r--app/views/group_memberships/edit.html.haml3
-rw-r--r--app/views/group_memberships/index.html.haml6
-rw-r--r--app/views/group_memberships/new.html.haml3
-rw-r--r--app/views/group_memberships/show.html.haml10
-rw-r--r--app/views/group_permissions/_form.html.haml7
-rw-r--r--app/views/group_permissions/_form_core.html.haml3
-rw-r--r--app/views/group_permissions/_index_core.html.haml11
-rw-r--r--app/views/group_permissions/edit.html.haml3
-rw-r--r--app/views/group_permissions/index.html.haml6
-rw-r--r--app/views/group_permissions/new.html.haml3
-rw-r--r--app/views/group_permissions/show.html.haml10
-rw-r--r--app/views/groups/_form.html.haml7
-rw-r--r--app/views/groups/_form_core.html.haml4
-rw-r--r--app/views/groups/_index_core.html.haml17
-rw-r--r--app/views/groups/edit.html.haml3
-rw-r--r--app/views/groups/index.html.haml6
-rw-r--r--app/views/groups/new.html.haml3
-rw-r--r--app/views/groups/show.html.haml25
-rw-r--r--app/views/gs_nodes/sync.xml.haml2
-rw-r--r--app/views/intruders/_index_core.html.haml9
-rw-r--r--app/views/layouts/_navbar.html.haml29
-rw-r--r--app/views/layouts/application.html.haml2
-rw-r--r--app/views/phone_books/_index_core.html.haml7
-rw-r--r--app/views/phone_numbers/_form_core.html.haml2
-rw-r--r--app/views/phone_numbers/show.html.haml15
-rw-r--r--app/views/restore_jobs/_form.html.haml7
-rw-r--r--app/views/restore_jobs/_form_core.html.haml2
-rw-r--r--app/views/restore_jobs/_index_core.html.haml12
-rw-r--r--app/views/restore_jobs/index.html.haml6
-rw-r--r--app/views/restore_jobs/new.html.haml3
-rw-r--r--app/views/restore_jobs/show.html.haml22
-rw-r--r--app/views/ringtones/_form_core.html.haml2
-rw-r--r--app/views/ringtones/_index_core.html.haml4
-rw-r--r--app/views/ringtones/index.html.haml4
-rw-r--r--app/views/sessions/new.html.haml16
-rw-r--r--app/views/sip_accounts/_form_core.html.haml2
-rw-r--r--app/views/sip_accounts/_index_core.html.haml4
-rw-r--r--app/views/sip_accounts/show.html.haml33
-rw-r--r--app/views/users/show.html.haml20
-rw-r--r--config/backup.rb25
-rw-r--r--config/initializers/simple_form.rb1
-rw-r--r--config/locales/views/call_forwards/de.yml14
-rw-r--r--config/locales/views/call_forwards/en.yml14
-rw-r--r--config/locales/views/calls/de.yml37
-rw-r--r--config/locales/views/calls/en.yml37
-rw-r--r--config/locales/views/fax_accounts/de.yml22
-rw-r--r--config/locales/views/fax_documents/de.yml2
-rw-r--r--config/locales/views/gemeinschaft_setups/de.yml2
-rw-r--r--config/locales/views/gemeinschaft_setups/en.yml2
-rw-r--r--config/locales/views/group_memberships/de.yml50
-rw-r--r--config/locales/views/group_memberships/en.yml50
-rw-r--r--config/locales/views/group_permissions/de.yml50
-rw-r--r--config/locales/views/group_permissions/en.yml50
-rw-r--r--config/locales/views/groups/de.yml50
-rw-r--r--config/locales/views/groups/en.yml50
-rw-r--r--config/locales/views/phone_book_entries/de.yml2
-rw-r--r--config/locales/views/phone_books/de.yml2
-rw-r--r--config/locales/views/restore_jobs/de.yml45
-rw-r--r--config/locales/views/restore_jobs/en.yml45
-rw-r--r--config/locales/views/sip_accounts/de.yml2
-rw-r--r--config/locales/views/sip_accounts/en.yml2
-rw-r--r--config/routes.rb13
-rw-r--r--config/schedule.rb2
-rw-r--r--db/migrate/20130109090000_populate_gs_parameter_with_dialplan_defaults.rb4
-rw-r--r--db/migrate/20130213110000_add_sounds_to_parameters.rb2
-rw-r--r--db/migrate/20130219135000_remove_sound_prefix_from_conference_parameters.rb8
-rw-r--r--db/migrate/20130222074610_create_groups.rb14
-rw-r--r--db/migrate/20130222074652_create_group_memberships.rb14
-rw-r--r--db/migrate/20130222092313_create_group_permissions.rb14
-rw-r--r--db/migrate/20130224081700_groups_to_user_groups_in_routes.rb19
-rw-r--r--db/migrate/20130224091700_add_initial_groups.rb22
-rw-r--r--db/migrate/20130225091200_add_destinationable_to_call_forward.rb21
-rw-r--r--db/migrate/20130225160423_create_restore_jobs.rb13
-rw-r--r--db/schema.rb33
-rw-r--r--lib/tasks/backup.rake52
-rw-r--r--lib/tasks/send_fax_notifications.rake2
-rw-r--r--misc/freeswitch/conf/freeswitch.xml16
-rw-r--r--misc/freeswitch/scripts/common/call_forwarding.lua55
-rw-r--r--misc/freeswitch/scripts/common/conference.lua6
-rw-r--r--misc/freeswitch/scripts/common/group.lua88
-rw-r--r--misc/freeswitch/scripts/common/phone_number.lua55
-rw-r--r--misc/freeswitch/scripts/common/str.lua34
-rw-r--r--misc/freeswitch/scripts/configuration.lua3
-rw-r--r--misc/freeswitch/scripts/dialplan/call_parking.lua16
-rw-r--r--misc/freeswitch/scripts/dialplan/dialplan.lua136
-rw-r--r--misc/freeswitch/scripts/dialplan/dtmf.lua8
-rw-r--r--misc/freeswitch/scripts/dialplan/fax.lua8
-rw-r--r--misc/freeswitch/scripts/dialplan/functions.lua141
-rw-r--r--misc/freeswitch/scripts/dialplan/sip_call.lua26
-rw-r--r--misc/freeswitch/scripts/dialplan/user.lua17
-rw-r--r--misc/freeswitch/scripts/dialplan/voicemail.lua2
-rw-r--r--misc/freeswitch/scripts/send_fax.lua5
-rwxr-xr-xscript/logout_phones.sh3
-rw-r--r--test/functional/group_memberships_controller_test.rb49
-rw-r--r--test/functional/group_permissions_controller_test.rb49
-rw-r--r--test/functional/groups_controller_test.rb49
-rw-r--r--test/functional/restore_jobs_controller_test.rb49
-rw-r--r--test/unit/group_membership_test.rb7
-rw-r--r--test/unit/group_permission_test.rb7
-rw-r--r--test/unit/group_test.rb7
-rw-r--r--test/unit/restore_job_test.rb7
157 files changed, 2553 insertions, 556 deletions
diff --git a/app/assets/javascripts/forms.js.coffee b/app/assets/javascripts/forms.js.coffee
new file mode 100644
index 0000000..42b1c45
--- /dev/null
+++ b/app/assets/javascripts/forms.js.coffee
@@ -0,0 +1,11 @@
+# Simple Form Toggle for required fields
+$(document).ready ->
+ validate_fields = (obj)->
+ if ($(obj).val() == "")
+ $(obj).addClass "invalid"
+ else
+ $(obj).removeClass "invalid"
+
+ sel = "input.required, textarea.required"
+ $(sel).each (i, e)-> validate_fields(e)
+ $(sel).keyup -> validate_fields(this)
diff --git a/app/assets/stylesheets/gemeinschaft-generic.css.scss b/app/assets/stylesheets/gemeinschaft-generic.css.scss
index fbeaa1f..9448b84 100644
--- a/app/assets/stylesheets/gemeinschaft-generic.css.scss
+++ b/app/assets/stylesheets/gemeinschaft-generic.css.scss
@@ -25,6 +25,28 @@ li.display {
}
input, textarea, .uneditable-input {
width: 500px;
+ @media (max-width: 979px) {
+ width: 200px;
+ }
+ @media (max-width: 480px) {
+ width: 96%;
+ }
+}
+input, textarea {
+ &.invalid {
+ box-shadow: inset -9px 0px 0px rgb(255, 219, 219), inset -14px 0px 0px rgb(255, 245, 245) !important;
+ }
+}
+
+select {
+ width: 520px;
+ @media (max-width: 979px) {
+ width: 220px;
+ }
+ @media (max-width: 480px) {
+ width: 99.5%;
+ }
+
}
@media (max-width: 979px) {
diff --git a/app/controllers/call_forwards_controller.rb b/app/controllers/call_forwards_controller.rb
index b1ced87..34fb77a 100644
--- a/app/controllers/call_forwards_controller.rb
+++ b/app/controllers/call_forwards_controller.rb
@@ -1,7 +1,9 @@
class CallForwardsController < ApplicationController
- load_and_authorize_resource :phone_number
- load_and_authorize_resource :call_forward, :through => [:phone_number]
+ load_resource :phone_number
+ load_resource :sip_account
+ load_and_authorize_resource :call_forward, :through => [:phone_number, :sip_account]
+ before_filter :set_and_authorize_parent
before_filter :spread_breadcrumbs
class CallForwardingDestination
@@ -20,7 +22,7 @@ class CallForwardsController < ApplicationController
end
def new
- @call_forward = @phone_number.call_forwards.build
+ @call_forward = @parent.call_forwards.build
@call_forward.depth = GsParameter.get('DEFAULT_CALL_FORWARD_DEPTH')
@call_forward.active = true
@call_forwarding_destinations = call_forwarding_destination_types()
@@ -33,7 +35,7 @@ class CallForwardsController < ApplicationController
end
end
- if @phone_number.call_forwards.where(
+ if @parent.call_forwards.where(
:call_forward_case_id => CallForwardCase.find_by_value('noanswer').id,
:active => true
).count == 0
@@ -43,10 +45,11 @@ class CallForwardsController < ApplicationController
end
def create
- @call_forward = @phone_number.call_forwards.build( params[:call_forward] )
+ @call_forward = @parent.call_forwards.build( params[:call_forward] )
if @call_forward.save
- redirect_to phone_number_call_forward_path( @phone_number, @call_forward ), :notice => t('call_forwards.controller.successfuly_created')
+ m = method( :"#{@parent.class.name.underscore}_call_forwards_url" )
+ redirect_to m.( @parent ), :notice => t('call_forwards.controller.successfuly_created')
else
@available_call_forward_cases = CallForwardCase.all
render :new
@@ -61,7 +64,8 @@ class CallForwardsController < ApplicationController
def update
@available_call_forward_cases = CallForwardCase.all
if @call_forward.update_attributes(params[:call_forward])
- redirect_to phone_number_call_forward_path( @phone_number, @call_forward ), :notice => t('call_forwards.controller.successfuly_updated')
+ m = method( :"#{@parent.class.name.underscore}_call_forwards_url" )
+ redirect_to m.( @parent ), :notice => t('call_forwards.controller.successfuly_updated')
else
@call_forwarding_destinations = call_forwarding_destination_types()
render :edit
@@ -70,30 +74,48 @@ class CallForwardsController < ApplicationController
def destroy
@call_forward.destroy
- redirect_to phone_number_call_forwards_path( @phone_number ), :notice => t('call_forwards.controller.successfuly_destroyed')
+ m = method( :"#{@parent.class.name.underscore}_call_forwards_url" )
+ redirect_to m.( @parent ), :notice => t('call_forwards.controller.successfuly_destroyed')
end
private
+ private
+ def set_and_authorize_parent
+ @parent = @sip_account || @phone_number
+ authorize! :read, @parent
+ end
+
def spread_breadcrumbs
- if @phone_number && @phone_number.phone_numberable_type == 'SipAccount'
- @sip_account = @phone_number.phone_numberable
+ if @parent
+ if @parent.class == PhoneNumber && @parent.phone_numberable_type == 'SipAccount'
+ @sip_account = @parent.phone_numberable
+ end
if @sip_account.sip_accountable_type == 'User'
- @user = @phone_number.phone_numberable.sip_accountable
- add_breadcrumb t("users.index.page_title"), tenant_users_path(@user.current_tenant)
- add_breadcrumb @user, tenant_users_path(@user.current_tenant, @user)
- add_breadcrumb t("sip_accounts.index.page_title"), user_sip_accounts_path(@user)
- add_breadcrumb @sip_account, user_sip_account_path(@user, @sip_account)
+ @user = @sip_account.sip_accountable
+ if @parent.class == PhoneNumber
+ add_breadcrumb t("users.index.page_title"), tenant_users_path(@user.current_tenant)
+ add_breadcrumb @user, tenant_users_path(@user.current_tenant, @user)
+ add_breadcrumb t("sip_accounts.index.page_title"), user_sip_accounts_path(@user)
+ add_breadcrumb @sip_account, user_sip_account_path(@user, @sip_account)
+ add_breadcrumb t("phone_numbers.index.page_title"), sip_account_phone_numbers_path(@sip_account)
+ add_breadcrumb @parent, sip_account_phone_number_path(@sip_account, @parent)
+ elsif @parent.class == SipAccount
+ add_breadcrumb t("users.index.page_title"), tenant_users_path(@user.current_tenant)
+ add_breadcrumb @user, tenant_users_path(@user.current_tenant, @user)
+ add_breadcrumb t("sip_accounts.index.page_title"), user_sip_accounts_path(@user)
+ end
end
if @sip_account.sip_accountable_type == 'Tenant'
@tenant = @sip_account.sip_accountable
add_breadcrumb t("sip_accounts.index.page_title"), tenant_sip_accounts_path(@tenant)
add_breadcrumb @sip_account, tenant_sip_account_path(@tenant, @sip_account)
end
- add_breadcrumb t("phone_numbers.index.page_title"), sip_account_phone_numbers_path(@sip_account)
- add_breadcrumb @phone_number, sip_account_phone_number_path(@sip_account, @phone_number)
- add_breadcrumb t("call_forwards.index.page_title"), phone_number_call_forwards_path(@phone_number)
+
+ m = method( :"#{@parent.class.name.underscore}_call_forwards_url" )
+ add_breadcrumb t("call_forwards.index.page_title"), m.(@parent)
if @call_forward && !@call_forward.new_record?
- add_breadcrumb @call_forward, phone_number_call_forward_path(@phone_number, @call_forward)
+ m = method( :"#{@parent.class.name.underscore}_call_forward_path" )
+ add_breadcrumb @call_forward, m.(@parent, @call_forward)
end
end
end
diff --git a/app/controllers/calls_controller.rb b/app/controllers/calls_controller.rb
index d5f3b42..5534b1b 100644
--- a/app/controllers/calls_controller.rb
+++ b/app/controllers/calls_controller.rb
@@ -1,6 +1,58 @@
class CallsController < ApplicationController
+ load_resource :sip_account
+ load_resource :call
+ before_filter :set_and_authorize_parent
+
def index
- @calls = Call.all
+ if @parent
+ @calls = @parent.calls
+ else
+ @calls = Call.all
+ end
+ end
+
+ def new
+ if !params[:url].blank?
+ protocol, separator, phone_number = params[:url].partition(':')
+ if ! phone_number.blank?
+ @call = @parent.calls.new()
+ @call.dest = phone_number
+ end
+ elsif !params[:number].blank?
+ @call = @parent.calls.new()
+ @call.dest = params[:number]
+ end
+ end
+
+ def show
+ redirect_to :index
+ end
+
+ def create
+ params[:call][:sip_account] = @sip_account
+ @call = Call.create(params[:call])
+
+ if @call && @call.call
+ m = method( :"#{@parent.class.name.underscore}_calls_url" )
+ redirect_to m.( @parent ), :notice => t('calls.controller.successfuly_created')
+ else
+ render :new
+ end
+ end
+
+ def destroy
+ @call.destroy
+ if @parent
+ m = method( :"#{@parent.class.name.underscore}_calls_url" )
+ else
+ m = method( :"calls_url" )
+ end
+ redirect_to m.(@parent), :notice => t('calls.controller.successfuly_destroyed')
+ end
+
+ private
+ def set_and_authorize_parent
+ @parent = @sip_account
end
end
diff --git a/app/controllers/config_siemens_controller.rb b/app/controllers/config_siemens_controller.rb
index bbeba46..1966d49 100644
--- a/app/controllers/config_siemens_controller.rb
+++ b/app/controllers/config_siemens_controller.rb
@@ -1068,8 +1068,8 @@ class ConfigSiemensController < ApplicationController
phone_numbers.push(phone_number.number)
assistant_call_forwardings = phone_number.call_forwards.where(:call_forward_case_id => CallForwardCase.where(:value => 'assistant').first.id)
assistant_call_forwardings.each do |assistant_call_forwarding|
- if assistant_call_forwarding.call_forwardable_type == 'HuntGroup' && assistant_call_forwarding.call_forwardable_id.to_i > 0
- hunt_groups.push(assistant_call_forwarding.call_forwardable_id.to_i)
+ if assistant_call_forwarding.destinationable_type == 'HuntGroup' && assistant_call_forwarding.destinationable_id.to_i > 0
+ hunt_groups.push(assistant_call_forwarding.destinationable_id.to_i)
end
end
end
diff --git a/app/controllers/config_snom_controller.rb b/app/controllers/config_snom_controller.rb
index 76fa633..eb94038 100644
--- a/app/controllers/config_snom_controller.rb
+++ b/app/controllers/config_snom_controller.rb
@@ -799,7 +799,7 @@ AAAA'
end
phone_book_entry.phone_numbers.each do |phone_number|
if phone_book_entry.phone_numbers.count > 1
- entry_name = " #{phone_number.name} #{phone_number.number}"
+ entry_name = "- #{phone_number.name} #{phone_number.number}"
else
entry_name = "#{phone_book_entry.to_s} #{phone_number.number}"
end
diff --git a/app/controllers/fax_documents_controller.rb b/app/controllers/fax_documents_controller.rb
index 5653683..c2b3083 100644
--- a/app/controllers/fax_documents_controller.rb
+++ b/app/controllers/fax_documents_controller.rb
@@ -31,6 +31,24 @@ class FaxDocumentsController < ApplicationController
)
end
}
+ format.tiff {
+ caller_number = @fax_document.caller_id_number.to_s.gsub(/[^0-9]/, '')
+ if caller_number.blank?
+ caller_number = 'anonymous'
+ end
+
+ if @fax_document.tiff
+ send_file @fax_document.tiff, :type => "image/tiff",
+ :filename => "#{@fax_document.created_at.strftime('%Y%m%d-%H%M%S')}-#{caller_number}.tiff"
+ else
+ render(
+ :status => 404,
+ :layout => false,
+ :content_type => 'text/plain',
+ :text => "<!-- Raw image not found -->",
+ )
+ end
+ }
end
end
diff --git a/app/controllers/group_memberships_controller.rb b/app/controllers/group_memberships_controller.rb
new file mode 100644
index 0000000..e0f897b
--- /dev/null
+++ b/app/controllers/group_memberships_controller.rb
@@ -0,0 +1,53 @@
+class GroupMembershipsController < ApplicationController
+ load_and_authorize_resource :group
+ load_and_authorize_resource :group_membership, :through => [:group]
+
+ before_filter :spread_breadcrumbs
+
+ def index
+ end
+
+ def show
+ end
+
+ def new
+ end
+
+ def create
+ if params[:group_membership][:item_type].blank?
+ params[:group_membership][:item_type] = @group.group_memberships.first.item_type
+ end
+ @group_membership = @group.group_memberships.new(params[:group_membership])
+ if @group_membership.save
+ redirect_to action: "index", :notice => t('group_memberships.controller.successfuly_created')
+ else
+ render :new
+ end
+ end
+
+ def edit
+ end
+
+ def update
+ if @group_membership.update_attributes(params[:group_membership])
+ redirect_to action: "index", :notice => t('group_memberships.controller.successfuly_updated')
+ else
+ render :edit
+ end
+ end
+
+ def destroy
+ @group_membership.destroy
+ redirect_to action: "index", :notice => t('group_memberships.controller.successfuly_destroyed')
+ end
+
+ private
+ def spread_breadcrumbs
+ add_breadcrumb t("groups.index.page_title"), groups_path
+ add_breadcrumb @group, group_path(@group)
+ add_breadcrumb t("group_memberships.index.page_title"), group_group_memberships_path(@group)
+ if @group_membership && !@group_membership.new_record?
+ add_breadcrumb @group_membership, group_group_membership_path(@group, @group_membership)
+ end
+ end
+end
diff --git a/app/controllers/group_permissions_controller.rb b/app/controllers/group_permissions_controller.rb
new file mode 100644
index 0000000..b6517b1
--- /dev/null
+++ b/app/controllers/group_permissions_controller.rb
@@ -0,0 +1,51 @@
+class GroupPermissionsController < ApplicationController
+ load_and_authorize_resource :group
+ load_and_authorize_resource :group_permission, :through => [:group]
+
+ before_filter :spread_breadcrumbs
+
+ def index
+ end
+
+ def show
+ end
+
+ def new
+ @group_permission.target_group_id = @group_permission.group_id
+ end
+
+ def create
+ @group_permission = @group.group_permissions.new(params[:group_permission])
+ if @group_permission.save
+ redirect_to action: "index", :notice => t('group_permissions.controller.successfuly_created')
+ else
+ render :new
+ end
+ end
+
+ def edit
+ end
+
+ def update
+ if @group_permission.update_attributes(params[:group_permission])
+ redirect_to action: "index", :notice => t('group_permissions.controller.successfuly_updated')
+ else
+ render :edit
+ end
+ end
+
+ def destroy
+ @group_permission.destroy
+ redirect_to action: "index", :notice => t('group_permissions.controller.successfuly_destroyed')
+ end
+
+ private
+ def spread_breadcrumbs
+ add_breadcrumb t("groups.index.page_title"), groups_path
+ add_breadcrumb @group, group_path(@group)
+ add_breadcrumb t("group_permissions.index.page_title"), group_group_permissions_path(@group)
+ if @group_permission && !@group_permission.new_record?
+ add_breadcrumb @group_permission, group_group_permission_path(@group, @group_permission)
+ end
+ end
+end
diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb
new file mode 100644
index 0000000..74ad7c8
--- /dev/null
+++ b/app/controllers/groups_controller.rb
@@ -0,0 +1,52 @@
+class GroupsController < ApplicationController
+ load_and_authorize_resource :group
+ before_filter :spread_breadcrumbs
+
+ def index
+ @groups = Group.all
+ end
+
+ def show
+ @group = Group.find(params[:id])
+ end
+
+ def new
+ @group = Group.new
+ end
+
+ def create
+ @group = Group.new(params[:group])
+ if @group.save
+ redirect_to @group, :notice => t('groups.controller.successfuly_created')
+ else
+ render :new
+ end
+ end
+
+ def edit
+ @group = Group.find(params[:id])
+ end
+
+ def update
+ @group = Group.find(params[:id])
+ if @group.update_attributes(params[:group])
+ redirect_to @group, :notice => t('groups.controller.successfuly_updated')
+ else
+ render :edit
+ end
+ end
+
+ def destroy
+ @group = Group.find(params[:id])
+ @group.destroy
+ redirect_to groups_url, :notice => t('groups.controller.successfuly_destroyed')
+ end
+
+ private
+ def spread_breadcrumbs
+ add_breadcrumb t("groups.index.page_title"), groups_path
+ if @group && !@group.new_record?
+ add_breadcrumb @group, @group
+ end
+ end
+end
diff --git a/app/controllers/intruders_controller.rb b/app/controllers/intruders_controller.rb
index 147e06d..d3c767e 100644
--- a/app/controllers/intruders_controller.rb
+++ b/app/controllers/intruders_controller.rb
@@ -1,6 +1,8 @@
class IntrudersController < ApplicationController
+ load_and_authorize_resource :intruder
+
def index
- @intruders = Intruder.all
+ @intruders = Intruder.order('list_type ASC, contact_last DESC').all
spread_breadcrumbs
end
diff --git a/app/controllers/page_controller.rb b/app/controllers/page_controller.rb
index ed48e3c..10ecf2c 100644
--- a/app/controllers/page_controller.rb
+++ b/app/controllers/page_controller.rb
@@ -7,6 +7,8 @@ class PageController < ApplicationController
def index
if current_user
redirect_to [current_user.current_tenant, current_user]
+ else
+ redirect_to log_in_path
end
end
diff --git a/app/controllers/restore_jobs_controller.rb b/app/controllers/restore_jobs_controller.rb
new file mode 100644
index 0000000..bfecc33
--- /dev/null
+++ b/app/controllers/restore_jobs_controller.rb
@@ -0,0 +1,25 @@
+class RestoreJobsController < ApplicationController
+ skip_before_filter :start_setup_if_new_installation, :only => [:new, :create, :show, :index]
+
+ load_and_authorize_resource :restore_job
+
+ def index
+ end
+
+ def show
+ end
+
+ def new
+ end
+
+ def create
+ @restore_job.state = 'new'
+
+ if @restore_job.save
+ session[:user_id] = nil
+ redirect_to @restore_job, :notice => t('restore_jobs.controller.successfuly_created')
+ else
+ render :new
+ end
+ end
+end
diff --git a/app/controllers/ringtones_controller.rb b/app/controllers/ringtones_controller.rb
index 7ffe30e..e5a4f64 100644
--- a/app/controllers/ringtones_controller.rb
+++ b/app/controllers/ringtones_controller.rb
@@ -1,7 +1,8 @@
class RingtonesController < ApplicationController
load_resource :phone_number
+ load_resource :sip_account
load_resource :boss_assistant_cooperation
- load_and_authorize_resource :ringtone, :through => [:phone_number, :boss_assistant_cooperation]
+ load_and_authorize_resource :ringtone, :through => [:phone_number, :sip_account, :boss_assistant_cooperation]
before_filter :set_parent
before_filter :spread_breadcrumbs
@@ -14,12 +15,13 @@ class RingtonesController < ApplicationController
def new
@ringtone = @parent.ringtones.build
+ @ringtone.bellcore_id = GsParameter.get('default_ringtone', 'dialplan', 'parameters')
end
def create
@ringtone = @parent.ringtones.build(params[:ringtone])
if @ringtone.save
- redirect_to phone_number_ringtone_path(@parent, @ringtone), :notice => t('ringtones.controller.successfuly_created')
+ redirect_to method( :"#{@parent.class.name.underscore}_ringtones_url" ).(@parent), :notice => t('ringtones.controller.successfuly_created')
else
render :new
end
@@ -30,7 +32,7 @@ class RingtonesController < ApplicationController
def update
if @ringtone.update_attributes(params[:ringtone])
- redirect_to method( :"#{@parent.class.name.underscore}_ringtone_path" ).(@ringtone.ringtoneable, @ringtone), :notice => t('ringtones.controller.successfuly_updated')
+ redirect_to method( :"#{@parent.class.name.underscore}_ringtones_url" ).(@parent), :notice => t('ringtones.controller.successfuly_updated')
else
render :edit
end
@@ -38,12 +40,12 @@ class RingtonesController < ApplicationController
def destroy
@ringtone.destroy
- redirect_to phone_number_ringtones_path(@parent), :notice => t('ringtones.controller.successfuly_destroyed')
+ redirect_to method( :"#{@parent.class.name.underscore}_ringtones_url" ).(@parent), :notice => t('ringtones.controller.successfuly_destroyed')
end
private
def set_parent
- @parent = @phone_number || @boss_assistant_cooperation
+ @parent = @phone_number || @boss_assistant_cooperation || @sip_account
end
def spread_breadcrumbs
diff --git a/app/controllers/sip_accounts_controller.rb b/app/controllers/sip_accounts_controller.rb
index b5c3ae4..621bd3c 100644
--- a/app/controllers/sip_accounts_controller.rb
+++ b/app/controllers/sip_accounts_controller.rb
@@ -1,6 +1,7 @@
class SipAccountsController < ApplicationController
load_resource :user
load_resource :tenant
+ load_and_authorize_resource :sip_account, :only => [:call]
load_and_authorize_resource :sip_account, :through => [:user, :tenant ]
before_filter :set_and_authorize_parent
@@ -10,6 +11,7 @@ class SipAccountsController < ApplicationController
end
def show
+ @register_tel_protocol = "#{request.protocol}#{request.host_with_port}/sip_accounts/#{@sip_account.try(:id)}/call?url=%s"
end
def new
@@ -74,6 +76,36 @@ class SipAccountsController < ApplicationController
redirect_to :root, :notice => t('sip_accounts.controller.successfuly_destroyed')
end
+ def call
+ if !params[:url].blank?
+ protocol, separator, phone_number = params[:url].partition(':')
+ if ! phone_number.blank?
+ @sip_account.call(phone_number)
+ render(
+ :status => 200,
+ :layout => false,
+ :content_type => 'text/plain',
+ :text => "<!-- CALL -->",
+ )
+ return;
+ end
+ render(
+ :status => 404,
+ :layout => false,
+ :content_type => 'text/plain',
+ :text => "<!-- Number not found -->",
+ )
+ return;
+ end
+
+ render(
+ :status => 404,
+ :layout => false,
+ :content_type => 'text/plain',
+ :text => "<!-- Call URL not found -->",
+ )
+ end
+
private
def set_and_authorize_parent
@parent = @user || @tenant
diff --git a/app/controllers/trigger_controller.rb b/app/controllers/trigger_controller.rb
index 2b491be..64a5f91 100644
--- a/app/controllers/trigger_controller.rb
+++ b/app/controllers/trigger_controller.rb
@@ -1,7 +1,4 @@
class TriggerController < ApplicationController
- TIFF_FUFFIX = ".tiff"
- PDF_SUFFIX = ".pdf"
- TMP_DIR = "/tmp/"
def voicemail
if !params[:sip_account_id].blank?
@@ -68,44 +65,29 @@ class TriggerController < ApplicationController
if fax_account
fax_account.fax_documents.where(:state => 'received').each do |fax_document|
- tiff_file = File.basename(fax_document.tiff.to_s)
+ pdf_file = fax_document.tiff_to_pdf
- if !File.exists?( "#{TMP_DIR}#{tiff_file}" )
+ if !pdf_file
fax_document.state = 'unsuccessful'
fax_document.save
next
end
- paper_size = "letter"
- pdf_file = "#{TMP_DIR}#{File.basename(tiff_file, TIFF_FUFFIX)}#{PDF_SUFFIX}"
-
- system "tiff2pdf \\
- -o \"#{pdf_file}\" \\
- -p #{paper_size} \\
- -a \"#{fax_document.remote_station_id}\" \\
- -c \"AMOOMA Gemeinschaft version #{GsParameter.get('GEMEINSCHAFT_VERSION')}\" \\
- -t \"#{fax_document.remote_station_id}\" \"#{TMP_DIR}#{tiff_file}\""
-
- if !File.exists?( pdf_file )
- fax_document.state = 'unsuccessful'
- fax_document.save
- next
+ working_path, tiff_file = File.split(fax_document.tiff)
+ if fax_document.store_dir != working_path
+ FileUtils.mkdir(fax_document.store_dir)
+ FileUtils.mv(fax_document.tiff, fax_document.store_dir)
+ fax_document.tiff = "#{fax_document.store_dir}/#{tiff_file}"
end
fax_document.document = File.open(pdf_file)
fax_document.state = 'successful'
if fax_document.save
- Notifications.new_fax(fax_document).deliver
- begin
- File.delete("#{TMP_DIR}#{tiff_file}");
- rescue => e
- logger.error "Raw fax file could not be deleted: #{TMP_DIR}#{tiff_file} => #{e.inspect}"
- end
begin
- File.delete(pdf_file);
+ File.delete(pdf_file)
rescue => e
- logger.error "PDF fax file could not be deleted: #{TMP_DIR}#{pdf_file} => #{e.inspect}"
+ logger.error "PDF fax file could not be deleted: #{pdf_file} => #{e.inspect}"
end
fax_document.tiff = nil
fax_document.save
diff --git a/app/helpers/group_memberships_helper.rb b/app/helpers/group_memberships_helper.rb
new file mode 100644
index 0000000..837bafd
--- /dev/null
+++ b/app/helpers/group_memberships_helper.rb
@@ -0,0 +1,2 @@
+module GroupMembershipsHelper
+end
diff --git a/app/helpers/group_permissions_helper.rb b/app/helpers/group_permissions_helper.rb
new file mode 100644
index 0000000..45571d0
--- /dev/null
+++ b/app/helpers/group_permissions_helper.rb
@@ -0,0 +1,2 @@
+module GroupPermissionsHelper
+end
diff --git a/app/helpers/groups_helper.rb b/app/helpers/groups_helper.rb
new file mode 100644
index 0000000..c091b2f
--- /dev/null
+++ b/app/helpers/groups_helper.rb
@@ -0,0 +1,2 @@
+module GroupsHelper
+end
diff --git a/app/helpers/restore_jobs_helper.rb b/app/helpers/restore_jobs_helper.rb
new file mode 100644
index 0000000..9a5d120
--- /dev/null
+++ b/app/helpers/restore_jobs_helper.rb
@@ -0,0 +1,2 @@
+module RestoreJobsHelper
+end
diff --git a/app/models/ability.rb b/app/models/ability.rb
index d66577d..3ba4481 100644
--- a/app/models/ability.rb
+++ b/app/models/ability.rb
@@ -90,6 +90,11 @@ class Ability
# SIM cards
#
cannot [:edit, :update], SimCard
+
+ # Restore is only possible on a new system.
+ #
+ cannot :manage, RestoreJob
+
else
# Any user can do the following stuff.
#
@@ -126,11 +131,12 @@ class Ability
# SipAccounts and Phones
#
- can :read, SipAccount, :sip_accountable_type => 'User', :sip_accountable_id => user.id
+ can [:read, :call], SipAccount, :sip_accountable_type => 'User', :sip_accountable_id => user.id
user.sip_accounts.each do |sip_account|
can :read, PhoneNumber, :id => sip_account.phone_number_ids
- can :manage, CallForward, :phone_number_id => sip_account.phone_number_ids
+ can :manage, CallForward, :call_forwardable_id => sip_account.phone_number_ids
can :manage, Ringtone, :ringtoneable_type => 'PhoneNumber', :ringtoneable_id => sip_account.phone_number_ids
+ can :manage, Ringtone, :ringtoneable_type => 'SipAccount', :ringtoneable_id => sip_account.id
can [:read, :destroy, :call] , CallHistory, :id => sip_account.call_history_ids
end
can :read, Phone, :phoneable_type => 'User', :phoneable_id => user.id
@@ -158,7 +164,7 @@ class Ability
# User can manage CallForwards of the PhoneNumbers of his
# own SipAccounts:
#
- can :manage, CallForward, :phone_number_id => user.phone_number_ids
+ can :manage, CallForward, :call_forwardable_id => user.phone_number_ids
# SoftkeyFunctions
#
@@ -176,6 +182,7 @@ class Ability
#
can :create, GemeinschaftSetup
can :manage, SipDomain
+ can [:create, :new, :show, :index], RestoreJob
end
end
diff --git a/app/models/backup_job.rb b/app/models/backup_job.rb
index 96574a7..a04f6c0 100644
--- a/app/models/backup_job.rb
+++ b/app/models/backup_job.rb
@@ -32,7 +32,7 @@ class BackupJob < ActiveRecord::Base
if tmp_backup_directory.blank?
self.state = 'failed'
else
- system "cd #{backup_directory} && tar czf #{backup_name_prefix}#{File.basename(tmp_backup_directory)}.tar.gz #{File.basename(tmp_backup_directory)}"
+ system "cd #{backup_directory} && sudo /bin/tar czf #{backup_name_prefix}#{File.basename(tmp_backup_directory)}.tar.gz #{File.basename(tmp_backup_directory)}"
require 'fileutils'
FileUtils.rm_rf tmp_backup_directory
file = File::Stat.new("#{backup_directory}/#{backup_name_prefix}#{File.basename(tmp_backup_directory)}.tar.gz")
diff --git a/app/models/call.rb b/app/models/call.rb
index c0f0f08..db6d9d6 100644
--- a/app/models/call.rb
+++ b/app/models/call.rb
@@ -1,9 +1,31 @@
class Call < ActiveRecord::Base
self.table_name = 'detailed_calls'
self.primary_key = 'uuid'
+
+ attr_writer :sip_account_id
+
+ validates :dest,
+ :presence => true
- def readonly?
- return true
+ def create(attributes=nil)
+ if ! attributes
+ return
+ end
+
+ self.sip_account = SipAccount.where(:id => attributes[:sip_account_id]).first
+ self.dest = attributes[:dest]
+ return self
+ end
+
+ def save(attributes=nil)
+
+ end
+
+ def call(number=nil)
+ if @sip_account && self.dest
+ return @sip_account.call(self.dest)
+ end
+ return false
end
def destroy
@@ -15,15 +37,25 @@ class Call < ActiveRecord::Base
return FreeswitchAPI.execute('uuid_kill', self.uuid, true);
end
+ def sip_account=(sip_a)
+ @sip_account = sip_a
+ end
+
def sip_account
+ if @sip_account
+ return @sip_account
+ end
+
result = self.presence_id.match('^(.+)@(.+)$')
if result && ! result[1].blank? and ! result[2].blank?
domain = SipDomain.where(:host => result[2]).first
if domain
- return SipAccount.where(:auth_name => result[1], :sip_domain_id => domain.id).first
+ @sip_account = SipAccount.where(:auth_name => result[1], :sip_domain_id => domain.id).first
end
end
+
+ return @sip_account
end
def sip_account_bleg
@@ -69,4 +101,5 @@ class Call < ActiveRecord::Base
true
end
end
+
end
diff --git a/app/models/call_forward.rb b/app/models/call_forward.rb
index c668993..a932e11 100644
--- a/app/models/call_forward.rb
+++ b/app/models/call_forward.rb
@@ -6,17 +6,17 @@ class CallForward < ActiveRecord::Base
:destination, :source, :depth, :active, :to_voicemail,
:hunt_group_id,
:call_forwardable_type, :call_forwardable_id,
- :call_forwarding_destination, :position, :uuid
+ :call_forwarding_destination, :position, :uuid,
+ :destinationable_type, :destinationable_id
- belongs_to :phone_number
belongs_to :call_forwardable, :polymorphic => true
- has_many :softkeys
+ belongs_to :destinationable, :polymorphic => true
+ has_many :softkeys, :as => :softkeyable
- acts_as_list :scope => [ :phone_number_id, :call_forward_case_id ]
+ acts_as_list :scope => [ :call_forwardable_id, :call_forwardable_type, :call_forward_case_id ]
- validates_presence_of :phone_number
validates_presence_of :call_forward_case_id
- validates_presence_of :destination, :if => Proc.new { |cf| cf.call_forwardable_type.to_s.downcase == 'phonenumber' || cf.call_forwardable_type.blank? }
+ validates_presence_of :destination, :if => Proc.new { |cf| cf.destinationable_type.to_s.downcase == 'phonenumber' || cf.destinationable_type.blank? }
validates_inclusion_of :destination,
:in => [ nil, '' ],
@@ -24,8 +24,8 @@ class CallForward < ActiveRecord::Base
belongs_to :call_forward_case
- validates_presence_of :depth
validates_numericality_of :depth,
+ :allow_nil => true,
:only_integer => true,
:greater_than_or_equal_to => 1,
:less_than_or_equal_to => (GsParameter.get('MAX_CALL_FORWARD_DEPTH').nil? ? 0 : GsParameter.get('MAX_CALL_FORWARD_DEPTH'))
@@ -44,25 +44,21 @@ class CallForward < ActiveRecord::Base
:in => [ nil ],
:if => Proc.new { |cf| cf.call_forward_case_id != 3 }
- validate :validate_empty_hunt_group, :if => Proc.new { |cf| cf.active == true && cf.call_forwardable_type == 'HuntGroup' && cf.call_forward_case.value == 'assistant' }
+ validate :validate_empty_hunt_group, :if => Proc.new { |cf| cf.active == true && cf.destinationable_type == 'HuntGroup' && cf.call_forward_case.value == 'assistant' }
validates_presence_of :uuid
validates_uniqueness_of :uuid
# Make sure the call forward's parent can't be changed:
before_validation { |cfwd|
- if cfwd.id \
- && cfwd.phone_number_id != cfwd.phone_number_id_was
- errors.add( :phone_number_id, "cannot be changed." )
+ if cfwd.id && (cfwd.call_forwardable_id != cfwd.call_forwardable_id_was || cfwd.call_forwardable_type != cfwd.call_forwardable_type_was)
+ errors.add( :call_forwardable_id, "cannot be changed." )
end
}
- #before_validation :set_call_forwardable
before_save :split_and_format_destination_numbers
after_save :set_presence
- after_save :work_through_callforward_rules_act_per_sip_account
after_save :deactivate_concurring_entries, :if => Proc.new { |cf| cf.active == true }
- before_destroy :check_if_other_callforward_rules_have_to_be_destroyed
before_destroy :deactivate_connected_softkeys
def case_string
@@ -70,70 +66,25 @@ class CallForward < ActiveRecord::Base
end
def to_s
- if self.call_forwardable_type.blank?
- self.call_forwardable_type = ''
+ if self.destinationable_type.blank?
+ self.destinationable_type = ''
else
- call_forwardable_type = " #{self.call_forwardable_type}"
+ destinationable_type = " #{self.destinationable_type}"
end
- if self.call_forwardable
- destination = "#{self.call_forwardable}#{call_forwardable_type}"
+ if self.destinationable
+ destination = "#{self.destinationable}#{destinationable_type}"
else
- destination = "#{self.destination}#{call_forwardable_type}"
+ destination = "#{self.destination}#{destinationable_type}"
end
- "#{self.phone_number} (#{I18n.t("call_forward_cases.#{self.call_forward_case}")}) -> #{destination}"
- end
-
- def set_this_callforward_rule_to_all_phone_numbers_of_the_parent_sip_account
- # This is to make sure that no recursion kicks in.
- #
- if ! self.phone_number.phone_numberable.respond_to? :callforward_rules_act_per_sip_account
- return false
- end
-
- old_value_of_callforward_rules_act_per_sip_account = self.phone_number.phone_numberable.callforward_rules_act_per_sip_account
- self.phone_number.phone_numberable.update_attributes({:callforward_rules_act_per_sip_account => false})
-
- attributes_of_this_call_forward = self.attributes.delete_if {|key, value| ['id','updated_at','created_at','phone_number_id','call_forward_case_id', 'uuid'].include?(key)}
- phone_numbers = self.phone_number.phone_numberable.phone_numbers.where('id != ?', self.phone_number.id)
-
- phone_numbers.each do |phone_number|
- # Problem
- call_forward = phone_number.call_forwards.find_or_create_by_call_forward_case_id_and_position(self.call_forward_case_id, self.position, attributes_of_this_call_forward)
- call_forward.update_attributes(attributes_of_this_call_forward)
- end
-
- self.phone_number.phone_numberable.update_attributes({:callforward_rules_act_per_sip_account => old_value_of_callforward_rules_act_per_sip_account})
- end
-
- def destroy_all_similar_callforward_rules_of_the_parent_sip_account
- # This is to make sure that no recursion kicks in.
- #
- if ! self.phone_number.phone_numberable.respond_to? :callforward_rules_act_per_sip_account
- return false
- end
-
- old_value_of_callforward_rules_act_per_sip_account = self.phone_number.phone_numberable.callforward_rules_act_per_sip_account
- self.phone_number.phone_numberable.update_attributes({:callforward_rules_act_per_sip_account => false})
-
- phone_numbers_of_parent_sip_account = self.phone_number.phone_numberable.phone_numbers.where('id != ?', self.phone_number.id)
-
- phone_numbers_of_parent_sip_account.each do |phone_number|
- if self.call_forwardable_type != 'Voicemail'
- phone_number.call_forwards.where(:call_forward_case_id => self.call_forward_case_id, :destination => self.destination).destroy_all
- else
- phone_number.call_forwards.where(:call_forward_case_id => self.call_forward_case_id, :call_forwardable_type => self.call_forwardable_type).destroy_all
- end
- end
-
- self.phone_number.phone_numberable.update_attributes({:callforward_rules_act_per_sip_account => old_value_of_callforward_rules_act_per_sip_account})
+ "#{self.call_forwardable} (#{I18n.t("call_forward_cases.#{self.call_forward_case}")}) -> #{destination}"
end
def call_forwarding_destination
- "#{self.call_forwardable_id}:#{self.call_forwardable_type}"
+ "#{self.destinationable_id}:#{self.destinationable_type}"
end
def call_forwarding_destination=(destination_record)
- self.call_forwardable_id, delimeter, self.call_forwardable_type = destination_record.to_s.partition(':')
+ self.destinationable_id, delimeter, self.destinationable_type = destination_record.to_s.partition(':')
end
def toggle
@@ -168,7 +119,7 @@ class CallForward < ActiveRecord::Base
state = 'terminated'
if self.active
- if self.call_forwardable_type and self.call_forwardable_type.downcase() == 'voicemail'
+ if self.destinationable_type and self.destinationable_type.downcase() == 'voicemail'
state = 'early'
else
state = 'confirmed'
@@ -187,47 +138,28 @@ class CallForward < ActiveRecord::Base
#return send_presence_event(self.call_forward_case.value, state)
end
- def set_call_forwardable
+ def set_destinationable
if @hunt_group_id && HuntGroup.where(:id => @hunt_group_id.to_i).count > 0
- self.call_forwardable = HuntGroup.where(:id => @hunt_group_id.to_i).first
+ self.destinationable = HuntGroup.where(:id => @hunt_group_id.to_i).first
end
if @to_voicemail && @to_voicemail.first.downcase == 'true'
- self.call_forwardable_type = 'Voicemail'
- self.call_forwardable_id = nil
+ self.destinationable_type = 'Voicemail'
+ self.destinationable_id = nil
end
end
- def work_through_callforward_rules_act_per_sip_account
- if ! self.phone_number.phone_numberable.respond_to? :callforward_rules_act_per_sip_account
- return false
- end
-
- if self.phone_number.phone_numberable.callforward_rules_act_per_sip_account == true
- self.set_this_callforward_rule_to_all_phone_numbers_of_the_parent_sip_account
- end
- end
-
- def check_if_other_callforward_rules_have_to_be_destroyed
- if ! self.phone_number.phone_numberable.respond_to? :callforward_rules_act_per_sip_account
- return false
- end
-
- if self.phone_number.phone_numberable.callforward_rules_act_per_sip_account == true
- self.destroy_all_similar_callforward_rules_of_the_parent_sip_account
- end
- end
def send_presence_event(state, call_forwarding_service = nil)
dialplan_function = "cftg-#{self.id}"
unique_id = "call_forwarding_#{self.id}"
if call_forwarding_service == 'always'
- dialplan_function = "cfutg-#{self.phone_number.id}"
- unique_id = "call_forwarding_number_#{self.phone_number.id}"
+ dialplan_function = "cfutg-#{self.call_forwardable.id}"
+ unique_id = "call_forwarding_number_#{self.call_forwardable.id}"
elsif call_forwarding_service == 'assistant'
- dialplan_function = "cfatg-#{self.phone_number.id}"
- unique_id = "call_forwarding_number_#{self.phone_number.id}"
+ dialplan_function = "cfatg-#{self.call_forwardable.id}"
+ unique_id = "call_forwarding_number_#{self.call_forwardable.id}"
end
if dialplan_function
@@ -245,7 +177,7 @@ class CallForward < ActiveRecord::Base
end
def deactivate_concurring_entries
- CallForward.where(:phone_number_id => self.phone_number_id, :call_forward_case_id => self.call_forward_case_id, :active => true).each do |call_forwarding_entry|
+ CallForward.where(:call_forwardable_id => self.call_forwardable_id, :call_forwardable_type => self.call_forwardable_type, :call_forward_case_id => self.call_forward_case_id, :active => true).each do |call_forwarding_entry|
if call_forwarding_entry.id != self.id
call_forwarding_entry.update_attributes(:active => false)
end
@@ -253,7 +185,7 @@ class CallForward < ActiveRecord::Base
end
def validate_empty_hunt_group
- hunt_group = self.call_forwardable
+ hunt_group = self.destinationable
if hunt_group && hunt_group.hunt_group_members.where(:active => true).count == 0
errors.add(:call_forwarding_destination, 'HuntGroup has no active members')
end
diff --git a/app/models/fax_document.rb b/app/models/fax_document.rb
index 564d3bb..5b27965 100644
--- a/app/models/fax_document.rb
+++ b/app/models/fax_document.rb
@@ -1,8 +1,7 @@
class FaxDocument < ActiveRecord::Base
# attr_accessible :inbound, :transmission_time, :sent_at, :document_total_pages, :document_transferred_pages, :ecm_requested, :ecm_used, :image_resolution, :image_size, :local_station_id, :result_code, :result_text, :remote_station_id, :success, :transfer_rate, :t38_gateway_format, :t38_peer, :document
- mount_uploader :document, DocumentUploader
- mount_uploader :tiff, TiffUploader
+ mount_uploader :document, FaxDocumentUploader
validates_presence_of :document
validates_numericality_of :retry_counter, :only_integer => true, :greater_than_or_equal_to => 0
@@ -18,8 +17,10 @@ class FaxDocument < ActiveRecord::Base
has_many :fax_thumbnails, :order => :position, :dependent => :destroy
- after_create :convert_pdf_to_tiff
+ after_save :convert_to_tiff
after_create :render_thumbnails
+
+ after_destroy :remove_storage_dir
# Scopes
scope :inbound, where(:state => 'inbound')
@@ -57,7 +58,7 @@ class FaxDocument < ActiveRecord::Base
end
def create_thumbnails_and_save_them
- tmp_dir = "/tmp/fax_convertions/#{self.id}"
+ tmp_dir = "/var/spool/gemeinschaft/fax_convertions/#{self.id}"
FileUtils.mkdir_p tmp_dir
system("cd #{tmp_dir} && convert #{self.document.path} -colorspace Gray PNG:'fax_page.png'")
Dir.glob("#{tmp_dir}/fax_page*.png").each do |thumbnail|
@@ -68,17 +69,64 @@ class FaxDocument < ActiveRecord::Base
FileUtils.rm_rf tmp_dir
end
- private
- def convert_pdf_to_tiff
+ def tiff_to_pdf
+ if !File.exists?(self.tiff)
+ return nil
+ end
+
+ working_path, file_name = File.split(self.tiff)
+ pdf_file = "#{working_path}/#{File.basename(self.tiff, '.tiff')}.pdf"
+
+ system "tiff2pdf \\
+ -o \"#{pdf_file}\" \\
+ -p letter \\
+ -a \"#{self.remote_station_id}\" \\
+ -c \"AMOOMA Gemeinschaft version #{GsParameter.get('GEMEINSCHAFT_VERSION')}\" \\
+ -t \"#{self.remote_station_id}\" \"#{self.tiff}\""
+
+ if !File.exists?(pdf_file)
+ return nil
+ end
+
+ return pdf_file
+ end
+
+ def to_tiff
page_size_a4 = '595 842'
page_size_command = "<< /Policies << /PageSize 3 >> /InputAttributes currentpagedevice /InputAttributes get dup { pop 1 index exch undef } forall dup 0 << /PageSize [ #{page_size_a4} ] >> put >> setpagedevice"
- directory = "/tmp/GS-#{GsParameter.get('GEMEINSCHAFT_VERSION')}/faxes/#{self.id}"
- FileUtils.mkdir_p directory
- tiff_file_name = File.basename(self.document.to_s.downcase, ".pdf") + '.tiff'
- system "cd #{directory} && gs -q -r#{self.fax_resolution.resolution_value} -dNOPAUSE -dBATCH -dSAFER -sDEVICE=tiffg3 -sOutputFile=\"#{tiff_file_name}\" -c \"#{page_size_command}\" -- \"#{Rails.root.to_s}/public#{self.document.to_s}\""
- self.tiff = File.open("#{directory}/#{tiff_file_name}")
- self.save
- FileUtils.rm_rf directory
+ working_path, file_name = File.split(self.document.to_s)
+ tiff_file = File.basename(file_name.to_s.downcase, File.extname(file_name)) + '.tiff'
+ result = system "cd #{store_dir} && gs -q -r#{self.fax_resolution.resolution_value} -dNOPAUSE -dBATCH -dSAFER -sDEVICE=tiffg3 -sOutputFile=\"#{tiff_file}\" -c \"#{page_size_command}\" -- \"#{self.document.to_s}\""
+
+ if !File.exists?("#{store_dir}/#{tiff_file}")
+ return nil
+ end
+
+ return "#{store_dir}/#{tiff_file}"
+ end
+
+ def store_dir
+ if self.try(:inbound)
+ "/var/opt/gemeinschaft/fax/in/#{self.id.to_i}"
+ else
+ "/var/opt/gemeinschaft/fax/out/#{self.id.to_i}"
+ end
+ end
+
+ private
+ def convert_to_tiff
+ if self.tiff.blank?
+ self.tiff = self.to_tiff
+ if self.tiff
+ return self.save
+ end
+ end
+ end
+
+ def remove_storage_dir
+ if File.directory?(self.store_dir)
+ FileUtils.rm_rf(self.store_dir)
+ end
end
end
diff --git a/app/models/group.rb b/app/models/group.rb
new file mode 100644
index 0000000..e0cfaab
--- /dev/null
+++ b/app/models/group.rb
@@ -0,0 +1,11 @@
+class Group < ActiveRecord::Base
+ attr_accessible :name, :active, :comment
+
+ has_many :group_memberships, :dependent => :destroy
+ has_many :group_permissions, :dependent => :destroy
+ has_many :permittances, :foreign_key => :target_group_id, :class_name => "GroupPermission", :dependent => :destroy
+
+ def to_s
+ self.name
+ end
+end
diff --git a/app/models/group_membership.rb b/app/models/group_membership.rb
new file mode 100644
index 0000000..0f04ae1
--- /dev/null
+++ b/app/models/group_membership.rb
@@ -0,0 +1,37 @@
+class GroupMembership < ActiveRecord::Base
+ attr_accessible :group_id, :item_type, :item_id
+
+ belongs_to :group
+ belongs_to :item, :polymorphic => true
+
+ validates :item_id,
+ :presence => true,
+ :uniqueness => { :scope => [:group_id, :item_type] }
+
+ validates :item_type,
+ :presence => true,
+ :uniqueness => { :scope => [:group_id, :item_id] }
+
+ validate :validate_item_type_consitency
+
+ validates :item,
+ :presence => true
+
+ def to_s
+ "#{self.item_type}: #{self.item}"
+ end
+
+ def item_type_allowed
+ fist_item = self.group.group_memberships.first.try(:item)
+ if fist_item
+ return fist_item.class.name
+ end
+ end
+
+ def validate_item_type_consitency
+ type_allowed = self.item_type_allowed
+ if type_allowed && type_allowed != self.item_type
+ errors.add(:item_type, "must be of type: #{type_allowed}")
+ end
+ end
+end
diff --git a/app/models/group_permission.rb b/app/models/group_permission.rb
new file mode 100644
index 0000000..fe988ba
--- /dev/null
+++ b/app/models/group_permission.rb
@@ -0,0 +1,24 @@
+class GroupPermission < ActiveRecord::Base
+ attr_accessible :group_id, :permission, :target_group_id
+
+ PERMISSION_TYPES = ['pickup']
+
+ belongs_to :group
+ belongs_to :target_group, :class_name => "Group"
+
+ validates :target_group_id,
+ :presence => true,
+ :uniqueness => { :scope => [:group_id, :permission] }
+
+ validates :target_group,
+ :presence => true
+
+ validates :permission,
+ :presence => true,
+ :uniqueness => { :scope => [:group_id, :target_group_id] },
+ :inclusion => { :in => PERMISSION_TYPES }
+
+ def to_s
+ "#{self.permission} => #{self.target_group}"
+ end
+end
diff --git a/app/models/gs_parameter.rb b/app/models/gs_parameter.rb
index fe2a845..cd4f47b 100644
--- a/app/models/gs_parameter.rb
+++ b/app/models/gs_parameter.rb
@@ -10,9 +10,13 @@ class GsParameter < ActiveRecord::Base
:presence => true,
:inclusion => { :in => ['String', 'Integer', 'Boolean', 'YAML', 'Nil'] }
- def self.get(wanted_variable)
+ def self.get(wanted_variable, entity=nil, section=nil)
if GsParameter.table_exists?
- item = GsParameter.where(:name => wanted_variable).first
+ if entity || section
+ item = GsParameter.where(:name => wanted_variable, :entity => entity, :section => section).first
+ else
+ item = GsParameter.where(:name => wanted_variable).first
+ end
if item.nil? || item.class_type == 'Nil'
return nil
else
diff --git a/app/models/hunt_group.rb b/app/models/hunt_group.rb
index 5011bf0..7338606 100644
--- a/app/models/hunt_group.rb
+++ b/app/models/hunt_group.rb
@@ -2,7 +2,7 @@ class HuntGroup < ActiveRecord::Base
attr_accessible :name, :strategy, :seconds_between_jumps, :phone_numbers_attributes
belongs_to :tenant, :touch => true
- has_many :call_forwards, :as => :call_forwardable, :dependent => :destroy
+ has_many :call_forwards, :as => :destinationable, :dependent => :destroy
validates_uniqueness_of :name, :scope => :tenant_id,
:allow_nil => true, :allow_blank => true
diff --git a/app/models/intruder.rb b/app/models/intruder.rb
index 249fffc..97e3773 100644
--- a/app/models/intruder.rb
+++ b/app/models/intruder.rb
@@ -31,6 +31,41 @@ class Intruder < ActiveRecord::Base
end
end
+ def self.write_firewall_blacklist
+ firewall_blacklist_file = GsParameter.get('blacklist_file', 'perimeter', 'general')
+ entry_template = GsParameter.get('blacklist_file_entry', 'perimeter', 'general')
+ comment_template = GsParameter.get('blacklist_file_comment', 'perimeter', 'general')
+ File.open(firewall_blacklist_file, 'w') do |file|
+ Intruder.where(:list_type => 'blacklist').where('bans > 0').all.each do |entry|
+ if ! comment_template.blank?
+ file.write(self.expand_variables(comment_template, entry.to_hash) + "\n")
+ end
+ file.write(self.expand_variables(entry_template, entry.to_hash) + "\n")
+ end
+ end
+ end
+
+ def self.expand_variables(line, variables)
+ return line.gsub(/\{([a-z_]+)\}/) do |m|
+ variables[$1.to_sym]
+ end
+ end
+
+ def to_hash
+ return {
+ :key => self.key,
+ :points => self.points,
+ :bans => self.bans,
+ :received_port => self.contact_port,
+ :received_ip => self.contact_ip,
+ :contact_count => self.contact_count,
+ :user_agent => self.user_agent,
+ :to_user => self.to_user,
+ :comment => self.comment,
+ :date => DateTime.now.strftime('%Y-%m-%d %X')
+ }
+ end
+
private
def set_key_if_empty
if self.key.blank?
diff --git a/app/models/phone_book_entry.rb b/app/models/phone_book_entry.rb
index 275c7b6..96c8468 100644
--- a/app/models/phone_book_entry.rb
+++ b/app/models/phone_book_entry.rb
@@ -1,6 +1,8 @@
# encoding: UTF-8
class PhoneBookEntry < ActiveRecord::Base
+ PHONE_NUMBER_NAMES = ['Phone', 'Office', 'Home', 'Mobile', 'Fax']
+
before_save :run_phonetic_algorithm
before_save :save_value_of_to_s
diff --git a/app/models/phone_number.rb b/app/models/phone_number.rb
index d1e950f..f6453ce 100644
--- a/app/models/phone_number.rb
+++ b/app/models/phone_number.rb
@@ -3,7 +3,7 @@ class PhoneNumber < ActiveRecord::Base
attr_accessible :name, :number, :gs_node_id, :access_authorization_user_id
- has_many :call_forwards, :dependent => :destroy
+ has_many :call_forwards, :as => :call_forwardable, :dependent => :destroy
has_many :ringtones, :as => :ringtoneable, :dependent => :destroy
diff --git a/app/models/restore_job.rb b/app/models/restore_job.rb
new file mode 100644
index 0000000..80741ac
--- /dev/null
+++ b/app/models/restore_job.rb
@@ -0,0 +1,24 @@
+class RestoreJob < ActiveRecord::Base
+ attr_accessible :state, :backup_file
+
+ mount_uploader :backup_file, BackupFileUploader
+
+ after_create :queue_the_restore_rake_task
+
+ def to_s
+ if self.backup_file?
+ File.basename(self.backup_file.to_s)
+ else
+ "RestoreJob ID #{self.id}"
+ end
+ end
+
+ private
+ def queue_the_restore_rake_task
+ self.delay.run_the_restore_rake_task
+ end
+
+ def run_the_restore_rake_task
+ system "cd #{Rails.root} && rake backup:restore"
+ end
+end
diff --git a/app/models/ringtone.rb b/app/models/ringtone.rb
index 36053c0..45ecd93 100644
--- a/app/models/ringtone.rb
+++ b/app/models/ringtone.rb
@@ -1,11 +1,25 @@
class Ringtone < ActiveRecord::Base
attr_accessible :audio, :bellcore_id
+ CORE_RINGTONES_AVAILABLE = {
+ 'Silence' => 0,
+ 'Ringtone 1' => 1,
+ 'Ringtone 2' => 2,
+ 'Ringtone 3' => 3,
+ 'Ringtone 4' => 4,
+ 'Ringtone 5' => 5,
+ 'Ringtone 6' => 6,
+ 'Ringtone 7' => 7,
+ 'Ringtone 8' => 8,
+ 'Ringtone 9' => 9,
+ 'Ringtone 10' => 10,
+ }
mount_uploader :audio, AudioUploader
validates_presence_of :audio, :if => Proc.new{ |ringtone| ringtone.bellcore_id.blank? }
validates_presence_of :ringtoneable_type
validates_presence_of :ringtoneable_id
validates_presence_of :ringtoneable
+ validates_uniqueness_of :ringtoneable_id, :scope => [:ringtoneable_type]
belongs_to :ringtoneable, :polymorphic => true
diff --git a/app/models/sip_account.rb b/app/models/sip_account.rb
index 7df8e3b..2040b41 100644
--- a/app/models/sip_account.rb
+++ b/app/models/sip_account.rb
@@ -16,7 +16,7 @@ class SipAccount < ActiveRecord::Base
has_many :phones, :through => :phone_sip_accounts
has_many :phone_numbers, :as => :phone_numberable, :dependent => :destroy
- has_many :call_forwards, :through => :phone_numbers
+ has_many :call_forwards, :as => :call_forwardable, :dependent => :destroy
belongs_to :tenant
belongs_to :sip_domain
@@ -33,6 +33,13 @@ class SipAccount < ActiveRecord::Base
belongs_to :language, :foreign_key => 'language_code', :primary_key => 'code'
+ has_many :group_memberships, :as => :item, :dependent => :destroy, :uniq => true
+ has_many :groups, :through => :group_memberships
+
+ has_many :ringtones, :as => :ringtoneable, :dependent => :destroy
+
+ has_many :calls, :finder_sql => lambda { |s| "SELECT DISTINCT detailed_calls.* FROM detailed_calls WHERE presence_id LIKE '#{self.auth_name}@%'" }
+
# Delegations:
#
delegate :host, :to => :sip_domain, :allow_nil => true
@@ -67,6 +74,7 @@ class SipAccount < ActiveRecord::Base
validates_uniqueness_of :uuid
after_create { self.create_on_other_gs_nodes('sip_accountable', self.sip_accountable.try(:uuid)) }
+ after_create :create_default_group_memberships
after_destroy :destroy_on_other_gs_nodes
after_update { self.update_on_other_gs_nodes('sip_accountable', self.sip_accountable.try(:uuid)) }
@@ -92,8 +100,8 @@ class SipAccount < ActiveRecord::Base
if call_forwarding_master.active
call_forwarding_master.active = false
else
- if call_forwarding_service = 'assistant' && call_forwarding_master.call_forwardable_type == 'HuntGroup' && call_forwarding_master.call_forwardable
- if call_forwarding_master.call_forwardable.hunt_group_members.where(:active => true).count > 0
+ if call_forwarding_service = 'assistant' && call_forwarding_master.destinationable_type == 'HuntGroup' && call_forwarding_master.destinationable
+ if call_forwarding_master.destinationable.hunt_group_members.where(:active => true).count > 0
call_forwarding_master.active = true
else
call_forwarding_master.active = false
@@ -105,7 +113,7 @@ class SipAccount < ActiveRecord::Base
call_forwarding = phone_number.call_forwards.where(:call_forward_case_id => service_id).order(:active).all(:conditions => 'source IS NULL OR source = ""').first
if ! call_forwarding
call_forwarding = CallForward.new()
- call_forwarding.phone_number_id = phone_number.id
+ call_forwarding.call_forwardable = phone_number
end
if to_voicemail == nil
@@ -146,7 +154,7 @@ class SipAccount < ActiveRecord::Base
true
);
end
-
+
private
@@ -202,7 +210,7 @@ class SipAccount < ActiveRecord::Base
# log out phone if sip_account is not on this node
def log_out_phone_if_not_local
- if self.gs_node_id && ! GsNode.where(:ip_address => GsParameter.get('HOMEBASE_IP_ADDRESS'), :id => self.gs_node_id).first
+ if self.gs_node_id && GsNode.count > 1 && ! GsNode.where(:ip_address => GsParameter.get('HOMEBASE_IP_ADDRESS'), :id => self.gs_node_id).first
self.phones.each do |phone|
phone.user_logout;
end
@@ -220,4 +228,29 @@ class SipAccount < ActiveRecord::Base
voicemail_setting.purge = false
voicemail_setting.save
end
+
+ def create_default_group_memberships
+ default_groups = Hash.new()
+ templates = GsParameter.get('SipAccount', 'group', 'default')
+ if templates.class == Array
+ templates.each do |group_name|
+ default_groups[group_name] = true
+ end
+ end
+
+ templates = GsParameter.get("SipAccount.#{self.sip_accountable_type}", 'group', 'default')
+ if templates.class == Array
+ templates.each do |group_name|
+ default_groups[group_name] = true
+ end
+ end
+
+ default_groups.each do |group_name, value|
+ group = Group.where(:name => group_name).first
+ if group
+ self.group_memberships.create(:group_id => group.id)
+ end
+ end
+ end
+
end
diff --git a/app/models/softkey.rb b/app/models/softkey.rb
index 4b758e0..8049456 100644
--- a/app/models/softkey.rb
+++ b/app/models/softkey.rb
@@ -30,7 +30,7 @@ class Softkey < ActiveRecord::Base
# We pick one phone_number and display the rules of it.
#
phone_number = self.sip_account.phone_numbers.order(:number).first
- call_forwards = self.sip_account.call_forwards.where(:phone_number_id => phone_number.id)
+ call_forwards = self.sip_account.call_forwards.where(:call_forwardable_id => phone_number.id, :call_forwardable_type => 'PhoneNumber')
else
call_forwards = self.sip_account.call_forwards
end
@@ -42,8 +42,8 @@ class Softkey < ActiveRecord::Base
map{ |phone_number| phone_number.phone_numberable.hunt_group.id }.
uniq
- call_forwards + CallForward.where(:call_forwardable_type => 'HuntGroup', :call_forwardable_id => hunt_group_ids).
- where('phone_number_id NOT IN (?)', phone_numbers_ids)
+ call_forwards + CallForward.where(:destinationable_type => 'HuntGroup', :destinationable_id => hunt_group_ids, :call_forwardable_type => 'PhoneNumber').
+ where('call_forwardable_id NOT IN (?)', phone_numbers_ids)
end
end
diff --git a/app/models/user.rb b/app/models/user.rb
index 6c67351..913d75f 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -6,6 +6,7 @@ class User < ActiveRecord::Base
# Sync other nodes when this is a cluster.
#
after_create :create_on_other_gs_nodes
+ after_create :create_default_group_memberships
after_destroy :destroy_on_other_gs_nodes
after_update :update_on_other_gs_nodes
@@ -89,6 +90,9 @@ class User < ActiveRecord::Base
belongs_to :gs_node
has_many :parking_stalls, :as => :parking_stallable, :dependent => :destroy
+
+ has_many :group_memberships, :as => :item, :dependent => :destroy, :uniq => true
+ has_many :groups, :through => :group_memberships
# Avatar like photo
mount_uploader :image, ImageUploader
@@ -226,4 +230,16 @@ class User < ActiveRecord::Base
end
end
+ def create_default_group_memberships
+ templates = GsParameter.get('User', 'group', 'default')
+ if templates.class == Array
+ templates.each do |group_name|
+ group = Group.where(:name => group_name).first
+ if group
+ self.group_memberships.create(:group_id => group.id)
+ end
+ end
+ end
+ end
+
end
diff --git a/app/uploaders/backup_file_uploader.rb b/app/uploaders/backup_file_uploader.rb
index 8b126a9..0244ba5 100644
--- a/app/uploaders/backup_file_uploader.rb
+++ b/app/uploaders/backup_file_uploader.rb
@@ -42,9 +42,9 @@ class BackupFileUploader < CarrierWave::Uploader::Base
# Add a white list of extensions which are allowed to be uploaded.
# For images you might use something like this:
- # def extension_white_list
- # %w(jpg jpeg gif png)
- # end
+ def extension_white_list
+ %w(tar.gz)
+ end
# Override the filename of the uploaded files:
# Avoid using model.id or version_name here, see uploader/store.rb for details.
diff --git a/app/uploaders/fax_document_uploader.rb b/app/uploaders/fax_document_uploader.rb
new file mode 100644
index 0000000..bfb7e07
--- /dev/null
+++ b/app/uploaders/fax_document_uploader.rb
@@ -0,0 +1,19 @@
+# encoding: utf-8
+
+class FaxDocumentUploader < CarrierWave::Uploader::Base
+ include CarrierWave::MiniMagick
+
+ storage :file
+
+ def store_dir
+ model.store_dir
+ end
+
+ def cache_dir
+ '/tmp/gs_fax_uploader'
+ end
+
+ def extension_white_list
+ %w(pdf ps jpg jpeg gif png tif tiff)
+ end
+end
diff --git a/app/views/backup_jobs/show.html.haml b/app/views/backup_jobs/show.html.haml
index 6fcb1dc..8bb270f 100644
--- a/app/views/backup_jobs/show.html.haml
+++ b/app/views/backup_jobs/show.html.haml
@@ -1,22 +1,34 @@
- content_for :title, t("backup_jobs.show.page_title")
-%p
- %strong= t('backup_jobs.show.started_at') + ":"
- = @backup_job.started_at
-%p
- %strong= t('backup_jobs.show.finished_at') + ":"
- = @backup_job.finished_at
-%p
- %strong= t('backup_jobs.show.state') + ":"
- = @backup_job.state
-%p
- %strong= t('backup_jobs.show.directory') + ":"
- = @backup_job.directory
-%p
- %strong= t('backup_jobs.show.size_of_the_backup') + ":"
- - if @backup_job.backup_file?
- %a{:href => backup_job.backup_file.url}
- %i{:class => 'icon-download'}
- = number_to_human_size(backup_job.backup_file.size, :precision => 2)
+%table.table.table-striped
+ %tbody
+ %tr
+ %td
+ %strong= t('backup_jobs.show.started_at') + ":"
+ %td
+ = @backup_job.started_at
+ %tr
+ %td
+ %strong= t('backup_jobs.show.finished_at') + ":"
+ %td
+ = @backup_job.finished_at
+ %tr
+ %td
+ %strong= t('backup_jobs.show.state') + ":"
+ %td
+ = @backup_job.state
+ %tr
+ %td
+ %strong= t('backup_jobs.show.directory') + ":"
+ %td
+ = @backup_job.directory
+ %tr
+ %td
+ %strong= t('backup_jobs.show.size_of_the_backup') + ":"
+ %td
+ - if @backup_job.backup_file?
+ %a{:href => @backup_job.backup_file.url}
+ %i{:class => 'icon-download'}
+ = number_to_human_size(@backup_job.backup_file.size, :precision => 2)
= render :partial => 'shared/show_edit_destroy_part', :locals => { :child => @backup_job } \ No newline at end of file
diff --git a/app/views/call_forwards/_form.html.haml b/app/views/call_forwards/_form.html.haml
index 58ffd78..1944fc4 100644
--- a/app/views/call_forwards/_form.html.haml
+++ b/app/views/call_forwards/_form.html.haml
@@ -1,4 +1,4 @@
-= simple_form_for([ @phone_number, @call_forward ]) do |f|
+= simple_form_for([ @parent, @call_forward ]) do |f|
= f.error_notification
= render "form_core", :f => f
diff --git a/app/views/call_forwards/_form_core.html.haml b/app/views/call_forwards/_form_core.html.haml
index b751fb3..83de044 100644
--- a/app/views/call_forwards/_form_core.html.haml
+++ b/app/views/call_forwards/_form_core.html.haml
@@ -1,5 +1,5 @@
.inputs
- = f.input :call_forward_case_id, :as => :select, :collection => @available_call_forward_cases.map {|x| [I18n.t("call_forward_cases.#{x.value}"), x.id] }, :label => t('call_forwards.form.call_forward_case_id.label'), :hint => conditional_hint('call_forwards.form.call_forward_case_id.hint'), :include_blank => false, :autofocus => true
+ = f.input :call_forward_case_id, :as => :select, :collection => @available_call_forward_cases.map {|x| [I18n.t("call_forward_cases.#{x.value}"), x.id] }, :label => t('call_forwards.form.call_forward_case.label'), :hint => conditional_hint('call_forwards.form.call_forward_case_id.hint'), :include_blank => false, :autofocus => true
= f.input :timeout, :label => t('call_forwards.form.timeout.label'), :hint => conditional_hint('call_forwards.form.timeout.hint')
= f.input :call_forwarding_destination , :as => :select, :collection => @call_forwarding_destinations, :label => t('call_forwards.form.call_forwarding_destination.label'), :hint => conditional_hint('call_forwards.form.call_forwarding_destination.hint'), :include_blank => false
@@ -8,8 +8,4 @@
= f.input :source, :label => t('call_forwards.form.source.label'), :hint => conditional_hint('call_forwards.form.source.hint')
- - if GuiFunction.display?('depth_field_in_call_forward_form', current_user)
- = f.input :depth, :collection => 1..GsParameter.get('MAX_CALL_FORWARD_DEPTH'), :label => t('call_forwards.form.depth.label'), :hint => conditional_hint('call_forwards.form.depth.hint')
- - else
- = f.hidden_field :depth
= f.input :active, :label => t('call_forwards.form.active.label'), :hint => conditional_hint('call_forwards.form.active.hint')
diff --git a/app/views/call_forwards/_index_core.html.haml b/app/views/call_forwards/_index_core.html.haml
index 878e0e2..3c57405 100644
--- a/app/views/call_forwards/_index_core.html.haml
+++ b/app/views/call_forwards/_index_core.html.haml
@@ -1,32 +1,29 @@
%table.table.table-striped
%thead
%tr
- - if !@phone_number
- %th= t('call_forwards.index.phone_number_id')
- %th= t('call_forwards.index.call_forward_case_id')
+ %th
+ %th= t('call_forwards.index.call_forward_case')
%th= t('call_forwards.index.timeout')
%th= t('call_forwards.index.destination')
- %th= t('call_forwards.index.source')
- - if GuiFunction.display?('depth_field_value_in_index_table', current_user)
- %th= t('call_forwards.index.depth')
- %th= t('call_forwards.index.active')
+ %th= t('call_forwards.index.source')
%tbody
- for call_forward in call_forwards
%tr
- - if !@phone_number
- %td= call_forward.phone_number
+ %td
+ -if call_forward.active
+ %i.icon-ok
+ - else
+ %i.icon-ban-circle
%td= t("call_forward_cases.#{call_forward.call_forward_case.value}")
%td= call_forward.timeout
%td
= call_forward.destination
- - if call_forward.call_forwardable_type
+ - if call_forward.destinationable_type
%br
- = call_forward.call_forwardable_type
- - if call_forward.call_forwardable
- = ": #{call_forward.call_forwardable}"
+ = call_forward.destinationable_type
+ - if call_forward.destinationable_id
+ = ": #{call_forward.destinationable}"
%td= call_forward.source
- - if GuiFunction.display?('depth_field_value_in_index_table', current_user)
- %td= call_forward.depth
- %td= call_forward.active
- =render :partial => 'shared/index_view_edit_destroy_part', :locals => {:parent => call_forward.phone_number, :child => call_forward} \ No newline at end of file
+ =render :partial => 'shared/index_view_edit_destroy_part', :locals => {:parent => call_forward.call_forwardable, :child => call_forward}
+
diff --git a/app/views/call_forwards/index.html.haml b/app/views/call_forwards/index.html.haml
index 91b923a..e206653 100644
--- a/app/views/call_forwards/index.html.haml
+++ b/app/views/call_forwards/index.html.haml
@@ -3,4 +3,4 @@
- if @call_forwards.count > 0
= render "index_core", :call_forwards => @call_forwards
-= render :partial => 'shared/create_link', :locals => {:parent => @phone_number, :child_class => CallForward} \ No newline at end of file
+= render :partial => 'shared/create_link', :locals => {:parent => @parent, :child_class => CallForward} \ No newline at end of file
diff --git a/app/views/call_forwards/show.html.haml b/app/views/call_forwards/show.html.haml
index c2187b1..ad9ab16 100644
--- a/app/views/call_forwards/show.html.haml
+++ b/app/views/call_forwards/show.html.haml
@@ -1,33 +1,25 @@
- content_for :title, t("call_forwards.show.page_title")
%p
- %strong= t('call_forwards.show.phone_number_id') + ":"
- = @call_forward.phone_number
-%p
- %strong= t('call_forwards.show.call_forward_case_id') + ":"
+ %strong= t('call_forwards.show.call_forward_case') + ":"
= t("call_forward_cases.#{@call_forward.call_forward_case.value}")
%p
%strong= t('call_forwards.show.timeout') + ":"
= @call_forward.timeout
%p
%strong= t('call_forwards.show.destination') + ":"
- = @call_forward.destination
-- if @call_forward.call_forwardable_type == 'HuntGroup' && @call_forward.call_forwardable.class == HuntGroup
- %p
- %strong= t('call_forwards.show.hunt_group') + ":"
- = @call_forward.call_forwardable
-- if @call_forward.call_forwardable_type == 'Voicemail'
- %p
- %strong= t('call_forwards.show.to_voicemail') + ":"
- = 'active'
+ - if @call_forward.destinationable_id && @call_forward.destinationable
+ = "#{@call_forward.destinationable_type}: #{@call_forward.destinationable}"
+ - elsif !@call_forward.destinationable_type.blank?
+ = "#{@call_forward.destinationable_type}: #{@call_forward.destination}"
+ - else
+ = @call_forward.destination
+
%p
%strong= t('call_forwards.show.source') + ":"
= @call_forward.source
%p
- %strong= t('call_forwards.show.depth') + ":"
- = @call_forward.depth
-%p
%strong= t('call_forwards.show.active') + ":"
= @call_forward.active
-= render :partial => 'shared/show_edit_destroy_part', :locals => { :parent => @phone_number, :child => @call_forward } \ No newline at end of file
+= render :partial => 'shared/show_edit_destroy_part', :locals => { :parent => @parent, :child => @call_forward }
diff --git a/app/views/calls/_form.html.haml b/app/views/calls/_form.html.haml
new file mode 100644
index 0000000..ccdcd72
--- /dev/null
+++ b/app/views/calls/_form.html.haml
@@ -0,0 +1,7 @@
+= simple_form_for([ @parent, @call ]) do |f|
+ = f.error_notification
+
+ = render "form_core", :f => f
+
+ .form-actions
+ = f.button :submit, conditional_t('calls.form.submit')
diff --git a/app/views/calls/_form_core.html.haml b/app/views/calls/_form_core.html.haml
new file mode 100644
index 0000000..4cdd55e
--- /dev/null
+++ b/app/views/calls/_form_core.html.haml
@@ -0,0 +1,2 @@
+.inputs
+ = f.input :dest, :as => :string, :label => t('calls.form.destination.label'), :hint => conditional_hint('calls.form.destination.hint'), :autofocus => true
diff --git a/app/views/calls/_index_core.html.haml b/app/views/calls/_index_core.html.haml
index 10f79f1..e5b769e 100644
--- a/app/views/calls/_index_core.html.haml
+++ b/app/views/calls/_index_core.html.haml
@@ -1,10 +1,38 @@
%table.table.table-striped
%thead
%tr
- %th= t('calls.index.uuid')
+ %th
+ %th= t('calls.index.created')
+ %th= t('calls.index.destination')
+ %th= t('calls.index.caller')
+ %th= t('calls.index.callee')
+ %th= t('calls.index.callstate')
+ %th= t('calls.index.codecs')
+ %th
%tbody
- - for call in @calls
+ - for call in calls
%tr
%td
- = call.uuid
+ - if call.direction == 'inbound'
+ %i.icon-arrow-left
+ - else
+ %i.icon-arrow-right
+ %td
+ = call.created
+ %td
+ = call.dest
+ %td
+ = "#{call.cid_name} #{call.cid_num}"
+ %td
+ = "#{call.callee_name} #{call.callee_num}"
+ %td
+ = call.callstate
+ %td
+ = "#{call.read_codec}/#{call.write_codec}"
+
+ %td
+ %p
+ %a.btn.btn-small.btn-danger{'data-confirm' => t('calls.index.actions.confirm_destroy'), 'data-method' => 'delete', :href => method( :"#{parent.class.name.underscore}_call_path" ).(parent, call), :rel => 'nofollow'}
+ %i.icon-trash.icon-white
+ =t('calls.index.actions.destroy')
diff --git a/app/views/calls/index.html.haml b/app/views/calls/index.html.haml
index be678cd..a87f809 100644
--- a/app/views/calls/index.html.haml
+++ b/app/views/calls/index.html.haml
@@ -1,6 +1,8 @@
- content_for :title, t("calls.index.page_title")
- if @calls.count > 0
- = render "index_core", :calls => @calls
+ = render "index_core", :calls => @calls, :parent => @parent
-= render :partial => 'shared/create_link', :locals => {:parent => @parent, :child_class => Call} \ No newline at end of file
+%a.btn.btn-small.btn-default{:href => method( :"new_#{@parent.class.name.underscore}_call_path" ).(@parent) }
+ %i.icon-plus
+ =t("calls.index.actions.create")
diff --git a/app/views/calls/new.html.haml b/app/views/calls/new.html.haml
new file mode 100644
index 0000000..44bb6ae
--- /dev/null
+++ b/app/views/calls/new.html.haml
@@ -0,0 +1,3 @@
+- content_for :title, t("calls.new.page_title")
+
+= render "form"
diff --git a/app/views/fax_documents/_index_core.html.haml b/app/views/fax_documents/_index_core.html.haml
index 5355521..2f9b214 100644
--- a/app/views/fax_documents/_index_core.html.haml
+++ b/app/views/fax_documents/_index_core.html.haml
@@ -50,7 +50,7 @@
- if fax_document.document?
%p
- %a{:href => fax_document.document.url}
+ %a{:href => fax_account_fax_document_path(@fax_account, fax_document, :format => :pdf), :method => :get}
%i{:class => 'icon-download'}
= t("fax_documents.index.actions.download_pdf") + " (#{number_to_human_size(fax_document.document.size, :precision => 2)})"
diff --git a/app/views/fax_documents/show.html.haml b/app/views/fax_documents/show.html.haml
index 9925c2f..b8f3e9e 100644
--- a/app/views/fax_documents/show.html.haml
+++ b/app/views/fax_documents/show.html.haml
@@ -46,7 +46,7 @@
- if @fax_document.document?
%p
- %a{:href => @fax_document.document.url}
+ %a{:href => fax_account_fax_document_path(@fax_account, @fax_document, :format => :pdf), :method => :get}
%i{:class => 'icon-download'}
= t("fax_documents.index.actions.download_pdf") + " (#{number_to_human_size(@fax_document.document.size, :precision => 2)})"
diff --git a/app/views/group_memberships/_form.html.haml b/app/views/group_memberships/_form.html.haml
new file mode 100644
index 0000000..c8a6a51
--- /dev/null
+++ b/app/views/group_memberships/_form.html.haml
@@ -0,0 +1,7 @@
+= simple_form_for([@group, @group_membership]) do |f|
+ = f.error_notification
+
+ = render "form_core", :f => f
+
+ .form-actions
+ = f.button :submit, conditional_t('group_memberships.form.submit')
diff --git a/app/views/group_memberships/_form_core.html.haml b/app/views/group_memberships/_form_core.html.haml
new file mode 100644
index 0000000..4a28a06
--- /dev/null
+++ b/app/views/group_memberships/_form_core.html.haml
@@ -0,0 +1,4 @@
+.inputs
+ - if @group.group_memberships.count < 1
+ = f.input :item_type, :label => t('group_memberships.form.item_type.label'), :hint => conditional_hint('group_memberships.form.item_type.hint')
+ = f.input :item_id, :label => t('group_memberships.form.item_id.label'), :hint => conditional_hint('group_memberships.form.item_id.hint')
diff --git a/app/views/group_memberships/_index_core.html.haml b/app/views/group_memberships/_index_core.html.haml
new file mode 100644
index 0000000..beeefc9
--- /dev/null
+++ b/app/views/group_memberships/_index_core.html.haml
@@ -0,0 +1,11 @@
+%table.table.table-striped
+ %tr
+ %th= t('group_memberships.index.item_type')
+ %th= t('group_memberships.index.item_id')
+
+
+ - for group_membership in group_memberships
+ %tr
+ %td= group_membership.item_type
+ %td= group_membership.item_id
+ =render :partial => 'shared/index_view_edit_destroy_part', :locals => {:parent => group_membership.group, :child => group_membership}
diff --git a/app/views/group_memberships/edit.html.haml b/app/views/group_memberships/edit.html.haml
new file mode 100644
index 0000000..643c095
--- /dev/null
+++ b/app/views/group_memberships/edit.html.haml
@@ -0,0 +1,3 @@
+- content_for :title, t("group_memberships.edit.page_title")
+
+= render "form" \ No newline at end of file
diff --git a/app/views/group_memberships/index.html.haml b/app/views/group_memberships/index.html.haml
new file mode 100644
index 0000000..b493017
--- /dev/null
+++ b/app/views/group_memberships/index.html.haml
@@ -0,0 +1,6 @@
+- content_for :title, t("group_memberships.index.page_title")
+
+- if @group_memberships && @group_memberships.count > 0
+ = render "index_core", :group_memberships => @group_memberships
+
+= render :partial => 'shared/create_link', :locals => {:parent => @group, :child_class => GroupMembership}
diff --git a/app/views/group_memberships/new.html.haml b/app/views/group_memberships/new.html.haml
new file mode 100644
index 0000000..6cf2ce7
--- /dev/null
+++ b/app/views/group_memberships/new.html.haml
@@ -0,0 +1,3 @@
+- content_for :title, t("group_memberships.new.page_title")
+
+= render "form" \ No newline at end of file
diff --git a/app/views/group_memberships/show.html.haml b/app/views/group_memberships/show.html.haml
new file mode 100644
index 0000000..0875f0b
--- /dev/null
+++ b/app/views/group_memberships/show.html.haml
@@ -0,0 +1,10 @@
+- content_for :title, t("group_memberships.show.page_title")
+
+%p
+ %strong= t('group_memberships.show.item_type') + ":"
+ = @group_membership.item_type
+%p
+ %strong= t('group_memberships.show.item_id') + ":"
+ = @group_membership.item_id
+
+= render :partial => 'shared/show_edit_destroy_part', :locals => { :parent => @group, :child => @group_membership }
diff --git a/app/views/group_permissions/_form.html.haml b/app/views/group_permissions/_form.html.haml
new file mode 100644
index 0000000..5f593f2
--- /dev/null
+++ b/app/views/group_permissions/_form.html.haml
@@ -0,0 +1,7 @@
+= simple_form_for([@group, @group_permission]) do |f|
+ = f.error_notification
+
+ = render "form_core", :f => f
+
+ .form-actions
+ = f.button :submit, conditional_t('group_permissions.form.submit')
diff --git a/app/views/group_permissions/_form_core.html.haml b/app/views/group_permissions/_form_core.html.haml
new file mode 100644
index 0000000..49c9e7c
--- /dev/null
+++ b/app/views/group_permissions/_form_core.html.haml
@@ -0,0 +1,3 @@
+.inputs
+ = f.input :permission, :collection => GroupPermission::PERMISSION_TYPES, :label => t('group_permissions.form.permission.label'), :hint => conditional_hint('group_permissions.form.permission.hint'), :include_blank => false
+ = f.input :target_group_id, :collection => Group.all.collect, :label => t('group_permissions.form.target_group_id.label'), :hint => conditional_hint('group_permissions.form.target_group_id.hint'), :include_blank => false
diff --git a/app/views/group_permissions/_index_core.html.haml b/app/views/group_permissions/_index_core.html.haml
new file mode 100644
index 0000000..ad06b38
--- /dev/null
+++ b/app/views/group_permissions/_index_core.html.haml
@@ -0,0 +1,11 @@
+%table.table.table-striped
+ %tr
+ %th= t('group_permissions.index.permission')
+ %th= t('group_permissions.index.target_group_id')
+
+
+ - for group_permission in group_permissions
+ %tr
+ %td= group_permission.permission
+ %td= group_permission.target_group
+ =render :partial => 'shared/index_view_edit_destroy_part', :locals => {:parent => group_permission.group, :child => group_permission}
diff --git a/app/views/group_permissions/edit.html.haml b/app/views/group_permissions/edit.html.haml
new file mode 100644
index 0000000..c673eea
--- /dev/null
+++ b/app/views/group_permissions/edit.html.haml
@@ -0,0 +1,3 @@
+- content_for :title, t("group_permissions.edit.page_title")
+
+= render "form" \ No newline at end of file
diff --git a/app/views/group_permissions/index.html.haml b/app/views/group_permissions/index.html.haml
new file mode 100644
index 0000000..0bc0c37
--- /dev/null
+++ b/app/views/group_permissions/index.html.haml
@@ -0,0 +1,6 @@
+- content_for :title, t("group_permissions.index.page_title")
+
+- if @group_permissions && @group_permissions.count > 0
+ = render "index_core", :group_permissions => @group_permissions
+
+= render :partial => 'shared/create_link', :locals => {:parent => @group, :child_class => GroupPermission} \ No newline at end of file
diff --git a/app/views/group_permissions/new.html.haml b/app/views/group_permissions/new.html.haml
new file mode 100644
index 0000000..8012273
--- /dev/null
+++ b/app/views/group_permissions/new.html.haml
@@ -0,0 +1,3 @@
+- content_for :title, t("group_permissions.new.page_title")
+
+= render "form" \ No newline at end of file
diff --git a/app/views/group_permissions/show.html.haml b/app/views/group_permissions/show.html.haml
new file mode 100644
index 0000000..402c5ce
--- /dev/null
+++ b/app/views/group_permissions/show.html.haml
@@ -0,0 +1,10 @@
+- content_for :title, t("group_permissions.show.page_title")
+
+%p
+ %strong= t('group_permissions.show.permission') + ":"
+ = @group_permission.permission
+%p
+ %strong= t('group_permissions.show.target_group_id') + ":"
+ = @group_permission.target_group_id
+
+= render :partial => 'shared/show_edit_destroy_part', :locals => { :parent => @group, :child => @group_permission }
diff --git a/app/views/groups/_form.html.haml b/app/views/groups/_form.html.haml
new file mode 100644
index 0000000..f5bdece
--- /dev/null
+++ b/app/views/groups/_form.html.haml
@@ -0,0 +1,7 @@
+= simple_form_for(@group) do |f|
+ = f.error_notification
+
+ = render "form_core", :f => f
+
+ .form-actions
+ = f.button :submit, conditional_t('groups.form.submit')
diff --git a/app/views/groups/_form_core.html.haml b/app/views/groups/_form_core.html.haml
new file mode 100644
index 0000000..1f9a39f
--- /dev/null
+++ b/app/views/groups/_form_core.html.haml
@@ -0,0 +1,4 @@
+.inputs
+ = f.input :name, :label => t('groups.form.name.label'), :hint => conditional_hint('groups.form.name.hint')
+ = f.input :active, :label => t('groups.form.active.label'), :hint => conditional_hint('groups.form.active.hint')
+ = f.input :comment, :label => t('groups.form.comment.label'), :hint => conditional_hint('groups.form.comment.hint')
diff --git a/app/views/groups/_index_core.html.haml b/app/views/groups/_index_core.html.haml
new file mode 100644
index 0000000..3a444bf
--- /dev/null
+++ b/app/views/groups/_index_core.html.haml
@@ -0,0 +1,17 @@
+%table.table.table-striped
+ %tr
+ %th
+ %th= t('groups.index.name')
+ %th= t('groups.index.comment')
+
+
+ - for group in groups
+ %tr
+ %td
+ -if group.active
+ %i.icon-ok
+ - else
+ %i.icon-ban-circle
+ %td= group.name
+ %td= group.comment
+ =render :partial => 'shared/index_view_edit_destroy_part', :locals => {:child => group} \ No newline at end of file
diff --git a/app/views/groups/edit.html.haml b/app/views/groups/edit.html.haml
new file mode 100644
index 0000000..7a3f784
--- /dev/null
+++ b/app/views/groups/edit.html.haml
@@ -0,0 +1,3 @@
+- content_for :title, t("groups.edit.page_title")
+
+= render "form" \ No newline at end of file
diff --git a/app/views/groups/index.html.haml b/app/views/groups/index.html.haml
new file mode 100644
index 0000000..7984b9e
--- /dev/null
+++ b/app/views/groups/index.html.haml
@@ -0,0 +1,6 @@
+- content_for :title, t("groups.index.page_title")
+
+- if @groups && @groups.count > 0
+ = render "index_core", :groups => @groups
+
+= render :partial => 'shared/create_link', :locals => {:child_class => Group} \ No newline at end of file
diff --git a/app/views/groups/new.html.haml b/app/views/groups/new.html.haml
new file mode 100644
index 0000000..e8017a8
--- /dev/null
+++ b/app/views/groups/new.html.haml
@@ -0,0 +1,3 @@
+- content_for :title, t("groups.new.page_title")
+
+= render "form" \ No newline at end of file
diff --git a/app/views/groups/show.html.haml b/app/views/groups/show.html.haml
new file mode 100644
index 0000000..fc291f3
--- /dev/null
+++ b/app/views/groups/show.html.haml
@@ -0,0 +1,25 @@
+- content_for :title, t("groups.show.page_title")
+
+%p
+ %strong= t('groups.show.name') + ":"
+ = @group.name
+%p
+ %strong= t('groups.show.active') + ":"
+ = @group.active
+%p
+ %strong= t('groups.show.comment') + ":"
+ = @group.comment
+
+= render :partial => 'shared/show_edit_destroy_part', :locals => { :child => @group }
+
+%h3= t('group_permissions.index.page_title')
+- if @group.group_permissions.any?
+ = render "group_permissions/index_core", :group_permissions => @group.group_permissions
+ %br
+= render :partial => 'shared/create_link', :locals => { :parent => @group, :child_class => GroupPermission }
+
+%h3= t('group_memberships.index.page_title')
+- if @group.group_memberships.any?
+ = render "group_memberships/index_core", :group_memberships => @group.group_memberships
+ %br
+= render :partial => 'shared/create_link', :locals => { :parent => @group, :child_class => GroupMembership }
diff --git a/app/views/gs_nodes/sync.xml.haml b/app/views/gs_nodes/sync.xml.haml
index a2fa71a..bba5c4e 100644
--- a/app/views/gs_nodes/sync.xml.haml
+++ b/app/views/gs_nodes/sync.xml.haml
@@ -55,7 +55,7 @@
- if !@call_forwards.blank?
%call_forwards
- @call_forwards.each do |call_forward|
- %call_forward{ :uuid => call_forward.uuid, :service => call_forward.call_forward_case.try(:value), :timeout => call_forward.timeout, :destination => call_forward.destination, :source => call_forward.source, :active => call_forward.active.to_s, :created_at => call_forward.created_at, :updated_at => call_forward.updated_at, :phone_number_uuid => call_forward.phone_number.try(:uuid), :depth => call_forward.depth, :call_forwardable_type => call_forward.call_forwardable_type, :call_forwardable_uuid => call_forward.call_forwardable.try(:uuid), :position => call_forward.position}
+ %call_forward{ :uuid => call_forward.uuid, :service => call_forward.call_forward_case.try(:value), :timeout => call_forward.timeout, :destination => call_forward.destination, :source => call_forward.source, :active => call_forward.active.to_s, :created_at => call_forward.created_at, :updated_at => call_forward.updated_at, :phone_number_uuid => call_forward.phone_number.try(:uuid), :depth => call_forward.depth, :call_forwardable_type => call_forward.call_forwardable_type, :call_forwardable_uuid => call_forward.call_forwardable.try(:uuid), :destinationable_type => call_forward.destinationable_type, :destinationable_uuid => call_forward.destinationable.try(:uuid), :position => call_forward.position}
- if !@softkeys.blank?
%softkeys
diff --git a/app/views/intruders/_index_core.html.haml b/app/views/intruders/_index_core.html.haml
index 31bbd11..63f2253 100644
--- a/app/views/intruders/_index_core.html.haml
+++ b/app/views/intruders/_index_core.html.haml
@@ -16,7 +16,14 @@
- for intruder in intruders
%tr
- %td= intruder.list_type.chars.first
+ %td
+ - if intruder.list_type == 'whitelist'
+ %i.icon-ok
+ - elsif intruder.bans > 0
+ %i.icon-fire
+ - elsif intruder.points > 0
+ %i.icon-warning-sign
+
%td= intruder.contact_ip
%td= intruder.contact_port
%td= intruder.points
diff --git a/app/views/layouts/_navbar.html.haml b/app/views/layouts/_navbar.html.haml
index 8e09859..8004c0e 100644
--- a/app/views/layouts/_navbar.html.haml
+++ b/app/views/layouts/_navbar.html.haml
@@ -1,16 +1,14 @@
.navbar.navbar-inverse.navbar-fixed-top
.navbar-inner
.container
- %a.brand{:href => (current_user.nil? ? '/' : tenant_path(current_user.current_tenant))}
- Gemeinschaft 5
-
- %a.btn.btn-navbar{"data-target" => ".nav-collapse", "data-toggle" => "collapse"}
- %span.icon-bar
- %span.icon-bar
- %span.icon-bar
+ %span.hidden-phone
+ %a.brand{:href => (current_user.nil? ? '/' : tenant_path(current_user.current_tenant))}
+ Gemeinschaft 5.1
.nav-collapse.collapse
%ul.nav
+ - if !GemeinschaftSetup.any?
+ %li=link_to t('restore_jobs.new.page_title'), new_restore_job_path
- if current_user && GemeinschaftSetup.any? && current_user.admin?
- if current_page?(page_help_path)
%li.active
@@ -29,13 +27,14 @@
- if current_user
%ul.nav.pull-right
%li.display
- - if current_user.image?
- = image_tag(current_user.image_url(:mini).to_s, :class => 'img-rounded')
- - else
- - if current_user.male?
- = image_tag 'icons/user-male-16x.png', :class => 'img-rounded'
+ %span.hidden-phone
+ - if current_user.image?
+ = image_tag(current_user.image_url(:mini).to_s, :class => 'img-rounded')
- else
- = image_tag 'icons/user-female-16x.png', :class => 'img-rounded'
+ - if current_user.male?
+ = image_tag 'icons/user-male-16x.png', :class => 'img-rounded'
+ - else
+ = image_tag 'icons/user-female-16x.png', :class => 'img-rounded'
- if current_page?(tenant_user_path(current_user.current_tenant, current_user))
%li.active
@@ -51,3 +50,7 @@
%a.navbar-link{:href => log_out_path}
%i.icon-off.icon-white
+ - if GuiFunction.display?('search_field_in_top_navigation_bar', current_user)
+ = form_tag search_path, :method => :post, :class => 'navbar-search pull-right' do
+ %input.text{:placeholder => 'Suchen ...', :name => 'q', :class => 'search-query span2'}
+
diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml
index 33a730f..eab6096 100644
--- a/app/views/layouts/application.html.haml
+++ b/app/views/layouts/application.html.haml
@@ -3,7 +3,7 @@
%head
%meta{:charset => "utf-8"}/
%title
- = content_for?(:title) ? yield(:title) : "Gemeinschaft 5"
+ = content_for?(:title) ? yield(:title) : "Gemeinschaft 5.1"
%meta{:name => 'viewport', :content => "width=device-width, initial-scale=1.0"}
- if content_for?(:meta_description)
%meta{:description => yield(:meta_description)}/
diff --git a/app/views/phone_books/_index_core.html.haml b/app/views/phone_books/_index_core.html.haml
index 09ce3a3..290a12e 100644
--- a/app/views/phone_books/_index_core.html.haml
+++ b/app/views/phone_books/_index_core.html.haml
@@ -5,7 +5,9 @@
%th
%span.visible-desktop
= t('phone_books.index.description')
- %th= t('phone_books.index.count')
+ %th
+ %span.visible-desktop
+ = t('phone_books.index.count')
%tbody
- for phone_book in phone_books
@@ -16,6 +18,7 @@
%span.visible-desktop
= phone_book.description
%td
- = number_with_delimiter( phone_book.phone_book_entries.count )
+ %span.visible-desktop
+ = number_with_delimiter( phone_book.phone_book_entries.count )
=render :partial => 'shared/index_view_edit_destroy_part', :locals => {:parent => phone_book.phone_bookable, :child => phone_book} \ No newline at end of file
diff --git a/app/views/phone_numbers/_form_core.html.haml b/app/views/phone_numbers/_form_core.html.haml
index a0a69db..1589e7e 100644
--- a/app/views/phone_numbers/_form_core.html.haml
+++ b/app/views/phone_numbers/_form_core.html.haml
@@ -1,7 +1,7 @@
.inputs
- if @phone_book_entry
- = f.input :name, :collection => ['Office', 'Home', 'Mobile', 'Fax'], :include_blank => false, :label => t('phone_numbers.form.name.label'), :hint => conditional_hint('phone_numbers.form.name.hint')
+ = f.input :name, :collection => PhoneBookEntry::PHONE_NUMBER_NAMES, :include_blank => false, :label => t('phone_numbers.form.name.label'), :hint => conditional_hint('phone_numbers.form.name.hint')
= f.input :number, :label => t('phone_numbers.form.number.label'), :hint => conditional_hint('phone_numbers.form.number.hint'), :autofocus => true
- else
- if @callthrough || @hunt_group_member || @access_authorization || current_user.current_tenant.array_of_available_internal_extensions_and_dids.count == 0 || current_user.current_tenant.array_of_available_internal_extensions_and_dids.count > 250
diff --git a/app/views/phone_numbers/show.html.haml b/app/views/phone_numbers/show.html.haml
index de6cb1b..9fe6ea4 100644
--- a/app/views/phone_numbers/show.html.haml
+++ b/app/views/phone_numbers/show.html.haml
@@ -9,15 +9,16 @@
%strong= t('phone_numbers.show.number') + ":"
= @phone_number.to_s
+= render :partial => 'shared/show_edit_destroy_part', :locals => { :parent => @phone_number.phone_numberable, :child => @phone_number }
+
- if @ringtoneable_classes.has_key?(@phone_number.phone_numberable.class.to_s)
%p
- %strong= t('ringtones.name') + ':'
- - if @phone_number.ringtones.count > 0
- = link_to @phone_number.ringtones.first, phone_number_ringtone_path(@phone_number, @phone_number.ringtones.first)
- - else
- = link_to t('ringtones.set_a_ringtone'), new_phone_number_ringtone_path(@phone_number)
-
-= render :partial => 'shared/show_edit_destroy_part', :locals => { :parent => @phone_number.phone_numberable, :child => @phone_number }
+ %strong= t('ringtones.name') + ':'
+ - if @phone_number.ringtones.count > 0
+ = @phone_number.ringtones.first
+ = render :partial => 'shared/show_edit_destroy_part', :locals => { :parent => @phone_number, :child => @phone_number.ringtones.first }
+ - else
+ = render :partial => 'shared/create_link', :locals => { :parent => @phone_number, :child_class => Ringtone }
- if @forwardable_classes.has_key?(@phone_number.phone_numberable.class.to_s)
%h3= t("call_forwards.index.page_title")
diff --git a/app/views/restore_jobs/_form.html.haml b/app/views/restore_jobs/_form.html.haml
new file mode 100644
index 0000000..43ced9a
--- /dev/null
+++ b/app/views/restore_jobs/_form.html.haml
@@ -0,0 +1,7 @@
+= simple_form_for(@restore_job) do |f|
+ = f.error_notification
+
+ = render "form_core", :f => f
+
+ .form-actions
+ = f.button :submit, conditional_t('restore_jobs.form.submit')
diff --git a/app/views/restore_jobs/_form_core.html.haml b/app/views/restore_jobs/_form_core.html.haml
new file mode 100644
index 0000000..017c124
--- /dev/null
+++ b/app/views/restore_jobs/_form_core.html.haml
@@ -0,0 +1,2 @@
+.inputs
+ = f.input :backup_file, :label => t('restore_jobs.form.backup_file.label'), :hint => conditional_hint('restore_jobs.form.backup_file.hint')
diff --git a/app/views/restore_jobs/_index_core.html.haml b/app/views/restore_jobs/_index_core.html.haml
new file mode 100644
index 0000000..f6127ba
--- /dev/null
+++ b/app/views/restore_jobs/_index_core.html.haml
@@ -0,0 +1,12 @@
+%table.table.table-striped
+ %tr
+ %th= t('restore_jobs.index.state')
+ %th= t('restore_jobs.index.backup_file')
+ %th
+
+
+ - for restore_job in restore_jobs
+ %tr
+ %td= restore_job.state
+ %td= restore_job.to_s
+ =render :partial => 'shared/index_view_edit_destroy_part', :locals => {:child => restore_job} \ No newline at end of file
diff --git a/app/views/restore_jobs/index.html.haml b/app/views/restore_jobs/index.html.haml
new file mode 100644
index 0000000..b8aa74e
--- /dev/null
+++ b/app/views/restore_jobs/index.html.haml
@@ -0,0 +1,6 @@
+- content_for :title, t("restore_jobs.index.page_title")
+
+- if @restore_jobs && @restore_jobs.count > 0
+ = render "index_core", :restore_jobs => @restore_jobs
+
+= render :partial => 'shared/create_link', :locals => {:child_class => RestoreJob} \ No newline at end of file
diff --git a/app/views/restore_jobs/new.html.haml b/app/views/restore_jobs/new.html.haml
new file mode 100644
index 0000000..ffae792
--- /dev/null
+++ b/app/views/restore_jobs/new.html.haml
@@ -0,0 +1,3 @@
+- content_for :title, t("restore_jobs.new.page_title")
+
+= render "form" \ No newline at end of file
diff --git a/app/views/restore_jobs/show.html.haml b/app/views/restore_jobs/show.html.haml
new file mode 100644
index 0000000..5993872
--- /dev/null
+++ b/app/views/restore_jobs/show.html.haml
@@ -0,0 +1,22 @@
+- content_for :title, t("restore_jobs.show.page_title")
+
+%table.table.table-striped
+ %tbody
+ %tr
+ %td
+ %strong= t('restore_jobs.show.state') + ":"
+ %td
+ = @restore_job.state
+ %tr
+ %td
+ %strong= t('restore_jobs.show.backup_file') + ":"
+ %td
+ = @restore_job.to_s
+ %tr
+ %td
+ %strong= t('backup_jobs.show.size_of_the_backup') + ":"
+ %td
+ - if @restore_job.backup_file?
+ = number_to_human_size(@restore_job.backup_file.size, :precision => 2)
+
+= render :partial => 'shared/show_edit_destroy_part', :locals => { :child => @restore_job } \ No newline at end of file
diff --git a/app/views/ringtones/_form_core.html.haml b/app/views/ringtones/_form_core.html.haml
index e44c950..de1cc38 100644
--- a/app/views/ringtones/_form_core.html.haml
+++ b/app/views/ringtones/_form_core.html.haml
@@ -1,3 +1,3 @@
.inputs
/ = f.input :audio, :label => t('ringtones.form.audio.label'), :hint => conditional_hint('ringtones.form.audio.hint')
- = f.input :bellcore_id, :collection => 0..10, :label => t('ringtones.form.bellcore_id.label'), :hint => conditional_hint('ringtones.form.bellcore_id.hint'), :include_blank => true
+ = f.input :bellcore_id, :collection => Ringtone::CORE_RINGTONES_AVAILABLE, :label => t('ringtones.form.bellcore_id.label'), :hint => conditional_hint('ringtones.form.bellcore_id.hint'), :include_blank => false
diff --git a/app/views/ringtones/_index_core.html.haml b/app/views/ringtones/_index_core.html.haml
index 715db3c..51347a5 100644
--- a/app/views/ringtones/_index_core.html.haml
+++ b/app/views/ringtones/_index_core.html.haml
@@ -1,12 +1,12 @@
%table.table.table-striped
%thead
%tr
- %th= t('ringtones.index.audio')
+ /%th= t('ringtones.index.audio')
%th= t('ringtones.index.bellcore_id')
%tbody
- for ringtone in ringtones
%tr
- %td= ringtone.audio
+ /%td= ringtone.audio
%td= ringtone.bellcore_id
=render :partial => 'shared/index_view_edit_destroy_part', :locals => {:parent => ringtone.ringtoneable, :child => ringtone} \ No newline at end of file
diff --git a/app/views/ringtones/index.html.haml b/app/views/ringtones/index.html.haml
index 2eea5fe..2e316a5 100644
--- a/app/views/ringtones/index.html.haml
+++ b/app/views/ringtones/index.html.haml
@@ -2,5 +2,5 @@
- if @ringtones.count > 0
= render "index_core", :ringtones => @ringtones
-
-= render :partial => 'shared/create_link', :locals => {:parent => @parent, :child_class => Ringtone} \ No newline at end of file
+- else
+ = render :partial => 'shared/create_link', :locals => {:parent => @parent, :child_class => Ringtone} \ No newline at end of file
diff --git a/app/views/sessions/new.html.haml b/app/views/sessions/new.html.haml
index 75dd3de..0c5c96d 100644
--- a/app/views/sessions/new.html.haml
+++ b/app/views/sessions/new.html.haml
@@ -1,8 +1,12 @@
- content_for :title, t("sessions.new.page_title")
-= simple_form_for :sessions, :url => sessions_path do |t|
- = t.input :login_data, :label => t('sessions.form.email'), :autofocus => true
- = t.input :password, :label => t('sessions.form.password'), :required => false
- = t.input :reset_password, :label => t('sessions.form.reset_password'), :as => :boolean
- .form-actions
- = t.button :submit, :value => 'Login'
+.row
+ .span12
+ %h1=t("sessions.new.page_title")
+
+ = simple_form_for :sessions, :url => sessions_path do |t|
+ = t.input :login_data, :label => t('sessions.form.email'), :autofocus => true
+ = t.input :password, :label => t('sessions.form.password'), :required => false
+ = t.input :reset_password, :label => t('sessions.form.reset_password'), :as => :boolean
+ .form-actions
+ = t.button :submit, :value => 'Login'
diff --git a/app/views/sip_accounts/_form_core.html.haml b/app/views/sip_accounts/_form_core.html.haml
index 1a8876a..d7c65d0 100644
--- a/app/views/sip_accounts/_form_core.html.haml
+++ b/app/views/sip_accounts/_form_core.html.haml
@@ -13,6 +13,4 @@
- if @sip_account.sip_accountable_type == 'User'
= f.input :hotdeskable, :label => t('sip_accounts.form.hotdeskable.label'), :hint => conditional_hint('sip_accounts.form.hotdeskable.hint')
= f.input :clip_no_screening, :label => t('sip_accounts.form.clip_no_screening.label'), :hint => conditional_hint('sip_accounts.form.clip_no_screening.hint')
- - if CallForward.where(:phone_number_id => @sip_account.phone_number_ids).count == 0 || @sip_account.callforward_rules_act_per_sip_account == true
- = f.input :callforward_rules_act_per_sip_account, :label => t('sip_accounts.form.callforward_rules_act_per_sip_account.label'), :hint => conditional_hint('sip_accounts.form.callforward_rules_act_per_sip_account.hint')
= f.input :language_code, :collection => Language.all.collect{|l| [l.to_s, l.code]}, :label => t('sip_accounts.form.language_code.label'), :hint => conditional_hint('sip_accounts.form.language_id.hint'), :include_blank => false
diff --git a/app/views/sip_accounts/_index_core.html.haml b/app/views/sip_accounts/_index_core.html.haml
index 34aac64..d98ea0a 100644
--- a/app/views/sip_accounts/_index_core.html.haml
+++ b/app/views/sip_accounts/_index_core.html.haml
@@ -20,13 +20,13 @@
- if sip_account.registration
%i.icon-ok
- else
- %i.icon-thumbs-down
+ %i.icon-ban-circle
%td
= sip_account.caller_name
- phone_numbers = sip_account.phone_numbers
%td
- if sip_account.phone_numbers.count > 0
- = render 'phone_numbers/listing', :phone_numbers => sip_account.phone_numbers.order(:number)
+ = render 'phone_numbers/listing', :phone_numbers => sip_account.phone_numbers.order(:position)
- if sip_accounts.map{ |sip_account| sip_account.phone_sip_accounts.any? }.include?(true)
%td
%span.hidden-phone
diff --git a/app/views/sip_accounts/show.html.haml b/app/views/sip_accounts/show.html.haml
index 72e10df..365aea8 100644
--- a/app/views/sip_accounts/show.html.haml
+++ b/app/views/sip_accounts/show.html.haml
@@ -37,11 +37,6 @@
%strong= t('sip_accounts.show.hotdeskable') + ":"
%td
= @sip_account.hotdeskable == true ? t('simple_form.yes') : t('simple_form.no')
- %tr
- %td
- %strong= t('sip_accounts.show.callforward_rules_act_per_sip_account') + ":"
- %td
- = @sip_account.callforward_rules_act_per_sip_account == true ? t('simple_form.yes') : t('simple_form.no')
- if @sip_account.registration.try(:network_ip) && @sip_account.registration.try(:network_port)
%tr
@@ -65,6 +60,21 @@
= render :partial => 'shared/show_edit_destroy_part', :locals => { :parent => @sip_account.sip_accountable, :child => @sip_account }
+%p
+ %strong= t('sip_accounts.show.tel_protocol') + ':'
+%p
+ %a.btn.btn-small.btn-default{ :href => '', :onclick => "navigator.registerProtocolHandler(\"tel\", \"#{@register_tel_protocol}\", \"#{@sip_account.to_s}\");" }
+ %i.icon-plus
+ = t('sip_accounts.show.register_tel_protocol')
+
+%p
+ %strong= t('ringtones.name') + ':'
+ - if @sip_account.ringtones.count > 0
+ = @sip_account.ringtones.first
+ = render :partial => 'shared/show_edit_destroy_part', :locals => { :parent => @sip_account, :child => @sip_account.ringtones.first }
+ - else
+ = render :partial => 'shared/create_link', :locals => { :parent => @sip_account, :child_class => Ringtone }
+
- if @sip_account.phone_numbers.count > 0 || can?(:create, @sip_account.phone_numbers.build)
%h2= t('phone_numbers.index.page_title')
- if @sip_account.phone_numbers.count > 0
@@ -72,9 +82,20 @@
%br
= render :partial => 'shared/create_link', :locals => { :parent => @sip_account, :child_class => PhoneNumber }
+- if @sip_account.call_forwards.count > 0 || can?(:create, @sip_account.call_forwards.build)
+ %h2= t('call_forwards.index.page_title')
+ - if @sip_account.call_forwards.count > 0
+ = render "call_forwards/index_core", :call_forwards => @sip_account.call_forwards
+ %br
+ = render :partial => 'shared/create_link', :locals => { :parent => @sip_account, :child_class => CallForward }
+
- if @sip_account.softkeys.count > 0 || can?(:create, @sip_account.softkeys.build)
%h2= t("softkeys.index.page_title")
- if @sip_account.softkeys.count > 0
= render "softkeys/index_core", :softkeys => @sip_account.softkeys
%br
- = render :partial => 'shared/create_link', :locals => { :parent => @sip_account, :child_class => Softkey } \ No newline at end of file
+ = render :partial => 'shared/create_link', :locals => { :parent => @sip_account, :child_class => Softkey }
+
+- if @sip_account.calls.count > 0
+ %h2= t("calls.index.page_title")
+ = render "calls/index_core", :calls => @sip_account.calls, :parent => @sip_account
diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml
index 0f6cc2c..8148005 100644
--- a/app/views/users/show.html.haml
+++ b/app/views/users/show.html.haml
@@ -29,22 +29,30 @@
= render :partial => 'shared/show_edit_destroy_part', :locals => { :parent => @tenant, :child => @user }
- @user.sip_accounts.each do |sip_account|
- - phone_number = sip_account.phone_numbers.order(:number).last
- - if phone_number && !phone_number.number.blank? && phone_number.number[0] != '+'
- %p
- %strong= sip_account.phone_numbers.order(:number).last.number
+ - phone_numbers = sip_account.phone_numbers.order(:position)
+ %p
+ - if phone_numbers[0]
+ %strong= phone_numbers[0].number
+ - else
+ %strong= sip_account.to_s
+ - if phone_numbers[1]
+ %strong= phone_numbers[1].number
+ - if phone_numbers[2]
+ %strong= phone_numbers[2].number
+ - if phone_numbers[3]
+ %strong ...
%p
=link_to t("call_histories.index.page_title"), sip_account_call_histories_path(sip_account)
%br
=link_to t("voicemail_messages.index.page_title"), sip_account_voicemail_messages_path(sip_account)
%br
- =link_to t("call_forwards.index.page_title"), phone_number_call_forwards_path(phone_number)
+ =link_to t("call_forwards.index.page_title"), sip_account_call_forwards_path(sip_account)
%br
=link_to t("voicemail_settings.index.page_title"), sip_account_voicemail_settings_path(sip_account)
%br
=link_to t("softkeys.index.page_title"), sip_account_softkeys_path(sip_account)
%br
- =link_to t("ringtones.show.page_title"), phone_number_ringtones_path(phone_number)
+ =link_to t("ringtones.show.page_title"), sip_account_ringtones_path(sip_account)
- if @user.conferences.any?
%p
diff --git a/config/backup.rb b/config/backup.rb
index e5816c1..b50f7a8 100644
--- a/config/backup.rb
+++ b/config/backup.rb
@@ -24,14 +24,31 @@ Backup::Model.new(:GS5, 'GS5 backup') do
db.host = "localhost"
db.port = 3306
db.socket = "/var/run/mysqld/mysqld.sock"
+ db.skip_tables = ["backup_jobs", "restore_jobs", "fax_thumbnails"]
end
##
# Faxes
#
- if File.exists?('/opt/gemeinschaft/public/uploads/fax_document')
+ if File.exists?('/var/opt/gemeinschaft/fax')
archive :faxes do |archive|
- archive.add '/opt/gemeinschaft/public/uploads/fax_document'
+ # Incoming faxes
+ #
+ Dir.glob("/var/opt/gemeinschaft/fax/in/**/*.pdf").each do |fax_file|
+ archive.add(fax_file)
+ end
+ Dir.glob("/var/opt/gemeinschaft/fax/in/**/*.tiff").each do |fax_file|
+ archive.add(fax_file)
+ end
+
+ # Outgoing faxes
+ #
+ Dir.glob("/var/opt/gemeinschaft/fax/out/**/*.pdf").each do |fax_file|
+ archive.add(fax_file)
+ end
+ Dir.glob("/var/opt/gemeinschaft/fax/out/**/*.tiff").each do |fax_file|
+ archive.add(fax_file)
+ end
end
end
@@ -55,6 +72,4 @@ Backup::Model.new(:GS5, 'GS5 backup') do
# Gzip [Compressor]
#
compress_with Gzip
-
-end
-
+end \ No newline at end of file
diff --git a/config/initializers/simple_form.rb b/config/initializers/simple_form.rb
index 062f823..06dc271 100644
--- a/config/initializers/simple_form.rb
+++ b/config/initializers/simple_form.rb
@@ -145,6 +145,7 @@ SimpleForm.setup do |config|
# How the label text should be generated altogether with the required text.
# config.label_text = lambda { |label, required| "#{required} #{label}" }
+ config.label_text = lambda { |label, required| "#{label}" }
# You can define the class to use on all labels. Default is nil.
config.label_class = 'control-label'
diff --git a/config/locales/views/call_forwards/de.yml b/config/locales/views/call_forwards/de.yml
index 3930938..4f6ee86 100644
--- a/config/locales/views/call_forwards/de.yml
+++ b/config/locales/views/call_forwards/de.yml
@@ -7,8 +7,8 @@ de:
successfuly_destroyed: 'Die Rufumleitung wurde gelöscht.'
index:
page_title: 'Rufumleitungen'
- phone_number_id: 'Telefonnummer'
- call_forward_case_id: 'Art der Rufumleitung'
+ call_forwardable: 'Umleitendes Objekt'
+ call_forward_case: 'Art der Rufumleitung'
timeout: 'Zeitüberschreitung'
destination: 'Ziel'
hunt_group: 'Rufgruppen-Verknüpfung'
@@ -25,8 +25,8 @@ de:
create_for: 'Neue Rufumleitung für die %{resource} anlegen'
show:
page_title: 'Rufumleitung anzeigen'
- phone_number_id: 'Telefonnummer'
- call_forward_case_id: 'Art der Rufumleitung'
+ call_forwardable: 'Umleitendes Objekt'
+ call_forward_case: 'Art der Rufumleitung'
timeout: 'Zeitüberschreitung'
destination: 'Ziel'
hunt_group: 'Rufgruppen-Verknüpfung'
@@ -44,10 +44,10 @@ de:
edit:
page_title: 'Rufumleitung bearbeiten'
form:
- phone_number_id:
- label: 'Telefonnummer'
+ call_forwardable:
+ label: 'Umleitendes Objekt'
hint: ''
- call_forward_case_id:
+ call_forward_case:
label: 'Art der Rufumleitung'
hint: ''
timeout:
diff --git a/config/locales/views/call_forwards/en.yml b/config/locales/views/call_forwards/en.yml
index 20fb834..65ae6b0 100644
--- a/config/locales/views/call_forwards/en.yml
+++ b/config/locales/views/call_forwards/en.yml
@@ -7,8 +7,8 @@ en:
successfuly_destroyed: 'Successfully destroyed call forward.'
index:
page_title: 'Call forwards'
- phone_number_id: 'Phone number'
- call_forward_case_id: 'Call forward case'
+ call_forwardable: 'Forwarding entity'
+ call_forward_case: 'Call forward case'
timeout: 'Timeout'
destination: 'Destination'
to_voicemail: 'Voicemail'
@@ -25,8 +25,8 @@ en:
create_for: 'New call forward for phone number %{resource}'
show:
page_title: 'Show call forward'
- phone_number_id: 'Phone number'
- call_forward_case_id: 'Call forward case'
+ call_forwardable: 'Forwarding entity'
+ call_forward_case: 'Call forward case'
timeout: 'Timeout'
destination: 'Destination'
hunt_group: 'Hunt group connection'
@@ -44,10 +44,10 @@ en:
edit:
page_title: 'Editing call forward'
form:
- phone_number_id:
- label: 'Phone number'
+ call_forwardable:
+ label: 'Forwarding entity'
hint: ''
- call_forward_case_id:
+ call_forward_case:
label: 'Call forward case'
hint: ''
timeout:
diff --git a/config/locales/views/calls/de.yml b/config/locales/views/calls/de.yml
new file mode 100644
index 0000000..1410e34
--- /dev/null
+++ b/config/locales/views/calls/de.yml
@@ -0,0 +1,37 @@
+de:
+ calls:
+ name: 'Anruf'
+ controller:
+ successfuly_created: 'Einen neue Anruf wurde erstellt.'
+ successfuly_updated: 'Der Anruf wurde aktualisiert.'
+ successfuly_destroyed: 'Der Anruf wurde aufgelegt.'
+ index:
+ page_title: 'Anrufe'
+ uuid: 'UUID'
+ actions:
+ confirm_destroy: 'Sind Sie sicher, dass Sie diese Anruf auflegen möchten?'
+ destroy: 'Löschen'
+ edit: 'Bearbeiten'
+ show: 'Anzeigen'
+ create: 'Neuer Anruf'
+ create_for: 'Neuer Anruf für %{resource}'
+ show:
+ page_title: 'Anruf'
+ uuid: 'UUID'
+ actions:
+ confirm_destroy: 'Sind Sie sicher, dass Sie diese Anruf auflegen möchten?'
+ destroy: 'Auflegen'
+ edit: 'Bearbeiten'
+ view_all: 'Alle Anrufe anzeigen'
+ new:
+ page_title: 'Neuer Anruf'
+ edit:
+ page_title: 'Anruf bearbeiten'
+ form:
+ uuid:
+ label: 'UUID'
+ hint: ''
+ destination:
+ label: 'Ziel'
+ hint: ''
+ submit: 'Absenden'
diff --git a/config/locales/views/calls/en.yml b/config/locales/views/calls/en.yml
new file mode 100644
index 0000000..9161d03
--- /dev/null
+++ b/config/locales/views/calls/en.yml
@@ -0,0 +1,37 @@
+en:
+ calls:
+ name: 'Call'
+ controller:
+ successfuly_created: 'Successfully created call.'
+ successfuly_updated: 'Successfully updated call.'
+ successfuly_destroyed: 'Successfully hung up call.'
+ index:
+ page_title: 'Calls'
+ uuid: 'UUID'
+ actions:
+ confirm_destroy: 'Are you sure you want to drop this call?'
+ destroy: 'Hang up'
+ edit: 'Edit'
+ show: 'View'
+ create: 'New'
+ create_for: 'New call for sip account %{resource}'
+ show:
+ page_title: 'Call'
+ uuid: 'UUID'
+ actions:
+ confirm_destroy: 'Are you sure you want to drop this call?'
+ destroy: 'Delete'
+ edit: 'Edit'
+ view_all: 'View all calls'
+ new:
+ page_title: 'New call'
+ edit:
+ page_title: 'Editing call'
+ form:
+ uuid:
+ label: 'UUID'
+ hint: ''
+ destination:
+ label: 'Destination'
+ hint: ''
+ submit: 'Submit'
diff --git a/config/locales/views/fax_accounts/de.yml b/config/locales/views/fax_accounts/de.yml
index cc93a24..8e6f954 100644
--- a/config/locales/views/fax_accounts/de.yml
+++ b/config/locales/views/fax_accounts/de.yml
@@ -1,12 +1,12 @@
de:
fax_accounts:
- name: 'Software-Fax-Konto'
+ name: 'Software-Fax'
controller:
- successfuly_created: 'Eine neues Software-Fax-Konto wurde erstellt.'
- successfuly_updated: 'Das Software-Fax-Konto wurde aktualisiert.'
- successfuly_destroyed: 'Das Software-Fax-Konto wurde gelöscht.'
+ successfuly_created: 'Eine neues Software-Fax wurde erstellt.'
+ successfuly_updated: 'Das Software-Fax wurde aktualisiert.'
+ successfuly_destroyed: 'Das Software-Fax wurde gelöscht.'
index:
- page_title: 'Software-Fax-Konten'
+ page_title: 'Software-Faxe'
name: 'Name'
station_id: 'Stations-ID'
email: 'E-Mail'
@@ -17,30 +17,30 @@ de:
sent: 'Gesendet'
retries: 'Max. Anzahl von Sendeversuchen'
last_update: 'Letzter Eintrag'
- send_a_fax: 'Fax versenden'
+ send_a_fax: 'versenden'
actions:
- confirm_destroy: 'Sind Sie sicher, dass Sie dieses Software-Fax-Konto löschen möchten?'
+ confirm_destroy: 'Sind Sie sicher, dass Sie dieses Software-Fax löschen möchten?'
destroy: 'Löschen'
edit: 'Bearbeiten'
show: 'Anzeigen'
create: 'Neu anlegen'
create_for: 'Neues Fax-Konto für %{resource} anlegen'
show:
- page_title: 'Software-Fax-Konto anzeigen'
+ page_title: 'Software-Fax anzeigen'
name: 'Name'
station_id: 'Stations-ID'
email: 'E-Mail'
days_till_auto_delete: 'Anzahl der Tage bis Faxe gelöscht werden'
retries: 'Max. Anzahl von Sendeversuchen'
actions:
- confirm_destroy: 'Sind Sie sicher, dass Sie dieses Software-Fax-Konto löschen möchten?'
+ confirm_destroy: 'Sind Sie sicher, dass Sie dieses Software-Fax löschen möchten?'
destroy: 'Löschen'
edit: 'Bearbeiten'
view_all: 'Alle anzeigen'
new:
- page_title: 'Neues Software-Fax-Konto'
+ page_title: 'Neues Software-Fax'
edit:
- page_title: 'Software-Fax-Konto bearbeiten'
+ page_title: 'Software-Fax bearbeiten'
form:
name:
label: 'Name'
diff --git a/config/locales/views/fax_documents/de.yml b/config/locales/views/fax_documents/de.yml
index 6bfa86b..da59833 100644
--- a/config/locales/views/fax_documents/de.yml
+++ b/config/locales/views/fax_documents/de.yml
@@ -62,7 +62,7 @@ de:
transmission_time: 'Ãœbertragungszeit'
sent_at: 'Sendezeit'
document_total_pages: 'Seitenanzahl'
- document_transferred_pages: 'Ãœbertragende Seiten'
+ document_transferred_pages: 'Ãœbertragene Seiten'
ecm_requested: 'Fehlerkorrektur (ECM) angefragt'
ecm_used: 'Fehlerkorrektur (ECM) verwendet'
image_resolution: 'Bildauflösung'
diff --git a/config/locales/views/gemeinschaft_setups/de.yml b/config/locales/views/gemeinschaft_setups/de.yml
index eb0145c..c035c96 100644
--- a/config/locales/views/gemeinschaft_setups/de.yml
+++ b/config/locales/views/gemeinschaft_setups/de.yml
@@ -27,7 +27,7 @@ de:
hint: ''
default_area_code:
label: 'Standard Ortsvorwahl'
- hint: '030 für Berlin, 0261 für Koblenz, 02631 für Neuwied, usw.'
+ hint: 'ohne führende Null; z.B. 30 für Berlin, 261 für Koblenz, 2631 für Neuwied, usw.'
trunk_access_code:
label: 'Amtsholungsziffer'
hint: ''
diff --git a/config/locales/views/gemeinschaft_setups/en.yml b/config/locales/views/gemeinschaft_setups/en.yml
index 3a1ac39..15edca5 100644
--- a/config/locales/views/gemeinschaft_setups/en.yml
+++ b/config/locales/views/gemeinschaft_setups/en.yml
@@ -11,7 +11,7 @@ en:
user_group_name: 'Users'
super_admin_group_name: 'Super-Admins'
new:
- page_title: 'New Gemeinschaft setup'
+ page_title: 'Gemeinschaft Setup'
form:
user_id:
label: 'User'
diff --git a/config/locales/views/group_memberships/de.yml b/config/locales/views/group_memberships/de.yml
new file mode 100644
index 0000000..7fdc100
--- /dev/null
+++ b/config/locales/views/group_memberships/de.yml
@@ -0,0 +1,50 @@
+de:
+ group_memberships:
+ name: 'Groupmembership'
+ controller:
+ successfuly_created: 'Groupmembership wurde angelegt.'
+ successfuly_updated: 'Groupmembership wurde aktualisiert.'
+ successfuly_destroyed: 'Groupmembership wurde gelöscht.'
+ index:
+ page_title: 'Ãœbersicht von Groupmembership'
+ group_id: 'Group'
+ item_type: 'Item type'
+ item_id: 'Item'
+ actions:
+ confirm_destroy: 'Sind Sie sicher, dass Sie folgendes löschen möchten: Groupmembership'
+ destroy: 'Löschen'
+ edit: 'Bearbeiten'
+ show: 'Anzeigen'
+ create: 'Neu anlegen'
+ create_for: 'Groupmembership neu anlegen für %{resource}'
+ show:
+ page_title: 'Groupmembership bearbeiten'
+ group_id: 'Group'
+ item_type: 'Item type'
+ item_id: 'Item'
+ actions:
+ confirm_destroy: 'Sind Sie sicher, dass die dieses Element löschen möchten?'
+ destroy: 'Löschen'
+ edit: 'Bearbeiten'
+ view_all: 'Alle anzeigen'
+ new:
+ page_title: 'Groupmembership neu anlegen'
+ actions:
+ back_to_list: 'Zurück zur Übersicht'
+ edit:
+ page_title: 'Groupmembership bearbeiten'
+ actions:
+ back_to_list: 'Zurück zur Übersicht'
+ edit: 'Bearbeiten'
+ view_all: 'Alle anzeigen'
+ form:
+ group_id:
+ label: 'Group'
+ hint: ''
+ item_type:
+ label: 'Item type'
+ hint: ''
+ item_id:
+ label: 'Item'
+ hint: ''
+ submit: 'Absenden' \ No newline at end of file
diff --git a/config/locales/views/group_memberships/en.yml b/config/locales/views/group_memberships/en.yml
new file mode 100644
index 0000000..35740a3
--- /dev/null
+++ b/config/locales/views/group_memberships/en.yml
@@ -0,0 +1,50 @@
+en:
+ group_memberships:
+ name: 'Groupmembership'
+ controller:
+ successfuly_created: 'Successfully created Groupmembership.'
+ successfuly_updated: 'Successfully updated Groupmembership.'
+ successfuly_destroyed: 'Successfully destroyed Groupmembership.'
+ index:
+ page_title: 'Listing Groupmembership'
+ group_id: 'Group'
+ item_type: 'Item type'
+ item_id: 'Item'
+ actions:
+ confirm_destroy: 'Are you sure you want to delete this Groupmembership?'
+ destroy: 'Delete'
+ edit: 'Edit'
+ show: 'View'
+ create: 'New'
+ create_for: 'New Groupmembership for %{resource}'
+ show:
+ page_title: 'Show Groupmembership'
+ group_id: 'Group'
+ item_type: 'Item type'
+ item_id: 'Item'
+ actions:
+ confirm_destroy: 'Are you sure you want to delete this element?'
+ destroy: 'Delete'
+ edit: 'Edit'
+ view_all: 'View All'
+ new:
+ page_title: 'New Groupmembership'
+ actions:
+ back_to_list: 'Back to Index'
+ edit:
+ page_title: 'Editing Groupmembership'
+ actions:
+ back_to_list: 'Back to Index'
+ edit: 'Edit'
+ view_all: 'View All'
+ form:
+ group_id:
+ label: 'Group'
+ hint: ''
+ item_type:
+ label: 'Item type'
+ hint: ''
+ item_id:
+ label: 'Item'
+ hint: ''
+ submit: 'Submit' \ No newline at end of file
diff --git a/config/locales/views/group_permissions/de.yml b/config/locales/views/group_permissions/de.yml
new file mode 100644
index 0000000..c075830
--- /dev/null
+++ b/config/locales/views/group_permissions/de.yml
@@ -0,0 +1,50 @@
+de:
+ group_permissions:
+ name: 'Grouppermission'
+ controller:
+ successfuly_created: 'Grouppermission wurde angelegt.'
+ successfuly_updated: 'Grouppermission wurde aktualisiert.'
+ successfuly_destroyed: 'Grouppermission wurde gelöscht.'
+ index:
+ page_title: 'Ãœbersicht von Grouppermission'
+ group_id: 'Group'
+ permission: 'Permission'
+ target_group_id: 'Target group'
+ actions:
+ confirm_destroy: 'Sind Sie sicher, dass Sie folgendes löschen möchten: Grouppermission'
+ destroy: 'Löschen'
+ edit: 'Bearbeiten'
+ show: 'Anzeigen'
+ create: 'Neu anlegen'
+ create_for: 'Grouppermission neu anlegen für %{resource}'
+ show:
+ page_title: 'Grouppermission bearbeiten'
+ group_id: 'Group'
+ permission: 'Permission'
+ target_group_id: 'Target group'
+ actions:
+ confirm_destroy: 'Sind Sie sicher, dass die dieses Element löschen möchten?'
+ destroy: 'Löschen'
+ edit: 'Bearbeiten'
+ view_all: 'Alle anzeigen'
+ new:
+ page_title: 'Grouppermission neu anlegen'
+ actions:
+ back_to_list: 'Zurück zur Übersicht'
+ edit:
+ page_title: 'Grouppermission bearbeiten'
+ actions:
+ back_to_list: 'Zurück zur Übersicht'
+ edit: 'Bearbeiten'
+ view_all: 'Alle anzeigen'
+ form:
+ group_id:
+ label: 'Group'
+ hint: ''
+ permission:
+ label: 'Permission'
+ hint: ''
+ target_group_id:
+ label: 'Target group'
+ hint: ''
+ submit: 'Absenden' \ No newline at end of file
diff --git a/config/locales/views/group_permissions/en.yml b/config/locales/views/group_permissions/en.yml
new file mode 100644
index 0000000..2a5f48e
--- /dev/null
+++ b/config/locales/views/group_permissions/en.yml
@@ -0,0 +1,50 @@
+en:
+ group_permissions:
+ name: 'Grouppermission'
+ controller:
+ successfuly_created: 'Successfully created Grouppermission.'
+ successfuly_updated: 'Successfully updated Grouppermission.'
+ successfuly_destroyed: 'Successfully destroyed Grouppermission.'
+ index:
+ page_title: 'Listing Grouppermission'
+ group_id: 'Group'
+ permission: 'Permission'
+ target_group_id: 'Target group'
+ actions:
+ confirm_destroy: 'Are you sure you want to delete this Grouppermission?'
+ destroy: 'Delete'
+ edit: 'Edit'
+ show: 'View'
+ create: 'New'
+ create_for: 'New Grouppermission for %{resource}'
+ show:
+ page_title: 'Show Grouppermission'
+ group_id: 'Group'
+ permission: 'Permission'
+ target_group_id: 'Target group'
+ actions:
+ confirm_destroy: 'Are you sure you want to delete this element?'
+ destroy: 'Delete'
+ edit: 'Edit'
+ view_all: 'View All'
+ new:
+ page_title: 'New Grouppermission'
+ actions:
+ back_to_list: 'Back to Index'
+ edit:
+ page_title: 'Editing Grouppermission'
+ actions:
+ back_to_list: 'Back to Index'
+ edit: 'Edit'
+ view_all: 'View All'
+ form:
+ group_id:
+ label: 'Group'
+ hint: ''
+ permission:
+ label: 'Permission'
+ hint: ''
+ target_group_id:
+ label: 'Target group'
+ hint: ''
+ submit: 'Submit' \ No newline at end of file
diff --git a/config/locales/views/groups/de.yml b/config/locales/views/groups/de.yml
new file mode 100644
index 0000000..fc60a72
--- /dev/null
+++ b/config/locales/views/groups/de.yml
@@ -0,0 +1,50 @@
+de:
+ groups:
+ name: 'Group'
+ controller:
+ successfuly_created: 'Group wurde angelegt.'
+ successfuly_updated: 'Group wurde aktualisiert.'
+ successfuly_destroyed: 'Group wurde gelöscht.'
+ index:
+ page_title: 'Ãœbersicht von Group'
+ name: 'Name'
+ active: 'Active'
+ comment: 'Comment'
+ actions:
+ confirm_destroy: 'Sind Sie sicher, dass Sie folgendes löschen möchten: Group'
+ destroy: 'Löschen'
+ edit: 'Bearbeiten'
+ show: 'Anzeigen'
+ create: 'Neu anlegen'
+ create_for: 'Group neu anlegen für %{resource}'
+ show:
+ page_title: 'Group bearbeiten'
+ name: 'Name'
+ active: 'Active'
+ comment: 'Comment'
+ actions:
+ confirm_destroy: 'Sind Sie sicher, dass die dieses Element löschen möchten?'
+ destroy: 'Löschen'
+ edit: 'Bearbeiten'
+ view_all: 'Alle anzeigen'
+ new:
+ page_title: 'Group neu anlegen'
+ actions:
+ back_to_list: 'Zurück zur Übersicht'
+ edit:
+ page_title: 'Group bearbeiten'
+ actions:
+ back_to_list: 'Zurück zur Übersicht'
+ edit: 'Bearbeiten'
+ view_all: 'Alle anzeigen'
+ form:
+ name:
+ label: 'Name'
+ hint: ''
+ active:
+ label: 'Active'
+ hint: ''
+ comment:
+ label: 'Comment'
+ hint: ''
+ submit: 'Absenden' \ No newline at end of file
diff --git a/config/locales/views/groups/en.yml b/config/locales/views/groups/en.yml
new file mode 100644
index 0000000..a7fb666
--- /dev/null
+++ b/config/locales/views/groups/en.yml
@@ -0,0 +1,50 @@
+en:
+ groups:
+ name: 'Group'
+ controller:
+ successfuly_created: 'Successfully created Group.'
+ successfuly_updated: 'Successfully updated Group.'
+ successfuly_destroyed: 'Successfully destroyed Group.'
+ index:
+ page_title: 'Listing Group'
+ name: 'Name'
+ active: 'Active'
+ comment: 'Comment'
+ actions:
+ confirm_destroy: 'Are you sure you want to delete this Group?'
+ destroy: 'Delete'
+ edit: 'Edit'
+ show: 'View'
+ create: 'New'
+ create_for: 'New Group for %{resource}'
+ show:
+ page_title: 'Show Group'
+ name: 'Name'
+ active: 'Active'
+ comment: 'Comment'
+ actions:
+ confirm_destroy: 'Are you sure you want to delete this element?'
+ destroy: 'Delete'
+ edit: 'Edit'
+ view_all: 'View All'
+ new:
+ page_title: 'New Group'
+ actions:
+ back_to_list: 'Back to Index'
+ edit:
+ page_title: 'Editing Group'
+ actions:
+ back_to_list: 'Back to Index'
+ edit: 'Edit'
+ view_all: 'View All'
+ form:
+ name:
+ label: 'Name'
+ hint: ''
+ active:
+ label: 'Active'
+ hint: ''
+ comment:
+ label: 'Comment'
+ hint: ''
+ submit: 'Submit' \ No newline at end of file
diff --git a/config/locales/views/phone_book_entries/de.yml b/config/locales/views/phone_book_entries/de.yml
index 2c77aa5..bdd0d67 100644
--- a/config/locales/views/phone_book_entries/de.yml
+++ b/config/locales/views/phone_book_entries/de.yml
@@ -6,7 +6,7 @@ de:
successfuly_updated: 'Der Telefonbucheintrag "%{resource}" wurde aktualisiert.'
successfuly_destroyed: 'Der Telefonbucheintrag wurde gelöscht.'
index:
- page_title: 'Anzahl Telefonbucheinträge'
+ page_title: 'Telefonbucheinträge'
phone_book_id: 'Telefonbuch'
first_name: 'Vorname'
middle_name: 'Zweiter Vorname'
diff --git a/config/locales/views/phone_books/de.yml b/config/locales/views/phone_books/de.yml
index fa93945..c7ba5c7 100644
--- a/config/locales/views/phone_books/de.yml
+++ b/config/locales/views/phone_books/de.yml
@@ -5,7 +5,7 @@ de:
name: 'Firmentelefonbuch'
description: 'Ein für alle Benutzer von %{resource} lesbares Telefonbuch.'
private_phone_book:
- name: 'Privates Telefonbuch von %{resource}'
+ name: 'Privates Telefonbuch'
description: 'Ein privates Telefonbuch.'
controller:
successfuly_created: 'Ein neues Telefonbuch wurde erstellt.'
diff --git a/config/locales/views/restore_jobs/de.yml b/config/locales/views/restore_jobs/de.yml
new file mode 100644
index 0000000..3fdd72c
--- /dev/null
+++ b/config/locales/views/restore_jobs/de.yml
@@ -0,0 +1,45 @@
+de:
+ restore_jobs:
+ name: 'Restore Auftrag'
+ controller:
+ successfuly_created: 'Restore Auftrag wurde angelegt.'
+ successfuly_updated: 'Restore Auftrag wurde aktualisiert.'
+ successfuly_destroyed: 'Restore Auftrag wurde gelöscht.'
+ index:
+ page_title: 'Liste Restore Aufträge'
+ state: 'Status'
+ backup_file: 'Backup Datei'
+ actions:
+ confirm_destroy: 'Sind Sie sicher, dass Sie folgendes löschen möchten: Restore Auftrag'
+ destroy: 'Löschen'
+ edit: 'Bearbeiten'
+ show: 'Anzeigen'
+ create: 'Neu anlegen'
+ create_for: 'Restore Auftrag neu anlegen für %{resource}'
+ show:
+ page_title: 'Restore Auftrag bearbeiten'
+ state: 'Status'
+ backup_file: 'Backup Datei'
+ actions:
+ confirm_destroy: 'Sind Sie sicher, dass die dieses Element löschen möchten?'
+ destroy: 'Löschen'
+ edit: 'Bearbeiten'
+ view_all: 'Alle anzeigen'
+ new:
+ page_title: 'Restore von einem Backup'
+ actions:
+ back_to_list: 'Zurück zur Übersicht'
+ edit:
+ page_title: 'Restore Auftrag bearbeiten'
+ actions:
+ back_to_list: 'Zurück zur Übersicht'
+ edit: 'Bearbeiten'
+ view_all: 'Alle anzeigen'
+ form:
+ state:
+ label: 'Status'
+ hint: ''
+ backup_file:
+ label: 'Backup Datei'
+ hint: ''
+ submit: 'Absenden' \ No newline at end of file
diff --git a/config/locales/views/restore_jobs/en.yml b/config/locales/views/restore_jobs/en.yml
new file mode 100644
index 0000000..636c335
--- /dev/null
+++ b/config/locales/views/restore_jobs/en.yml
@@ -0,0 +1,45 @@
+en:
+ restore_jobs:
+ name: 'Restorejob'
+ controller:
+ successfuly_created: 'Successfully created Restorejob.'
+ successfuly_updated: 'Successfully updated Restorejob.'
+ successfuly_destroyed: 'Successfully destroyed Restorejob.'
+ index:
+ page_title: 'Listing Restorejob'
+ state: 'State'
+ backup_file: 'Backup file'
+ actions:
+ confirm_destroy: 'Are you sure you want to delete this Restorejob?'
+ destroy: 'Delete'
+ edit: 'Edit'
+ show: 'View'
+ create: 'New'
+ create_for: 'New Restorejob for %{resource}'
+ show:
+ page_title: 'Show Restorejob'
+ state: 'State'
+ backup_file: 'Backup file'
+ actions:
+ confirm_destroy: 'Are you sure you want to delete this element?'
+ destroy: 'Delete'
+ edit: 'Edit'
+ view_all: 'View All'
+ new:
+ page_title: 'Restore from a backup'
+ actions:
+ back_to_list: 'Back to Index'
+ edit:
+ page_title: 'Editing Restorejob'
+ actions:
+ back_to_list: 'Back to Index'
+ edit: 'Edit'
+ view_all: 'View All'
+ form:
+ state:
+ label: 'State'
+ hint: ''
+ backup_file:
+ label: 'Backup file'
+ hint: ''
+ submit: 'Submit' \ No newline at end of file
diff --git a/config/locales/views/sip_accounts/de.yml b/config/locales/views/sip_accounts/de.yml
index 7a7e540..2b4939b 100644
--- a/config/locales/views/sip_accounts/de.yml
+++ b/config/locales/views/sip_accounts/de.yml
@@ -41,6 +41,8 @@ de:
registration: 'Registrierung'
expires: 'Läuft ab'
user_agent: 'User Agent'
+ tel_protocol: 'TEL Protokoll'
+ register_tel_protocol: 'Für tel: URLs registrieren'
actions:
confirm_destroy: 'Sind Sie sicher, dass Sie diesen SIP-Account löschen möchten?'
destroy: 'Löschen'
diff --git a/config/locales/views/sip_accounts/en.yml b/config/locales/views/sip_accounts/en.yml
index 35d5456..78d20c2 100644
--- a/config/locales/views/sip_accounts/en.yml
+++ b/config/locales/views/sip_accounts/en.yml
@@ -41,6 +41,8 @@ en:
registration: 'Registration'
expires: 'Expires'
user_agent: 'User Agent'
+ tel_protocol: 'TEL Protocol'
+ register_tel_protocol: 'Register for tel: URLs with browser'
actions:
confirm_destroy: 'Are you sure you want to delete this SIP account?'
destroy: 'Delete'
diff --git a/config/routes.rb b/config/routes.rb
index 65a9ac2..2fe1682 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -1,5 +1,12 @@
Gemeinschaft42c::Application.routes.draw do
+ resources :restore_jobs
+
+ resources :groups do
+ resources :group_memberships
+ resources :group_permissions
+ end
+
resources :sim_card_providers do
resources :sim_cards, :except => [:edit, :update]
end
@@ -248,6 +255,9 @@ Gemeinschaft42c::Application.routes.draw do
resources :phones_sip_accounts
resources :phone_numbers
resources :softkeys
+ resources :call_forwards
+ resources :ringtones
+ resources :calls
resources :call_histories do
collection do
delete 'destroy_multiple'
@@ -267,6 +277,9 @@ Gemeinschaft42c::Application.routes.draw do
end
end
resources :voicemail_settings
+ member do
+ get 'call'
+ end
end
resources :phones, :only => [] do
diff --git a/config/schedule.rb b/config/schedule.rb
index 94603f1..f2c1a09 100644
--- a/config/schedule.rb
+++ b/config/schedule.rb
@@ -7,7 +7,7 @@ end
# Auto-Reboot of Phones which should be rebootet
#
every 1.day, :at => '2:30 am' do
- command "/opt/GS5/script/logout_phones.sh"
+ command "/opt/GS5/script/logout_phones"
end
# Learn more: http://github.com/javan/whenever
diff --git a/db/migrate/20130109090000_populate_gs_parameter_with_dialplan_defaults.rb b/db/migrate/20130109090000_populate_gs_parameter_with_dialplan_defaults.rb
index fe1cdae..a8350a3 100644
--- a/db/migrate/20130109090000_populate_gs_parameter_with_dialplan_defaults.rb
+++ b/db/migrate/20130109090000_populate_gs_parameter_with_dialplan_defaults.rb
@@ -79,7 +79,7 @@ class PopulateGsParameterWithDialplanDefaults < ActiveRecord::Migration
GsParameter.create(:entity => 'conferences', :section => 'parameters', :name => 'rate', :value => 16000, :class_type => 'Integer')
GsParameter.create(:entity => 'conferences', :section => 'parameters', :name => 'interval', :value => 20, :class_type => 'Integer')
GsParameter.create(:entity => 'conferences', :section => 'parameters', :name => 'energy-level', :value => 300, :class_type => 'Integer')
- GsParameter.create(:entity => 'conferences', :section => 'parameters', :name => 'sound-prefix', :value => '/opt/freeswitch/sounds/en/us/callie', :class_type => 'String')
+ GsParameter.create(:entity => 'conferences', :section => 'parameters', :name => 'sound-prefix', :value => '/opt/freeswitch/sounds/de/tts/google', :class_type => 'String')
GsParameter.create(:entity => 'conferences', :section => 'parameters', :name => 'muted-sound', :value => 'conference/conf-muted.wav', :class_type => 'String')
GsParameter.create(:entity => 'conferences', :section => 'parameters', :name => 'unmuted-sound', :value => 'conference/conf-unmuted.wav', :class_type => 'String')
GsParameter.create(:entity => 'conferences', :section => 'parameters', :name => 'alone-sound', :value => 'conference/conf-alone.wav', :class_type => 'String')
@@ -101,7 +101,7 @@ class PopulateGsParameterWithDialplanDefaults < ActiveRecord::Migration
GsParameter.create(:entity => 'dialplan', :section => 'parameters', :name => 'dial_timeout', :value => '120', :class_type => 'Integer')
GsParameter.create(:entity => 'dialplan', :section => 'parameters', :name => 'max_loops', :value => '20', :class_type => 'Integer')
GsParameter.create(:entity => 'dialplan', :section => 'parameters', :name => 'default_ringtone', :value => '1', :class_type => 'Integer')
- GsParameter.create(:entity => 'dialplan', :section => 'parameters', :name => 'default_language', :value => 'en', :class_type => 'String')
+ GsParameter.create(:entity => 'dialplan', :section => 'parameters', :name => 'default_language', :value => 'de', :class_type => 'String')
GsParameter.create(:entity => 'dialplan', :section => 'parameters', :name => 'phone_book_entry_image_url', :value => 'http://192.168.0.150/uploads/phone_book_entry/image', :class_type => 'String')
GsParameter.create(:entity => 'dialplan', :section => 'parameters', :name => 'user_image_url', :value => 'http://192.168.0.150/uploads/user/image', :class_type => 'String')
GsParameter.create(:entity => 'dialplan', :section => 'parameters', :name => 'ringtone_url', :value => 'http://192.168.0.150', :class_type => 'String')
diff --git a/db/migrate/20130213110000_add_sounds_to_parameters.rb b/db/migrate/20130213110000_add_sounds_to_parameters.rb
index 8c4cd94..dd20ca3 100644
--- a/db/migrate/20130213110000_add_sounds_to_parameters.rb
+++ b/db/migrate/20130213110000_add_sounds_to_parameters.rb
@@ -1,7 +1,7 @@
class AddSoundsToParameters < ActiveRecord::Migration
def up
GsParameter.create(:entity => 'dialplan', :section => 'sounds', :name => 'en', :value => '/opt/freeswitch/sounds/en/us/callie', :class_type => 'String')
- GsParameter.create(:entity => 'dialplan', :section => 'sounds', :name => 'de', :value => '/opt/freeswitch/sounds/de/de/callie', :class_type => 'String')
+ GsParameter.create(:entity => 'dialplan', :section => 'sounds', :name => 'de', :value => '/opt/freeswitch/sounds/de/tts/google', :class_type => 'String')
end
def down
diff --git a/db/migrate/20130219135000_remove_sound_prefix_from_conference_parameters.rb b/db/migrate/20130219135000_remove_sound_prefix_from_conference_parameters.rb
new file mode 100644
index 0000000..950e3af
--- /dev/null
+++ b/db/migrate/20130219135000_remove_sound_prefix_from_conference_parameters.rb
@@ -0,0 +1,8 @@
+class RemoveSoundPrefixFromConferenceParameters < ActiveRecord::Migration
+ def up
+ GsParameter.where(:entity => 'conferences', :section => 'parameters', :name => 'sound-prefix').destroy_all
+ end
+
+ def down
+ end
+end
diff --git a/db/migrate/20130222074610_create_groups.rb b/db/migrate/20130222074610_create_groups.rb
new file mode 100644
index 0000000..e5848b9
--- /dev/null
+++ b/db/migrate/20130222074610_create_groups.rb
@@ -0,0 +1,14 @@
+class CreateGroups < ActiveRecord::Migration
+ def self.up
+ create_table :groups do |t|
+ t.string :name
+ t.boolean :active
+ t.string :comment
+ t.timestamps
+ end
+ end
+
+ def self.down
+ drop_table :groups
+ end
+end
diff --git a/db/migrate/20130222074652_create_group_memberships.rb b/db/migrate/20130222074652_create_group_memberships.rb
new file mode 100644
index 0000000..e572445
--- /dev/null
+++ b/db/migrate/20130222074652_create_group_memberships.rb
@@ -0,0 +1,14 @@
+class CreateGroupMemberships < ActiveRecord::Migration
+ def self.up
+ create_table :group_memberships do |t|
+ t.integer :group_id
+ t.string :item_type
+ t.integer :item_id
+ t.timestamps
+ end
+ end
+
+ def self.down
+ drop_table :group_memberships
+ end
+end
diff --git a/db/migrate/20130222092313_create_group_permissions.rb b/db/migrate/20130222092313_create_group_permissions.rb
new file mode 100644
index 0000000..5949819
--- /dev/null
+++ b/db/migrate/20130222092313_create_group_permissions.rb
@@ -0,0 +1,14 @@
+class CreateGroupPermissions < ActiveRecord::Migration
+ def self.up
+ create_table :group_permissions do |t|
+ t.integer :group_id
+ t.string :permission
+ t.integer :target_group_id
+ t.timestamps
+ end
+ end
+
+ def self.down
+ drop_table :group_permissions
+ end
+end
diff --git a/db/migrate/20130224081700_groups_to_user_groups_in_routes.rb b/db/migrate/20130224081700_groups_to_user_groups_in_routes.rb
new file mode 100644
index 0000000..5e03cfa
--- /dev/null
+++ b/db/migrate/20130224081700_groups_to_user_groups_in_routes.rb
@@ -0,0 +1,19 @@
+class GroupsToUserGroupsInRoutes < ActiveRecord::Migration
+ def up
+ RouteElement.where(:var_in => 'val:auth_account.owner.groups').each do |route_element|
+ route_element.update_attributes(:var_in => 'val:auth_account.owner.user_groups')
+ end
+ RouteElement.where(:var_in => 'val:account.owner.groups').each do |route_element|
+ route_element.update_attributes(:var_in => 'val:account.owner.user_groups')
+ end
+ end
+
+ def down
+ RouteElement.where(:var_in => 'val:auth_account.owner.user_groups').each do |route_element|
+ route_element.update_attributes(:var_in => 'val:auth_account.owner.groups')
+ end
+ RouteElement.where(:var_in => 'val:account.owner.user_groups').each do |route_element|
+ route_element.update_attributes(:var_in => 'val:account.owner.groups')
+ end
+ end
+end
diff --git a/db/migrate/20130224091700_add_initial_groups.rb b/db/migrate/20130224091700_add_initial_groups.rb
new file mode 100644
index 0000000..f680fb6
--- /dev/null
+++ b/db/migrate/20130224091700_add_initial_groups.rb
@@ -0,0 +1,22 @@
+class AddInitialGroups < ActiveRecord::Migration
+ def up
+ Group.create(:name => 'admins', :active => true, :comment => 'Administrator user accounts')
+ Group.create(:name => 'users', :active => true, :comment => 'Generic user accounts')
+ Group.create(:name => 'tenant_sip_accounts', :active => true, :comment => 'SIP accounts owned by tenants')
+
+ user_sip_accounts = Group.create(:name => 'user_sip_accounts', :active => true, :comment => 'SIP accounts owned by user accounts')
+ user_sip_accounts.group_permissions.create(:permission => 'pickup', :target_group_id => user_sip_accounts.id)
+
+ Group.create(:name => 'international_calls', :active => true, :comment => 'International calls permitted')
+ Group.create(:name => 'national_calls', :active => true, :comment => 'National calls permitted')
+
+ GsParameter.create(:entity => 'group', :section => 'default', :name => 'User.admin', :value => '--- [admins]\n', :class_type => 'YAML')
+ GsParameter.create(:entity => 'group', :section => 'default', :name => 'User', :value => '--- [users]\n', :class_type => 'YAML')
+ GsParameter.create(:entity => 'group', :section => 'default', :name => 'SipAccount.user', :value => '--- [user_sip_accounts, international_calls, national_calls]\n', :class_type => 'YAML')
+ GsParameter.create(:entity => 'group', :section => 'default', :name => 'SipAccount.tenant', :value => '--- [tenant_sip_accounts]\n', :class_type => 'YAML')
+ end
+
+ def down
+ Group.destroy_all
+ end
+end
diff --git a/db/migrate/20130225091200_add_destinationable_to_call_forward.rb b/db/migrate/20130225091200_add_destinationable_to_call_forward.rb
new file mode 100644
index 0000000..89e4b3b
--- /dev/null
+++ b/db/migrate/20130225091200_add_destinationable_to_call_forward.rb
@@ -0,0 +1,21 @@
+class AddDestinationableToCallForward < ActiveRecord::Migration
+ def up
+ add_column :call_forwards, :destinationable_type, :string
+ add_column :call_forwards, :destinationable_id, :integer
+
+ CallForward.all.each do |call_forward|
+ call_forward.update_attributes(:destinationable_type => call_forward.call_forwardable_type, :destinationable_id => call_forward.call_forwardable_id, :call_forwardable_type => 'PhoneNumber', :call_forwardable_id => call_forward.phone_number_id )
+ end
+
+ remove_column :call_forwards, :phone_number_id
+ end
+
+ def down
+ add_column :call_forwards, :phone_number_id, :integer
+ CallForward.where(:call_forwardable_type => 'PhoneNumber').each do |call_forward|
+ call_forward.update_attributes(:phone_number_id => call_forward.call_forwardable_id, :call_forwardable_type => call_forward.destinationable_type, :call_forwardable_id => call_forward.destinationable_id)
+ end
+ remove_column :call_forwards, :destinationable_type
+ remove_column :call_forwards, :destinationable_id
+ end
+end
diff --git a/db/migrate/20130225160423_create_restore_jobs.rb b/db/migrate/20130225160423_create_restore_jobs.rb
new file mode 100644
index 0000000..9f83791
--- /dev/null
+++ b/db/migrate/20130225160423_create_restore_jobs.rb
@@ -0,0 +1,13 @@
+class CreateRestoreJobs < ActiveRecord::Migration
+ def self.up
+ create_table :restore_jobs do |t|
+ t.string :state
+ t.string :backup_file
+ t.timestamps
+ end
+ end
+
+ def self.down
+ drop_table :restore_jobs
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index df55604..60bc7f5 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,7 +11,7 @@
#
# It's strongly recommended to check this file into your version control system.
-ActiveRecord::Schema.define(:version => 20130215133749) do
+ActiveRecord::Schema.define(:version => 20130225160423) do
create_table "access_authorizations", :force => true do |t|
t.string "access_authorizationable_type"
@@ -554,6 +554,30 @@ ActiveRecord::Schema.define(:version => 20130215133749) do
t.string "trunk_access_code"
end
+ create_table "group_memberships", :force => true do |t|
+ t.integer "group_id"
+ t.string "item_type"
+ t.integer "item_id"
+ t.datetime "created_at", :null => false
+ t.datetime "updated_at", :null => false
+ end
+
+ create_table "group_permissions", :force => true do |t|
+ t.integer "group_id"
+ t.string "permission"
+ t.integer "target_group_id"
+ t.datetime "created_at", :null => false
+ t.datetime "updated_at", :null => false
+ end
+
+ create_table "groups", :force => true do |t|
+ t.string "name"
+ t.boolean "active"
+ t.string "comment"
+ t.datetime "created_at", :null => false
+ t.datetime "updated_at", :null => false
+ end
+
create_table "gs_cluster_sync_log_entries", :force => true do |t|
t.integer "gs_node_id"
t.string "class_name"
@@ -854,6 +878,13 @@ ActiveRecord::Schema.define(:version => 20130215133749) do
add_index "registrations", ["reg_user", "realm", "hostname"], :name => "regindex1"
+ create_table "restore_jobs", :force => true do |t|
+ t.string "state"
+ t.string "backup_file"
+ t.datetime "created_at", :null => false
+ t.datetime "updated_at", :null => false
+ end
+
create_table "ringtones", :force => true do |t|
t.string "ringtoneable_type"
t.integer "ringtoneable_id"
diff --git a/lib/tasks/backup.rake b/lib/tasks/backup.rake
index c285e1f..21b0fac 100644
--- a/lib/tasks/backup.rake
+++ b/lib/tasks/backup.rake
@@ -3,4 +3,56 @@ namespace :backup do
task :daily_backup => :environment do
# This would be the daily backup.
end
+
+ desc "Restore the system"
+ task :restore => :environment do
+ # This task takes the first RestoreJob to restore the system.
+ #
+ if RestoreJob.where(:state => 'new').any?
+ restore_job = RestoreJob.where(:state => 'new').order(:created_at).last
+ tmp_dir = "/tmp/gs5_restore_directory"
+ FileUtils.rm_rf tmp_dir
+ FileUtils.mkdir_p tmp_dir
+ system "cd #{tmp_dir} && sudo /bin/tar xzf #{restore_job.backup_file.path}"
+ restore_directory = Dir.glob("/tmp/gs5_restore_directory/*").first
+ system "cd #{restore_directory} && sudo /bin/tar xf GS5.tar && rm GS5.tar"
+
+ # Restore faxes
+ #
+ system "cd / && sudo /bin/tar xzfP #{restore_directory}/GS5/archives/faxes.tar.gz"
+
+ # Restore voicemails
+ #
+ system "cd / && sudo /bin/tar xzfP #{restore_directory}/GS5/archives/voicemails.tar.gz"
+
+ # Delete the archive tar.gz to get more air to breathe
+ #
+ FileUtils.mkdir_p "#{restore_directory}/GS5/archives"
+
+ # Restore the database
+ #
+ system_odbc_ini_file = '/var/lib/freeswitch/.odbc.ini'
+ system_odbc_configuration = IniFile.load(system_odbc_ini_file)
+ database = system_odbc_configuration['gemeinschaft']['DATABASE']
+ db_user = system_odbc_configuration['gemeinschaft']['USER']
+ db_password = system_odbc_configuration['gemeinschaft']['PASSWORD']
+
+ system "gunzip < #{restore_directory}/GS5/databases/MySQL/gemeinschaft.sql.gz | mysql -u #{db_user} -p#{db_password} #{database}"
+
+ FileUtils.rm_rf tmp_dir
+
+ system "cd /opt/gemeinschaft && rake db:migrate"
+
+ # Rebuild the thumbnails
+ #
+ FaxDocument.all.each do |fax_document|
+ fax_document.render_thumbnails
+ end
+
+ # Delete the restore_job. No need to waste that space.
+ #
+ restore_job.destroy
+ end
+ end
+
end \ No newline at end of file
diff --git a/lib/tasks/send_fax_notifications.rake b/lib/tasks/send_fax_notifications.rake
index 2ac74c8..b456466 100644
--- a/lib/tasks/send_fax_notifications.rake
+++ b/lib/tasks/send_fax_notifications.rake
@@ -6,7 +6,7 @@ task :send_fax_notifications => :environment do
FaxDocument.where(:state => 'received').each do |fax_document|
TIFF_FUFFIX = ".tiff"
PDF_SUFFIX = ".pdf"
- TMP_DIR = "/tmp/"
+ TMP_DIR = "/var/spool/freeswitch/"
tiff_file = File.basename(fax_document.tiff.to_s)
diff --git a/misc/freeswitch/conf/freeswitch.xml b/misc/freeswitch/conf/freeswitch.xml
index 4969b07..f72651f 100644
--- a/misc/freeswitch/conf/freeswitch.xml
+++ b/misc/freeswitch/conf/freeswitch.xml
@@ -27,6 +27,14 @@
</match>
</input>
</macro>
+ <macro name="voicemail_change_pass_success">
+ <input pattern="(.*)">
+ <match>
+ <action function="play-file" data="voicemail/vm-password_has_been_changed.wav"/>
+ <action function="say" data="$1" method="pronounced" type="name_spelled"/>
+ </match>
+ </input>
+ </macro>
<macro name="voicemail_fail_auth">
<input pattern="(.*)">
<match>
@@ -536,6 +544,14 @@
</match>
</input>
</macro>
+ <macro name="voicemail_change_pass_success">
+ <input pattern="(.*)">
+ <match>
+ <action function="play-file" data="voicemail/vm-password_has_been_changed.wav"/>
+ <action function="say" data="$1" method="pronounced" type="name_spelled"/>
+ </match>
+ </input>
+ </macro>
<macro name="voicemail_fail_auth">
<input pattern="(.*)">
<match>
diff --git a/misc/freeswitch/scripts/common/call_forwarding.lua b/misc/freeswitch/scripts/common/call_forwarding.lua
index 400fcde..192c694 100644
--- a/misc/freeswitch/scripts/common/call_forwarding.lua
+++ b/misc/freeswitch/scripts/common/call_forwarding.lua
@@ -37,6 +37,61 @@ function CallForwarding.find_by_id(self, id)
return nil
end
+
+function CallForwarding.list_by_owner(self, call_forwardable_id, call_forwardable_type, caller_ids)
+ require 'common.str';
+
+ if not tonumber(call_forwardable_id) or common.str.blank(call_forwardable_type) then
+ return {};
+ end
+
+ local sql_query = 'SELECT \
+ `a`.`destination` AS `number`, \
+ `a`.`destinationable_id` AS `id`, \
+ `a`.`destinationable_type` AS `type`, \
+ `a`.`call_forwardable_id`, \
+ `a`.`call_forwardable_type`, \
+ `a`.`timeout`, `a`.`depth`, \
+ `a`.`source`, \
+ `b`.`value` AS `service` \
+ FROM `call_forwards` `a` JOIN `call_forward_cases` `b` ON `a`.`call_forward_case_id` = `b`.`id` \
+ WHERE `a`.`call_forwardable_id`= ' .. tonumber(call_forwardable_id) .. ' \
+ AND `a`.`call_forwardable_type`= ' .. self.database:escape(call_forwardable_type, '"') .. ' \
+ AND `a`.`active` IS TRUE';
+
+ local call_forwarding_entries = {};
+
+ self.database:query(sql_query, function(forwarding_entry)
+ local entry_match = false;
+
+ if common.str.blank(forwarding_entry.source) then
+ entry_match = true;
+ else
+ local sources = common.str.strip_to_a(forwarding_entry.source, ',')
+ for source_index=1, #sources do
+ for caller_id_index=1, #caller_ids do
+ if caller_ids[caller_id_index]:match(sources[source_index]) then
+ entry_match = true;
+ self.log:debug('CALL_FORWARDING - source match: ', sources[source_index], ' ~ ', caller_ids[caller_id_index] );
+ break;
+ end
+ end
+ end
+ end
+
+ if entry_match then
+ call_forwarding_entries[forwarding_entry.service] = forwarding_entry;
+ self.log:debug('CALL_FORWARDING - ', call_forwardable_type, '=', call_forwardable_id,
+ ', service: ', forwarding_entry.service,
+ ', destination: ',forwarding_entry.type, '=', forwarding_entry.id,
+ ', number: ', forwarding_entry.number);
+ end
+ end)
+
+ return call_forwarding_entries;
+end
+
+
function CallForwarding.presence_set(self, presence_state)
require 'dialplan.presence'
local presence = dialplan.presence.Presence:new();
diff --git a/misc/freeswitch/scripts/common/conference.lua b/misc/freeswitch/scripts/common/conference.lua
index f6a4d87..b56cba9 100644
--- a/misc/freeswitch/scripts/common/conference.lua
+++ b/misc/freeswitch/scripts/common/conference.lua
@@ -159,7 +159,7 @@ function Conference.enter(self, caller, domain)
caller:sleep(1000);
caller.session:sayPhrase('conference_welcome');
- if pin and pin ~= "" then
+ if not common.str.blank(pin) then
local digits = "";
for i = 1, 3, 1 do
if digits == pin then
@@ -167,7 +167,7 @@ function Conference.enter(self, caller, domain)
elseif digits ~= "" then
caller.session:sayPhrase('conference_bad_pin');
end
- digits = caller.session:read(PIN_LENGTH_MIN, PIN_LENGTH_MAX, 'conference/conf-enter_conf_pin.wav', PIN_TIMEOUT, '#');
+ digits = caller.session:read(PIN_LENGTH_MIN, PIN_LENGTH_MAX, 'conference/conf-pin.wav', PIN_TIMEOUT, '#');
end
if digits ~= pin then
caller.session:sayPhrase('conference_goodbye');
@@ -191,7 +191,7 @@ function Conference.enter(self, caller, domain)
-- Record caller's name
if common.str.to_b(self.record.announce_new_member_by_name) or common.str.to_b(self.record.announce_left_member_by_name) then
local uid = session:get_uuid();
- name_file = "/tmp/conference_caller_name_" .. uid .. ".wav";
+ name_file = "/var/spool/freeswitch/conference_caller_name_" .. uid .. ".wav";
caller.session:sayPhrase('conference_record_name');
session:recordFile(name_file, ANNOUNCEMENT_MAX_LEN, ANNOUNCEMENT_SILENCE_THRESHOLD, ANNOUNCEMENT_SILENCE_LEN);
caller.session:streamFile(name_file);
diff --git a/misc/freeswitch/scripts/common/group.lua b/misc/freeswitch/scripts/common/group.lua
new file mode 100644
index 0000000..c4125bc
--- /dev/null
+++ b/misc/freeswitch/scripts/common/group.lua
@@ -0,0 +1,88 @@
+-- Gemeinschaft 5 module: group class
+-- (c) AMOOMA GmbH 2013
+--
+
+module(...,package.seeall)
+
+Group = {}
+
+MAX_GROUP_MEMBERSHIPS = 256;
+
+-- create group object
+function Group.new(self, arg)
+ arg = arg or {}
+ object = arg.object or {}
+ setmetatable(object, self);
+ self.__index = self;
+ self.class = 'group';
+ self.log = arg.log;
+ self.database = arg.database;
+ return object;
+end
+
+-- find group by id
+function Group.find_by_id(self, id)
+ local sql_query = 'SELECT * FROM `groups` WHERE `id`= ' .. tonumber(id) .. ' LIMIT 1';
+ local group = nil;
+
+ self.database:query(sql_query, function(account_entry)
+ group = Group:new(self);
+ group.record = account_entry;
+ group.id = tonumber(account_entry.id);
+ group.name = account_entry.name;
+ end);
+
+ return group;
+end
+
+-- list groups by member permissions
+function Group.name_id_by_permission(self, member_id, member_type, permission)
+ if not tonumber(member_id) then
+ return {};
+ end
+
+ local sql_query = 'SELECT DISTINCT `c`.`id`, `c`.`name` \
+ FROM `group_permissions` `a` \
+ JOIN `group_memberships` `b` ON `a`.`target_group_id` = `b`.`group_id` \
+ JOIN `groups` `c` ON `c`.`id` = `b`.`group_id` \
+ WHERE `b`.`item_type` = ' .. self.database:escape(member_type, '"') .. ' \
+ AND `b`.`item_id` = ' .. member_id .. ' \
+ AND `a`.`permission` = ' .. self.database:escape(permission, '"') .. ' \
+ AND `c`.`active` IS TRUE \
+ GROUP BY `b`.`group_id` LIMIT ' .. MAX_GROUP_MEMBERSHIPS;
+
+ local group_names = {};
+ local group_ids = {};
+
+ self.database:query(sql_query, function(account_entry)
+ table.insert(group_names, account_entry.name);
+ table.insert(group_ids, tonumber(account_entry.id));
+ end);
+
+ return group_names, group_ids;
+end
+
+-- list groups by member
+function Group.name_id_by_member(self, member_id, member_type)
+ if not tonumber(member_id) then
+ return {};
+ end
+
+ local sql_query = 'SELECT DISTINCT `c`.`id`, `c`.`name` \
+ FROM `group_memberships` `b` \
+ JOIN `groups` `c` ON `c`.`id` = `b`.`group_id` \
+ WHERE `b`.`item_type` = ' .. self.database:escape(member_type, '"') .. ' \
+ AND `b`.`item_id` = ' .. member_id .. ' \
+ AND `c`.`active` IS TRUE \
+ GROUP BY `b`.`group_id` LIMIT ' .. MAX_GROUP_MEMBERSHIPS;
+
+ local group_names = {};
+ local group_ids = {};
+
+ self.database:query(sql_query, function(account_entry)
+ table.insert(group_names, account_entry.name);
+ table.insert(group_ids, tonumber(account_entry.id));
+ end);
+
+ return group_names, group_ids;
+end
diff --git a/misc/freeswitch/scripts/common/phone_number.lua b/misc/freeswitch/scripts/common/phone_number.lua
index 6635296..d6ee42a 100644
--- a/misc/freeswitch/scripts/common/phone_number.lua
+++ b/misc/freeswitch/scripts/common/phone_number.lua
@@ -55,6 +55,8 @@ function PhoneNumber.find_by_number(self, number, phone_numberable_types)
self.database:query(sql_query, function(number_entry)
phone_number = PhoneNumber:new(self);
phone_number.record = number_entry;
+ phone_number.id = tonumber(number_entry.id);
+ phone_number.uuid = number_entry.uuid;
end)
return phone_number;
@@ -68,6 +70,8 @@ function PhoneNumber.find_all_by_owner(self, owner_id, owner_type)
self.database:query(sql_query, function(number_entry)
phone_numbers[tonumber(number_entry.id)] = PhoneNumber:new(self);
phone_numbers[tonumber(number_entry.id)].record = number_entry;
+ phone_numbers[tonumber(number_entry.id)].id = tonumber(number_entry.id);
+ phone_numbers[tonumber(number_entry.id)].uuid = number_entry.uuid;
end)
return phone_numbers;
@@ -94,57 +98,6 @@ function PhoneNumber.list_by_same_owner(self, number, owner_types)
end
end
--- Retrieve call forwarding
-function PhoneNumber.call_forwarding(self, caller_ids)
- require 'common.str'
-
- sources = sources or {};
- table.insert(sources, '');
-
- local sql_query = 'SELECT \
- `a`.`destination` AS `number`, \
- `a`.`call_forwardable_id` AS `id`, \
- `a`.`call_forwardable_type` AS `type`, \
- `a`.`timeout`, `a`.`depth`, \
- `a`.`source`, \
- `b`.`value` AS `service` \
- FROM `call_forwards` `a` JOIN `call_forward_cases` `b` ON `a`.`call_forward_case_id` = `b`.`id` \
- WHERE `a`.`phone_number_id`= ' .. tonumber(self.record.id) .. ' \
- AND `a`.`active` IS TRUE';
-
- local call_forwarding = {}
-
- self.database:query(sql_query, function(forwarding_entry)
- local entry_match = false;
-
- if common.str.blank(forwarding_entry.source) then
- entry_match = true;
- else
- local sources = common.str.strip_to_a(forwarding_entry.source, ',')
- for index, source in ipairs(sources) do
- for index, caller_id in ipairs(caller_ids) do
- if caller_id:match(source) then
- entry_match = true;
- self.log:debug('CALL_FORWARDING_GET - source match: ', source, ' ~ ', caller_id );
- break;
- end
- end
- end
- end
-
- if entry_match then
- call_forwarding[forwarding_entry.service] = forwarding_entry;
- self.log:debug('CALL_FORWARDING_GET - PhoneNumber=', self.record.id, '/', self.record.uuid, '@', self.record.gs_node_id,
- ', number: ', self.record.number,
- ', service: ', forwarding_entry.service,
- ', destination: ',forwarding_entry.type, '=', forwarding_entry.id,
- ', number: ', forwarding_entry.number);
- end
- end)
-
- return call_forwarding;
-end
-
function PhoneNumber.call_forwarding_effective(self, service, source)
local conditions = {}
diff --git a/misc/freeswitch/scripts/common/str.lua b/misc/freeswitch/scripts/common/str.lua
index 72ff388..541199f 100644
--- a/misc/freeswitch/scripts/common/str.lua
+++ b/misc/freeswitch/scripts/common/str.lua
@@ -146,3 +146,37 @@ end
function blank(value)
return (value == nil or to_s(value) == '');
end
+
+-- concatenate string to buffer
+function append(buffer, value, separator, prefix, suffix)
+ separator = separator or '';
+ prefix = prefix or '';
+ suffix = suffix or '';
+ if buffer ~= '' then
+ buffer = buffer .. separator .. prefix .. value .. suffix;
+ else
+ buffer = prefix .. value .. suffix;
+ end
+
+ return buffer;
+end
+
+-- concatenate array values to string
+function concat(array, separator, prefix, suffix)
+ local buffer = '';
+ for key, value in pairs(array) do
+ buffer = append(buffer, value, separator, prefix, suffix);
+ end
+
+ return buffer;
+end
+
+-- concatenate array keys to string
+function concat_keys(array, separator, prefix, suffix)
+ local buffer = '';
+ for key, value in pairs(array) do
+ buffer = append(buffer, key, separator, prefix, suffix);
+ end
+
+ return buffer;
+end
diff --git a/misc/freeswitch/scripts/configuration.lua b/misc/freeswitch/scripts/configuration.lua
index 75d0df3..6660c3d 100644
--- a/misc/freeswitch/scripts/configuration.lua
+++ b/misc/freeswitch/scripts/configuration.lua
@@ -79,6 +79,9 @@ function profile(database, sofia_ini, profile_name, index, domains, node_id)
parameters['odbc-dsn'] = 'gemeinschaft:' .. tostring(database.user_name) .. ':' .. tostring(database.password);
end
+ parameters['username'] = parameters['username'] or 'Gemeinschaft';
+ parameters['user-agent-string'] = parameters['user-agent-string'] or 'Gemeinschaft';
+
-- set local bind address
if domains[index] then
parameters['sip-ip'] = domains[index]['host'];
diff --git a/misc/freeswitch/scripts/dialplan/call_parking.lua b/misc/freeswitch/scripts/dialplan/call_parking.lua
index cc2cf4b..e51eb16 100644
--- a/misc/freeswitch/scripts/dialplan/call_parking.lua
+++ b/misc/freeswitch/scripts/dialplan/call_parking.lua
@@ -39,6 +39,22 @@ function CallParking.find_by_name(self, name)
end
+function CallParking.find_by_owner(self, owner_id, owner_type)
+ local sql_query = 'SELECT * FROM `parking_stalls` WHERE `parking_stallable_id` = '.. owner_id .. ' AND `parking_stallable_type` = "' .. owner_type .. '" ORDER BY `name`';
+ local parking_stalls = {};
+
+ self.database:query(sql_query, function(entry)
+ local parking_stall = CallParking:new(self);
+ parking_stall.record = entry;
+ parking_stall.id = tonumber(entry.id);
+ parking_stall.name = entry.name;
+ table.insert(parking_stalls, parking_stall)
+ end)
+
+ return parking_stalls;
+end
+
+
function CallParking.list_occupied(self, lot)
lot = lot or self.lot;
diff --git a/misc/freeswitch/scripts/dialplan/dialplan.lua b/misc/freeswitch/scripts/dialplan/dialplan.lua
index b27bb9d..7d9ac58 100644
--- a/misc/freeswitch/scripts/dialplan/dialplan.lua
+++ b/misc/freeswitch/scripts/dialplan/dialplan.lua
@@ -148,6 +148,9 @@ function Dialplan.object_find(self, class, identifier, auth_name)
require 'common.str'
class = common.str.downcase(class);
+ require 'common.group';
+ local group_class = common.group.Group:new{ log = self.log, database = self.database };
+
if class == 'user' then
require 'dialplan.user'
local user = nil;
@@ -158,7 +161,8 @@ function Dialplan.object_find(self, class, identifier, auth_name)
end
if user then
- user.groups = user:list_groups();
+ user.user_groups = user:list_groups();
+ user.groups = group_class:name_id_by_member(user.id, user.class);
end
return user;
@@ -171,6 +175,10 @@ function Dialplan.object_find(self, class, identifier, auth_name)
tenant = dialplan.tenant.Tenant:new{ log = self.log, database = self.database }:find_by_uuid(identifier);
end
+ if tenant then
+ tenant.groups = group_class:name_id_by_member(tenant.id, tenant.class);
+ end
+
return tenant;
elseif class == 'sipaccount' then
require 'common.sip_account'
@@ -184,6 +192,7 @@ function Dialplan.object_find(self, class, identifier, auth_name)
end
if sip_account then
sip_account.owner = self:object_find(sip_account.record.sip_accountable_type, tonumber(sip_account.record.sip_accountable_id));
+ sip_account.groups = group_class:name_id_by_member(sip_account.id, sip_account.class);
end
return sip_account;
elseif class == 'huntgroup' then
@@ -198,6 +207,7 @@ function Dialplan.object_find(self, class, identifier, auth_name)
if hunt_group then
hunt_group.owner = self:object_find('tenant', tonumber(hunt_group.record.tenant_id));
+ hunt_group.groups = group_class:name_id_by_member(hunt_group.id, hunt_group.class);
end
return hunt_group;
@@ -213,6 +223,7 @@ function Dialplan.object_find(self, class, identifier, auth_name)
if acd then
acd.owner = self:object_find(acd.record.automatic_call_distributorable_type, tonumber(acd.record.automatic_call_distributorable_id));
+ acd.groups = group_class:name_id_by_member(acd.id, acd.class);
end
return acd;
@@ -226,6 +237,7 @@ function Dialplan.object_find(self, class, identifier, auth_name)
end
if fax_account then
fax_account.owner = self:object_find(fax_account.record.fax_accountable_type, tonumber(fax_account.record.fax_accountable_id));
+ fax_account.groups = group_class:name_id_by_member(fax_account.id, fax_account.class);
end
return fax_account;
@@ -235,7 +247,6 @@ end
function Dialplan.retrieve_caller_data(self)
require 'common.str'
-
self.caller.caller_phone_numbers_hash = {}
-- TODO: Set auth_account on transfer initiated by calling party
@@ -252,9 +263,9 @@ function Dialplan.retrieve_caller_data(self)
end
if self.caller.auth_account then
- self.log:info('CALLER_DATA - auth account: ', self.caller.auth_account.class, '=', self.caller.auth_account.id, '/', self.caller.auth_account.uuid);
+ self.log:info('CALLER_DATA - auth account: ', self.caller.auth_account.class, '=', self.caller.auth_account.id, '/', self.caller.auth_account.uuid, ', groups: ', table.concat(self.caller.auth_account.groups, ','));
if self.caller.auth_account.owner then
- self.log:info('CALLER_DATA - auth owner: ', self.caller.auth_account.owner.class, '=', self.caller.auth_account.owner.id, '/', self.caller.auth_account.owner.uuid);
+ self.log:info('CALLER_DATA - auth owner: ', self.caller.auth_account.owner.class, '=', self.caller.auth_account.owner.id, '/', self.caller.auth_account.owner.uuid, ', groups: ', table.concat(self.caller.auth_account.owner.groups, ','));
else
self.log:error('CALLER_DATA - auth owner not found');
end
@@ -273,9 +284,9 @@ function Dialplan.retrieve_caller_data(self)
if not common.str.blank(self.caller.account.record.language_code) then
self.caller.language = self.caller.account.record.language_code;
end
- self.log:info('CALLER_DATA - caller account: ', self.caller.account.class, '=', self.caller.account.id, '/', self.caller.account.uuid, ', phone_numbers: ', #self.caller.caller_phone_numbers, ', language: ', self.caller.language);
+ self.log:info('CALLER_DATA - caller account: ', self.caller.account.class, '=', self.caller.account.id, '/', self.caller.account.uuid, ', phone_numbers: ', #self.caller.caller_phone_numbers, ', language: ', self.caller.language, ', groups: ', table.concat(self.caller.account.groups, ','));
if self.caller.account.owner then
- self.log:info('CALLER_DATA - caller owner: ', self.caller.account.owner.class, '=', self.caller.account.owner.id, '/', self.caller.account.owner.uuid);
+ self.log:info('CALLER_DATA - caller owner: ', self.caller.account.owner.class, '=', self.caller.account.owner.id, '/', self.caller.account.owner.uuid, ', groups: ', table.concat(self.caller.account.owner.groups, ','));
else
self.log:error('CALLER_DATA - caller owner not found');
end
@@ -319,7 +330,13 @@ function Dialplan.destination_new(self, arg)
destination.uuid = common.str.to_s(destination.phone_number.record.phone_numberable_uuid);
destination.node_id = common.str.to_i(destination.phone_number.record.gs_node_id);
if self.caller then
- destination.call_forwarding = destination.phone_number:call_forwarding(self.caller.caller_phone_numbers);
+ require 'common.call_forwarding';
+ local call_forwarding_class = common.call_forwarding.CallForwarding:new{ log = self.log, database = self.database }
+ destination.call_forwarding = call_forwarding_class:list_by_owner(destination.id, destination.type, self.caller.caller_phone_numbers);
+ for service, call_forwarding_entry in pairs(call_forwarding_class:list_by_owner(destination.phone_number.id, destination.phone_number.class, self.caller.caller_phone_numbers)) do
+ destination.call_forwarding[service] = call_forwarding_entry;
+ end
+ -- destination.call_forwarding = destination.phone_number:call_forwarding(self.caller.caller_phone_numbers);
end
elseif destination.type == 'unknown' then
require 'common.sip_account'
@@ -362,64 +379,74 @@ end
function Dialplan.dial(self, destination)
+ local user_id = nil;
+ local tenant_id = nil;
+
require 'common.str'
destination.caller_id_number = destination.caller_id_number or self.caller.caller_phone_numbers[1];
- if not self.caller.clir then
- if destination.node_local and destination.type == 'sipaccount' then
- local user_id = nil;
- local tenant_id = nil;
-
- destination.account = self:object_find(destination.type, destination.id);
- if destination.account then
- if destination.account.class == 'sipaccount' then
- destination.callee_id_name = destination.account.record.caller_name;
- self.caller:set_callee_id(destination.number, destination.account.record.caller_name);
- end
+ if destination.node_local and destination.type == 'sipaccount' then
+ destination.pickup_groups = {};
+
+ destination.account = self:object_find(destination.type, destination.id);
+ if destination.account then
+ if destination.account.class == 'sipaccount' then
+ destination.callee_id_name = destination.account.record.caller_name;
+ self.caller:set_callee_id(destination.number, destination.account.record.caller_name);
+ table.insert(destination.pickup_groups, 's' .. destination.account.id );
end
+ require 'common.group';
+ local group_names, group_ids = common.group.Group:new{ log = self.log, database = self.database }:name_id_by_permission(destination.id, destination.type, 'pickup');
+ self.log:debug('DESTINATION_GROUPS - pickup_groups: ', table.concat(group_names, ','));
+ for index=1, #group_ids do
+ table.insert(destination.pickup_groups, 'g' .. group_ids[index]);
+ end
+ end
- if destination.account and destination.account.owner then
- if destination.account.owner.class == 'user' then
- user_id = destination.account.owner.id;
- tenant_id = tonumber(destination.account.owner.record.current_tenant_id);
- elseif destination.account.owner.class == 'tenant' then
- tenant_id = destination.account.owner.id;
- end
+ if destination.account and destination.account.owner then
+ if destination.account.owner.class == 'user' then
+ user_id = destination.account.owner.id;
+ tenant_id = tonumber(destination.account.owner.record.current_tenant_id);
+ local user = self:object_find(destination.account.owner.class, tonumber(user_id));
+ elseif destination.account.owner.class == 'tenant' then
+ tenant_id = destination.account.owner.id;
end
+ end
+ end
- if user_id or tenant_id then
- require 'common.str'
- local phone_book_entry = nil;
+ if not self.caller.clir then
+ if user_id or tenant_id then
+ require 'common.str'
+ local phone_book_entry = nil;
- if self.phonebook_number_lookup then
- require 'dialplan.phone_book'
- phone_book_entry = dialplan.phone_book.PhoneBook:new{ log = self.log, database = self.database }:find_entry_by_number_user_tenant(self.caller.caller_phone_numbers, user_id, tenant_id);
- end
+ if self.phonebook_number_lookup then
+ require 'dialplan.phone_book'
+ phone_book_entry = dialplan.phone_book.PhoneBook:new{ log = self.log, database = self.database }:find_entry_by_number_user_tenant(self.caller.caller_phone_numbers, user_id, tenant_id);
+ end
- if phone_book_entry then
- self.log:info('PHONE_BOOK_ENTRY - phone_book=', phone_book_entry.phone_book_id, ' (', phone_book_entry.phone_book_name, '), caller_id_name: ', phone_book_entry.caller_id_name, ', ringtone: ', phone_book_entry.bellcore_id);
- destination.caller_id_name = common.str.to_ascii(phone_book_entry.caller_id_name);
- if tonumber(phone_book_entry.bellcore_id) then
- self.log:debug('RINGTONE - phonebookentry, index: ', phone_book_entry.bellcore_id);
- self.caller:export_variable('alert_info', 'http://amooma.de;info=Ringer' .. phone_book_entry.bellcore_id .. ';x-line-id=0');
- end
- if phone_book_entry.image then
- self:set_caller_picture(phone_book_entry.id, 'phonebookentry', phone_book_entry.image);
- elseif self.caller.account and self.caller.account.owner then
- self:set_caller_picture(self.caller.account.owner.id, self.caller.account.owner.class);
- end
+ if phone_book_entry then
+ self.log:info('PHONE_BOOK_ENTRY - phone_book=', phone_book_entry.phone_book_id, ' (', phone_book_entry.phone_book_name, '), caller_id_name: ', phone_book_entry.caller_id_name, ', ringtone: ', phone_book_entry.bellcore_id);
+ destination.caller_id_name = common.str.to_ascii(phone_book_entry.caller_id_name);
+ if tonumber(phone_book_entry.bellcore_id) then
+ self.log:debug('RINGTONE - phonebookentry, index: ', phone_book_entry.bellcore_id);
+ self.caller:export_variable('alert_info', 'http://amooma.de;info=Ringer' .. phone_book_entry.bellcore_id .. ';x-line-id=0');
+ end
+ if phone_book_entry.image then
+ self:set_caller_picture(phone_book_entry.id, 'phonebookentry', phone_book_entry.image);
elseif self.caller.account and self.caller.account.owner then
self:set_caller_picture(self.caller.account.owner.id, self.caller.account.owner.class);
- elseif self.geo_number_lookup then
- require 'dialplan.geo_number'
- local geo_number = dialplan.geo_number.GeoNumber:new{ log = self.log, database = self.database }:find(destination.caller_id_number);
- if geo_number then
- self.log:info('GEO_NUMBER - found: ', geo_number.name, ', ', geo_number.country);
- if geo_number.name then
- destination.caller_id_name = common.str.to_ascii(geo_number.name) .. ', ' .. common.str.to_ascii(geo_number.country);
- else
- destination.caller_id_name = common.str.to_ascii(geo_number.country);
- end
+ end
+ elseif self.caller.account and self.caller.account.owner then
+ self:set_caller_picture(self.caller.account.owner.id, self.caller.account.owner.class);
+ elseif self.geo_number_lookup then
+ require 'dialplan.geo_number'
+ local geo_number = dialplan.geo_number.GeoNumber:new{ log = self.log, database = self.database }:find(destination.caller_id_number);
+ if geo_number then
+ self.log:info('GEO_NUMBER - found: ', geo_number.name, ', ', geo_number.country);
+ if geo_number.name then
+ destination.caller_id_name = common.str.to_ascii(geo_number.name) .. ', ' .. common.str.to_ascii(geo_number.country);
+ else
+ destination.caller_id_name = common.str.to_ascii(geo_number.country);
end
end
end
@@ -997,6 +1024,7 @@ function Dialplan.run(self, destination)
destination = self:destination_new(result.call_forwarding);
self.caller.destination = destination;
+ self.caller.destination_number = destination.number;
if not result.no_cdr and auth_account then
require 'common.call_history'
diff --git a/misc/freeswitch/scripts/dialplan/dtmf.lua b/misc/freeswitch/scripts/dialplan/dtmf.lua
index 4dbd35f..64f538e 100644
--- a/misc/freeswitch/scripts/dialplan/dtmf.lua
+++ b/misc/freeswitch/scripts/dialplan/dtmf.lua
@@ -17,12 +17,17 @@ function Dtmf.new(self, arg)
self.bleg = arg.bleg
self.digit_timeout = arg.digit_timeout or 5;
self.router = arg.router;
+ self.digit_duration_min = arg.digit_duration_min or 500;
return object;
end
function Dtmf.detect(self, caller, sequence, digit, duration, calee)
+ if not tonumber(duration) or duration < self.digit_duration_min then
+ return;
+ end
+
local timestamp = os.time();
if timestamp - sequence.updated > self.digit_timeout then
sequence.digits = digit;
@@ -63,6 +68,9 @@ function Dtmf.transfer(self, caller, destination, calee)
caller:execute('transfer', destination);
fapi:execute('uuid_kill', callee_uuid);
else
+ if caller.account then
+ fapi:execute('uuid_setvar_multi', callee_uuid .. ' gs_auth_account_type=' .. caller.account.class .. ';gs_auth_account_uuid=' .. caller.account.uuid);
+ end
fapi:execute('uuid_transfer', callee_uuid .. ' ' .. destination);
caller.session:hangup();
end
diff --git a/misc/freeswitch/scripts/dialplan/fax.lua b/misc/freeswitch/scripts/dialplan/fax.lua
index 49a45d9..6dce0a9 100644
--- a/misc/freeswitch/scripts/dialplan/fax.lua
+++ b/misc/freeswitch/scripts/dialplan/fax.lua
@@ -4,7 +4,7 @@
module(...,package.seeall)
-FAX_DOCUMENTS_DIRECTORY = '/tmp/'
+FAX_SPOOL_DIRECTORY = '/var/spool/freeswitch/'
FAX_PARALLEL_MAX = 8;
Fax = {}
@@ -18,7 +18,7 @@ function Fax.new(self, arg)
self.log = arg.log;
self.database = arg.database;
self.record = arg.record;
- self.fax_directory = arg.fax_directory or FAX_DOCUMENTS_DIRECTORY;
+ self.fax_spool_directory = arg.fax_spool_directory or FAX_SPOOL_DIRECTORY;
return object;
end
@@ -79,7 +79,7 @@ end
-- List waiting fax documents
function Fax.queued_for_sending(self, limit)
limit = limit or FAX_PARALLEL_MAX;
- local sql_query = 'SELECT * FROM `fax_documents` WHERE `state` IN ("queued_for_sending","unsuccessful") AND `retry_counter` > 0 ORDER BY `sent_at` ASC LIMIT ' .. limit;
+ local sql_query = 'SELECT * FROM `fax_documents` WHERE `state` IN ("queued_for_sending","unsuccessful") AND `retry_counter` > 0 AND `tiff` IS NOT NULL AND `tiff` != "" ORDER BY `sent_at` ASC LIMIT ' .. limit;
local fax_documents = {}
self.database:query(sql_query, function(fax_entry)
fax_entry['destination_numbers'] = Fax:destination_numbers(fax_entry.id)
@@ -136,7 +136,7 @@ end
-- Receive Fax
function Fax.receive(self, caller, file_name)
- file_name = file_name or self.fax_directory .. 'fax_in_' .. caller.uuid .. '.tiff';
+ file_name = file_name or self.fax_spool_directory .. 'fax_in_' .. caller.uuid .. '.tiff';
caller:set_variable('fax_ident', self.record.station_id)
caller:set_variable('fax_verbose', 'false')
diff --git a/misc/freeswitch/scripts/dialplan/functions.lua b/misc/freeswitch/scripts/dialplan/functions.lua
index acfa336..3706872 100644
--- a/misc/freeswitch/scripts/dialplan/functions.lua
+++ b/misc/freeswitch/scripts/dialplan/functions.lua
@@ -35,10 +35,8 @@ function Functions.dialplan_function(self, caller, dialed_number)
if fid == "ta" then
result = self:transfer_all(caller, parameters[3]);
- elseif fid == "in" then
- result = self:intercept_extensions(caller, parameters[3]);
elseif fid == "ia" then
- result = self:intercept_any_extension(caller, parameters[3]);
+ result = self:intercept_any_number(caller, parameters[3]);
elseif fid == "anc" then
result = self:account_node_change(caller);
elseif fid == "li" then
@@ -113,9 +111,11 @@ function Functions.dialplan_function(self, caller, dialed_number)
result = self:hangup(caller, parameters[3], parameters[4]);
elseif fid == "cpa" then
result = self:call_parking_inout(caller, parameters[3], parameters[4]);
+ elseif fid == "cpai" then
+ result = self:call_parking_inout_index(caller, parameters[3]);
end
- return result;
+ return result or { continue = false, code = 505, phrase = 'Error executing function', no_cdr = true };
end
-- Transfer all calls to a conference
@@ -149,94 +149,27 @@ function Functions.transfer_all(self, caller, destination_number)
return destination_number;
end
--- Intercept Extensions
-function Functions.intercept_extensions(self, caller, destination_numbers)
- if type(destination_numbers) == "string" then
- destination_numbers = "\"" .. destination_numbers .. "\"";
- else
- destination_numbers = "\"" .. table.concat(destination_numbers, "\",\"") .. "\"";
- end
-
- self.log:debug("Intercept call to number(s): " .. destination_numbers);
-
- if caller.account_type ~= "SipAccount" then
- self.log:error("caller is not a SipAccount");
- return { continue = false, code = 403, phrase = 'Incompatible caller' }
- end
- local sql_query = 'SELECT * FROM `channels` WHERE `callstate` IN ("EARLY", "ACTIVE") AND `dest` IN (' .. destination_numbers .. ') LIMIT 1';
-
- self.database:query(sql_query, function(call_entry)
- self.log:debug("intercepting call with uid: " .. call_entry.uuid);
- caller:intercept(call_entry.uuid);
- end)
-
- return nil;
-end
+function Functions.intercept_any_number(self, caller, destination_number)
+ require 'common.phone_number'
+ local phone_number = common.phone_number.PhoneNumber:new{ log = self.log, database = self.database }:find_by_number(destination_number);
--- intercept call to destination (e.g. sip_account)
-function Functions.intercept_destination(self, caller, destination)
- self.log:debug("Intercept call to destination " .. destination);
- local result = false;
- local sql_query = 'SELECT `call_uuid`, `uuid` FROM `channels` WHERE `callstate` = "RINGING" AND `dest` = "' .. destination .. '" LIMIT 1';
+ if not phone_number or not phone_number.record then
+ self.log:notice('FUNCTION_INTERCEPT_ANY_NUMBER - number not found: ', destination_number);
+ return { continue = false, code = 404, phrase = 'Number not found', no_cdr = true };
+ end
- caller:set_caller_id(caller.caller_phone_numbers[1] ,caller.caller_id_name);
- self.database:query(sql_query, function(call_entry)
- if call_entry.call_uuid and tostring(call_entry.call_uuid) then
- self.log:debug("intercepting call - uuid: " .. call_entry.call_uuid);
- caller:intercept(call_entry.call_uuid);
- result = { continue = false, code = 200, call_service = 'pickup' }
- require 'common.str'
- require 'common.fapi'
- local fapi = common.fapi.FApi:new{ log = self.log, uuid = call_entry.call_uuid }
- if fapi:channel_exists() then
- caller:set_caller_id(
- common.str.to_s(fapi:get_variable('effective_caller_id_number')),
- common.str.to_s(fapi:get_variable('effective_caller_id_name'))
- );
- caller:set_callee_id(
- common.str.to_s(fapi:get_variable('effective_callee_id_number')),
- common.str.to_s(fapi:get_variable('effective_callee_id_name'))
- );
-
- caller:set_variable('gs_destination_type', fapi:get_variable('gs_destination_type'));
- caller:set_variable('gs_destination_id', fapi:get_variable('gs_destination_id'));
- caller:set_variable('gs_destination_uuid', fapi:get_variable('gs_destination_uuid'));
-
- caller:set_variable('gs_caller_account_type', fapi:get_variable('gs_account_type'));
- caller:set_variable('gs_caller_account_id', fapi:get_variable('gs_account_id'));
- caller:set_variable('gs_caller_account_uuid', fapi:get_variable('gs_account_uuid'));
-
- caller:set_variable('gs_auth_account_type', fapi:get_variable('gs_auth_account_type'));
- caller:set_variable('gs_auth_account_id', fapi:get_variable('gs_auth_account_id'));
- caller:set_variable('gs_auth_account_uuid', fapi:get_variable('gs_auth_account_uuid'));
- end
- else
- self.log:error('FUNCTION - failed to intercept call - no caller uuid for callee uuid: ', call_entry.uuid);
- end
- end)
+ if not phone_number.record.phone_numberable_type:lower() == 'sipaccount' or not tonumber(phone_number.record.phone_numberable_id) then
+ self.log:notice('FUNCTION_INTERCEPT_ANY_NUMBER - destination: ', phone_number.record.phone_numberable_type:lower(), '=', phone_number.record.phone_numberable_id, ', number: ', destination_number);
+ return { continue = false, code = 505, phrase = 'Incompatible destination', no_cdr = true };
+ end
- return result;
-end
+ self.log:info('FUNCTION_INTERCEPT_ANY_NUMBER intercepting call - to: ', phone_number.record.phone_numberable_type:lower(), '=', phone_number.record.phone_numberable_id, ', number: ', destination_number);
--- intercept call to owner of destination_number
-function Functions.intercept_any_extension(self, caller, destination_number)
- require 'common.phone_number'
- local phone_number_object = common.phone_number.PhoneNumber:new{ log = self.log, database = self.database }:find_by_number(destination_number);
+ caller:set_variable('gs_pickup_group_pick', 's' .. phone_number.record.phone_numberable_id);
+ caller:execute('pickup', 's' .. phone_number.record.phone_numberable_id);
- if not phone_number_object or not phone_number_object.record then
- self.log:notice("unallocated number: " .. tostring(destination_number));
- return false;
- end
-
- if phone_number_object.record.phone_numberable_type == 'SipAccount' then
- require "common.sip_account"
- local sip_account_class = common.sip_account.SipAccount:new{ log = self.log, database = self.database }
- local sip_account = sip_account_class:find_by_id(phone_number_object.record.phone_numberable_id)
- if sip_account then
- return self:intercept_destination(caller, sip_account.record.auth_name);
- end
- end
+ return { continue = false, code = 200, phrase = 'OK', no_cdr = true }
end
@@ -932,3 +865,39 @@ function Functions.call_parking_inout(self, caller, stall_name, lot_name)
return { continue = false, code = 200, phrase = 'OK', no_cdr = true }
end
+
+
+function Functions.call_parking_inout_index(self, caller, stall_index)
+ if not tonumber(stall_index) then
+ self.log:notice('FUNCTION_CALL_PARKING_INOUT_INDEX - malformed index: ', stall_index);
+ return { continue = false, code = 404, phrase = 'No parkings stall specified', no_cdr = true }
+ end
+
+ require 'common.str';
+ local owner = common.str.try(caller, 'auth_account.owner');
+
+ if not owner then
+ self.log:notice('FUNCTION_CALL_PARKING_INOUT_INDEX - stall owner not specified');
+ return { continue = false, code = 404, phrase = 'No parkings stalls owner' , no_cdr = true }
+ end
+
+ require 'dialplan.call_parking';
+ local parking_stalls = dialplan.call_parking.CallParking:new{ log = self.log, database = self.database, caller = caller }:find_by_owner(owner.id, owner.class);
+
+ if not parking_stalls or #parking_stalls < 1 then
+ self.log:notice('FUNCTION_CALL_PARKING_INOUT_INDEX - no parkings stalls found');
+ return { continue = false, code = 404, phrase = 'No parkings stalls', no_cdr = true }
+ end
+
+ local parking_stall = parking_stalls[tonumber(stall_index)];
+
+ if not parking_stall then
+ self.log:notice('FUNCTION_CALL_PARKING_INOUT_INDEX - no parkings stall found with index: ', stall_index);
+ return { continue = false, code = 404, phrase = 'Parking stall not found', no_cdr = true }
+ end
+
+ self.log:info('FUNCTION_CALL_PARKING_INOUT_INDEX parking/retrieving call - parkingstall=', parking_stall.id, '/', parking_stall.name, ', index: ', stall_index);
+ parking_stall:park_retrieve();
+
+ return { continue = false, code = 200, phrase = 'OK', no_cdr = true }
+end
diff --git a/misc/freeswitch/scripts/dialplan/sip_call.lua b/misc/freeswitch/scripts/dialplan/sip_call.lua
index b56f1b2..5c98792 100644
--- a/misc/freeswitch/scripts/dialplan/sip_call.lua
+++ b/misc/freeswitch/scripts/dialplan/sip_call.lua
@@ -76,7 +76,8 @@ end
function SipCall.fork(self, destinations, arg )
- local dial_strings = {}
+ local dial_strings = {};
+ local pickup_groups = {};
require 'common.sip_account'
require 'common.str'
@@ -135,6 +136,11 @@ function SipCall.fork(self, destinations, arg )
table.insert(origination_variables, "alert_info='" .. destination.alert_info .. "'");
end
table.insert(dial_strings, '[' .. table.concat(origination_variables , ',') .. ']sofia/' .. sip_account.record.profile_name .. '/' .. sip_account.record.auth_name .. '%' .. sip_account.record.sip_host);
+ if destination.pickup_groups and #destination.pickup_groups > 0 then
+ for key=1, #destination.pickup_groups do
+ pickup_groups[destination.pickup_groups[key]] = true;
+ end
+ end
else
some_destinations_busy = true;
call_result = { code = 486, phrase = 'User busy', disposition = 'USER_BUSY' };
@@ -184,6 +190,10 @@ function SipCall.fork(self, destinations, arg )
self.caller:set_variable('call_timeout', arg.timeout );
self.log:info('FORK DIAL - destinations: ', #dial_strings, ', timeout: ', arg.timeout);
+ for pickup_group, value in pairs(pickup_groups) do
+ table.insert(dial_strings, 'pickup/' .. pickup_group);
+ end
+
if arg.send_ringing then
self.caller:execute('ring_ready');
end
@@ -201,10 +211,20 @@ function SipCall.fork(self, destinations, arg )
fork_index = tonumber(session_callee:getVariable('gs_fork_index')) or 0;
local destination = destinations[fork_index];
- if arg.detect_dtmf_after_bridge_caller then
+ if not destination then
+ destination = {
+ ['type'] = session_callee:getVariable('gs_account_type');
+ id = session_callee:getVariable('gs_account_id');
+ uuid = session_callee:getVariable('gs_account_uuid');
+ pickup_group_pick = session_callee:getVariable('gs_pickup_group_pick');
+ }
+ self.log:notice('FORK - call picked off by: ', destination.type, '=', destination.id, '/', destination.uuid, ', pickup_group: ', destination.pickup_group_pick);
+ end
+
+ if arg.detect_dtmf_after_bridge_caller and self.caller.auth_account then
session:execute('start_dtmf');
end
- if arg.detect_dtmf_after_bridge_callee then
+ if arg.detect_dtmf_after_bridge_callee and destination.type == 'sipaccount' then
session_callee:execute('start_dtmf');
end
if arg.bypass_media_network then
diff --git a/misc/freeswitch/scripts/dialplan/user.lua b/misc/freeswitch/scripts/dialplan/user.lua
index b536600..b6928b4 100644
--- a/misc/freeswitch/scripts/dialplan/user.lua
+++ b/misc/freeswitch/scripts/dialplan/user.lua
@@ -69,6 +69,23 @@ function User.list_groups(self, id)
end
+function User.list_group_ids(self, id)
+ require 'common.str'
+ id = id or self.id;
+ local sql_query = 'SELECT `b`.`id` FROM `user_group_memberships` `a` \
+ JOIN `user_groups` `b` ON `a`.`user_group_id` = `b`.`id` \
+ WHERE `a`.`state` = "active" AND `a`.`user_id`= ' .. tonumber(id) .. ' ORDER BY `b`.`position` LIMIT ' .. MAX_GROUP_MEMBERSHIPS;
+
+ local groups = {};
+
+ self.database:query(sql_query, function(entry)
+ table.insert(groups, common.str.downcase(entry.id));
+ end);
+
+ return groups;
+end
+
+
function User.check_pin(self, pin_to_check)
if not self.record then
return nil
diff --git a/misc/freeswitch/scripts/dialplan/voicemail.lua b/misc/freeswitch/scripts/dialplan/voicemail.lua
index 4c96fbe..ae7d0a1 100644
--- a/misc/freeswitch/scripts/dialplan/voicemail.lua
+++ b/misc/freeswitch/scripts/dialplan/voicemail.lua
@@ -11,7 +11,7 @@ MESSAGE_LENGTH_MAX = 120;
SILENCE_LENGTH_ABORT = 5;
SILENCE_LEVEL = 500;
BEEP = 'tone_stream://%(1000,0,500)';
-RECORD_FILE_PREFIX = '/tmp/voicemail_';
+RECORD_FILE_PREFIX = '/var/spool/freeswitch/voicemail_';
-- create voicemail object
function Voicemail.new(self, arg)
diff --git a/misc/freeswitch/scripts/send_fax.lua b/misc/freeswitch/scripts/send_fax.lua
index 4898cb8..d717f93 100644
--- a/misc/freeswitch/scripts/send_fax.lua
+++ b/misc/freeswitch/scripts/send_fax.lua
@@ -2,7 +2,6 @@
-- (c) AMOOMA GmbH 2012-2013
--
-local FAX_FILE_PATH = "/opt/GS5/public/uploads/fax_document/tiff/";
local FAX_ANSWERING_TIMEOUT = 20;
-- Set logger
@@ -142,13 +141,11 @@ end
if session and session:answered() then
log:info('FAX_SEND - sending fax_document=' .. fax_document.id .. ' (' .. fax_document.tiff .. ')');
- local file_name = FAX_FILE_PATH .. fax_document.id .. "/" .. fax_document.tiff;
-
session:setVariable('fax_ident', fax_account.record.station_id)
session:setVariable('fax_header', fax_account.record.name)
session:setVariable('fax_verbose', 'false')
local start_time = os.time();
- session:execute('txfax', file_name);
+ session:execute('txfax', fax_document.tiff);
fax_state = {
state = nil,
diff --git a/script/logout_phones.sh b/script/logout_phones.sh
new file mode 100755
index 0000000..41e2a40
--- /dev/null
+++ b/script/logout_phones.sh
@@ -0,0 +1,3 @@
+#! /bin/bash
+cd /opt/GS5/script/
+/opt/GS5/script/logout_phones $@
diff --git a/test/functional/group_memberships_controller_test.rb b/test/functional/group_memberships_controller_test.rb
new file mode 100644
index 0000000..596de1f
--- /dev/null
+++ b/test/functional/group_memberships_controller_test.rb
@@ -0,0 +1,49 @@
+require 'test_helper'
+
+class GroupMembershipsControllerTest < ActionController::TestCase
+ setup do
+ @group_membership = group_memberships(:one)
+ end
+
+ test "should get index" do
+ get :index
+ assert_response :success
+ assert_not_nil assigns(:group_memberships)
+ end
+
+ test "should get new" do
+ get :new
+ assert_response :success
+ end
+
+ test "should create group_membership" do
+ assert_difference('GroupMembership.count') do
+ post :create, group_membership: @group_membership.attributes
+ end
+
+ assert_redirected_to group_membership_path(assigns(:group_membership))
+ end
+
+ test "should show group_membership" do
+ get :show, id: @group_membership.to_param
+ assert_response :success
+ end
+
+ test "should get edit" do
+ get :edit, id: @group_membership.to_param
+ assert_response :success
+ end
+
+ test "should update group_membership" do
+ put :update, id: @group_membership.to_param, group_membership: @group_membership.attributes
+ assert_redirected_to group_membership_path(assigns(:group_membership))
+ end
+
+ test "should destroy group_membership" do
+ assert_difference('GroupMembership.count', -1) do
+ delete :destroy, id: @group_membership.to_param
+ end
+
+ assert_redirected_to group_memberships_path
+ end
+end
diff --git a/test/functional/group_permissions_controller_test.rb b/test/functional/group_permissions_controller_test.rb
new file mode 100644
index 0000000..4b70ae3
--- /dev/null
+++ b/test/functional/group_permissions_controller_test.rb
@@ -0,0 +1,49 @@
+require 'test_helper'
+
+class GroupPermissionsControllerTest < ActionController::TestCase
+ setup do
+ @group_permission = group_permissions(:one)
+ end
+
+ test "should get index" do
+ get :index
+ assert_response :success
+ assert_not_nil assigns(:group_permissions)
+ end
+
+ test "should get new" do
+ get :new
+ assert_response :success
+ end
+
+ test "should create group_permission" do
+ assert_difference('GroupPermission.count') do
+ post :create, group_permission: @group_permission.attributes
+ end
+
+ assert_redirected_to group_permission_path(assigns(:group_permission))
+ end
+
+ test "should show group_permission" do
+ get :show, id: @group_permission.to_param
+ assert_response :success
+ end
+
+ test "should get edit" do
+ get :edit, id: @group_permission.to_param
+ assert_response :success
+ end
+
+ test "should update group_permission" do
+ put :update, id: @group_permission.to_param, group_permission: @group_permission.attributes
+ assert_redirected_to group_permission_path(assigns(:group_permission))
+ end
+
+ test "should destroy group_permission" do
+ assert_difference('GroupPermission.count', -1) do
+ delete :destroy, id: @group_permission.to_param
+ end
+
+ assert_redirected_to group_permissions_path
+ end
+end
diff --git a/test/functional/groups_controller_test.rb b/test/functional/groups_controller_test.rb
new file mode 100644
index 0000000..2981018
--- /dev/null
+++ b/test/functional/groups_controller_test.rb
@@ -0,0 +1,49 @@
+require 'test_helper'
+
+class GroupsControllerTest < ActionController::TestCase
+ setup do
+ @group = groups(:one)
+ end
+
+ test "should get index" do
+ get :index
+ assert_response :success
+ assert_not_nil assigns(:groups)
+ end
+
+ test "should get new" do
+ get :new
+ assert_response :success
+ end
+
+ test "should create group" do
+ assert_difference('Group.count') do
+ post :create, group: @group.attributes
+ end
+
+ assert_redirected_to group_path(assigns(:group))
+ end
+
+ test "should show group" do
+ get :show, id: @group.to_param
+ assert_response :success
+ end
+
+ test "should get edit" do
+ get :edit, id: @group.to_param
+ assert_response :success
+ end
+
+ test "should update group" do
+ put :update, id: @group.to_param, group: @group.attributes
+ assert_redirected_to group_path(assigns(:group))
+ end
+
+ test "should destroy group" do
+ assert_difference('Group.count', -1) do
+ delete :destroy, id: @group.to_param
+ end
+
+ assert_redirected_to groups_path
+ end
+end
diff --git a/test/functional/restore_jobs_controller_test.rb b/test/functional/restore_jobs_controller_test.rb
new file mode 100644
index 0000000..bd06b25
--- /dev/null
+++ b/test/functional/restore_jobs_controller_test.rb
@@ -0,0 +1,49 @@
+require 'test_helper'
+
+class RestoreJobsControllerTest < ActionController::TestCase
+ setup do
+ @restore_job = restore_jobs(:one)
+ end
+
+ test "should get index" do
+ get :index
+ assert_response :success
+ assert_not_nil assigns(:restore_jobs)
+ end
+
+ test "should get new" do
+ get :new
+ assert_response :success
+ end
+
+ test "should create restore_job" do
+ assert_difference('RestoreJob.count') do
+ post :create, restore_job: @restore_job.attributes
+ end
+
+ assert_redirected_to restore_job_path(assigns(:restore_job))
+ end
+
+ test "should show restore_job" do
+ get :show, id: @restore_job.to_param
+ assert_response :success
+ end
+
+ test "should get edit" do
+ get :edit, id: @restore_job.to_param
+ assert_response :success
+ end
+
+ test "should update restore_job" do
+ put :update, id: @restore_job.to_param, restore_job: @restore_job.attributes
+ assert_redirected_to restore_job_path(assigns(:restore_job))
+ end
+
+ test "should destroy restore_job" do
+ assert_difference('RestoreJob.count', -1) do
+ delete :destroy, id: @restore_job.to_param
+ end
+
+ assert_redirected_to restore_jobs_path
+ end
+end
diff --git a/test/unit/group_membership_test.rb b/test/unit/group_membership_test.rb
new file mode 100644
index 0000000..3719323
--- /dev/null
+++ b/test/unit/group_membership_test.rb
@@ -0,0 +1,7 @@
+require 'test_helper'
+
+class GroupMembershipTest < ActiveSupport::TestCase
+ def test_should_be_valid
+ assert GroupMembership.new.valid?
+ end
+end
diff --git a/test/unit/group_permission_test.rb b/test/unit/group_permission_test.rb
new file mode 100644
index 0000000..44e0b28
--- /dev/null
+++ b/test/unit/group_permission_test.rb
@@ -0,0 +1,7 @@
+require 'test_helper'
+
+class GroupPermissionTest < ActiveSupport::TestCase
+ def test_should_be_valid
+ assert GroupPermission.new.valid?
+ end
+end
diff --git a/test/unit/group_test.rb b/test/unit/group_test.rb
new file mode 100644
index 0000000..68ecdc0
--- /dev/null
+++ b/test/unit/group_test.rb
@@ -0,0 +1,7 @@
+require 'test_helper'
+
+class GroupTest < ActiveSupport::TestCase
+ def test_should_be_valid
+ assert Group.new.valid?
+ end
+end
diff --git a/test/unit/restore_job_test.rb b/test/unit/restore_job_test.rb
new file mode 100644
index 0000000..ce69ced
--- /dev/null
+++ b/test/unit/restore_job_test.rb
@@ -0,0 +1,7 @@
+require 'test_helper'
+
+class RestoreJobTest < ActiveSupport::TestCase
+ def test_should_be_valid
+ assert RestoreJob.new.valid?
+ end
+end