diff --git a/app/assets/javascripts/app/controllers/_application_controller.coffee b/app/assets/javascripts/app/controllers/_application_controller.coffee index f364256db..8309ce22c 100644 --- a/app/assets/javascripts/app/controllers/_application_controller.coffee +++ b/app/assets/javascripts/app/controllers/_application_controller.coffee @@ -172,13 +172,6 @@ class App.Controller extends Spine.Controller element.css('position', 'relative') shakeMe(element, position, 20) - isRole: (name) -> - roles = @Session.get('roles') - return false if !roles - for role in roles - return true if role.name is name - return false - # get all params of the form formParam: (form) -> App.ControllerForm.params(form) @@ -214,28 +207,50 @@ class App.Controller extends Spine.Controller callback: data.callback ) - authenticate: (checkOnly = false, role) -> - - # role check - if role && !@isRole(role) - return false if checkOnly - @navigate '#login' - return false - - # return true if session exists - return true if @Session.get() + permissionCheckRedirect: (key, closeTab = false) -> + return true if @permissionCheck(key) # remember requested url - if !checkOnly - location = window.location.hash - if location && location isnt '#login' && location isnt '#logout' && location isnt '#keyboard_shortcuts' - @Config.set('requested_url', location) + location = window.location.hash + if location && location isnt '#login' && location isnt '#logout' && location isnt '#keyboard_shortcuts' + App.Config.set('requested_url', location) - return false if checkOnly + if closeTab + App.TaskManager.remove(@task_key) # redirect to login @navigate '#login' - return false + + throw "No permission for #{key}" + + false + + permissionCheck: (key) -> + user_id = App.Session.get('id') + return false if !user_id + user = App.User.find(user_id) + return false if !user + user.permission(key) + + authenticateCheckRedirect: -> + return true if @authenticateCheck() + + # remember requested url + location = window.location.hash + if location && location isnt '#login' && location isnt '#logout' && location isnt '#keyboard_shortcuts' + @Config.set('requested_url', location) + + # redirect to login + @navigate '#login' + + throw 'No exsisting session' + + false + + authenticateCheck: -> + # return true if session exists + return true if @Session.get() + false frontendTime: (timestamp, row = {}) -> if !row['subclass'] @@ -264,7 +279,7 @@ class App.Controller extends Spine.Controller ticketPopups: (position = 'right') -> # open ticket in new task if curent user agent - if @isRole('Agent') + if @permissionCheck('ticket.agent') @$('div.ticket-popover, span.ticket-popover').bind('click', (e) => id = $(e.target).data('id') if id @@ -308,7 +323,7 @@ class App.Controller extends Spine.Controller userPopups: (position = 'right') -> # open user in new task if current user is agent - return if !@isRole('Agent') + return if !@permissionCheck('ticket.agent') @$('div.user-popover, span.user-popover').bind('click', (e) => id = $(e.target).data('id') if id @@ -365,7 +380,7 @@ class App.Controller extends Spine.Controller organizationPopups: (position = 'right') -> # open org in new task if current user agent - return if !@isRole('Agent') + return if !@permissionCheck('ticket.agent') @$('div.organization-popover, span.organization-popover').bind('click', (e) => id = $(e.target).data('id') @@ -626,12 +641,22 @@ class App.Controller extends Spine.Controller class App.ControllerPermanent extends App.Controller constructor: -> super + + # check authentication + if @requiredPermission + @permissionCheckRedirect(@requiredPermission, true) + $('.content').addClass('hide') @navShow() class App.ControllerContent extends App.Controller constructor: -> super + + # check authentication + if @requiredPermission + @permissionCheckRedirect(@requiredPermission) + $('.content').addClass('hide') $('#content').removeClass('hide') @navShow() @@ -667,7 +692,7 @@ class App.ControllerModal extends App.Controller super if @authenticateRequired - return if !@authenticate() + return if !@authenticateCheckRedirect() # rerender view, e. g. on langauge change @bind('ui:rerender', => diff --git a/app/assets/javascripts/app/controllers/_application_controller_generic.coffee b/app/assets/javascripts/app/controllers/_application_controller_generic.coffee index 8e09b1f3f..7ac1497eb 100644 --- a/app/assets/javascripts/app/controllers/_application_controller_generic.coffee +++ b/app/assets/javascripts/app/controllers/_application_controller_generic.coffee @@ -313,11 +313,16 @@ class App.ControllerDrox extends App.Controller class App.ControllerTabs extends App.Controller events: - 'click .nav-tabs [data-toggle="tab"]': 'tabRemember', + 'click .nav-tabs [data-toggle="tab"]': 'tabRemember' constructor: -> super + # check authentication + if @requiredPermission + if !@permissionCheckRedirect(@requiredPermission) + throw "No permission for #{@requiredPermission}" + render: -> @html App.view('generic/tabs')( header: @header @@ -359,27 +364,24 @@ class App.ControllerNavSidbar extends App.ControllerContent @navupdate '' if @authenticateRequired - return if !@authenticate() + @authenticateCheckRedirect() @params = params # get accessable groups - roles = App.Session.get('roles') + user = App.User.find(App.Session.get('id')) groups = App.Config.get(@configKey) groupsUnsorted = [] for key, item of groups if !item.controller - if !item.role + if !item.permission groupsUnsorted.push item else - match = _.include(item.role, 'Anybody') - if !match - for role in roles - if !match - match = _.include(item.role, role.name) - if match - groupsUnsorted.push item - + match = false + for permissionName in item.permission + if !match && user.permission(permissionName) + match = true + groupsUnsorted.push item @groupsSorted = _.sortBy(groupsUnsorted, (item) -> return item.prio) # get items of group @@ -389,16 +391,14 @@ class App.ControllerNavSidbar extends App.ControllerContent for key, item of items if item.parent is group.target if item.controller - if !item.role + if !item.permission itemsUnsorted.push item else - match = _.include(item.role, 'Anybody') - if !match - for role in roles - if !match - match = _.include(item.role, role.name) - if match - itemsUnsorted.push item + match = false + for permissionName in item.permission + if !match && user && user.permission(permissionName) + match = true + itemsUnsorted.push item group.items = _.sortBy(itemsUnsorted, (item) -> return item.prio) diff --git a/app/assets/javascripts/app/controllers/_channel/chat.coffee b/app/assets/javascripts/app/controllers/_channel/chat.coffee index 3db91c366..7b64d7423 100644 --- a/app/assets/javascripts/app/controllers/_channel/chat.coffee +++ b/app/assets/javascripts/app/controllers/_channel/chat.coffee @@ -1,4 +1,5 @@ -class App.ChannelChat extends App.Controller +class App.ChannelChat extends App.ControllerContent + requiredPermission: 'admin.channel_chat' events: 'change .js-params': 'updateParams' 'input .js-params': 'updateParams' @@ -358,7 +359,7 @@ class App.ChannelChat extends App.Controller @paramsBlock.each (i, block) -> hljs.highlightBlock block -App.Config.set( 'Chat', { prio: 4000, name: 'Chat', parent: '#channels', target: '#channels/chat', controller: App.ChannelChat, role: ['Admin'] }, 'NavBarAdmin' ) +App.Config.set('Chat', { prio: 4000, name: 'Chat', parent: '#channels', target: '#channels/chat', controller: App.ChannelChat, permission: ['admin.chat'] }, 'NavBarAdmin') class Topics extends App.Controller events: diff --git a/app/assets/javascripts/app/controllers/_channel/email.coffee b/app/assets/javascripts/app/controllers/_channel/email.coffee index 3750aad99..7f31cc3fc 100644 --- a/app/assets/javascripts/app/controllers/_channel/email.coffee +++ b/app/assets/javascripts/app/controllers/_channel/email.coffee @@ -1,4 +1,5 @@ class App.ChannelEmail extends App.ControllerTabs + requiredPermission: 'admin.channel_email' header: 'Email' constructor: -> super @@ -919,4 +920,4 @@ class App.ChannelEmailNotificationWizard extends App.WizardModal @enable(e) ) -App.Config.set( 'Email', { prio: 3000, name: 'Email', parent: '#channels', target: '#channels/email', controller: App.ChannelEmail, role: ['Admin'] }, 'NavBarAdmin' ) +App.Config.set('Email', { prio: 3000, name: 'Email', parent: '#channels', target: '#channels/email', controller: App.ChannelEmail, permission: ['admin.channel_email'] }, 'NavBarAdmin') diff --git a/app/assets/javascripts/app/controllers/_channel/facebook.coffee b/app/assets/javascripts/app/controllers/_channel/facebook.coffee index 65fb63715..d9da63b37 100644 --- a/app/assets/javascripts/app/controllers/_channel/facebook.coffee +++ b/app/assets/javascripts/app/controllers/_channel/facebook.coffee @@ -1,4 +1,5 @@ class Index extends App.ControllerContent + requiredPermission: 'admin.channel_facebook' events: 'click .js-new': 'new' 'click .js-edit': 'edit' @@ -7,7 +8,6 @@ class Index extends App.ControllerContent constructor: -> super - return if !@authenticate(false, 'Admin') #@interval(@load, 60000) @load() @@ -193,4 +193,4 @@ class Index extends App.ControllerContent container: @el.closest('.content') ) -App.Config.set('Facebook', { prio: 5100, name: 'Facebook', parent: '#channels', target: '#channels/facebook', controller: Index, role: ['Admin'] }, 'NavBarAdmin') +App.Config.set('Facebook', { prio: 5100, name: 'Facebook', parent: '#channels', target: '#channels/facebook', controller: Index, permission: ['admin.channel_facebook'] }, 'NavBarAdmin') diff --git a/app/assets/javascripts/app/controllers/_channel/form.coffee b/app/assets/javascripts/app/controllers/_channel/form.coffee index a4a3ad74d..f417f45f8 100644 --- a/app/assets/javascripts/app/controllers/_channel/form.coffee +++ b/app/assets/javascripts/app/controllers/_channel/form.coffee @@ -1,5 +1,6 @@ # coffeelint: disable=no_unnecessary_double_quotes -class App.ChannelForm extends App.Controller +class App.ChannelForm extends App.ControllerContent + requiredPermission: 'admin.channel_form' events: 'change form.js-params': 'updateParams' 'keyup form.js-params': 'updateParams' @@ -52,4 +53,4 @@ class App.ChannelForm extends App.Controller value = @formSetting.prop('checked') App.Setting.set('form_ticket_create', value) -App.Config.set( 'Form', { prio: 2000, name: 'Form', parent: '#channels', target: '#channels/form', controller: App.ChannelForm, role: ['Admin'] }, 'NavBarAdmin' ) +App.Config.set('Form', { prio: 2000, name: 'Form', parent: '#channels', target: '#channels/form', controller: App.ChannelForm, permission: ['admin.formular'] }, 'NavBarAdmin') diff --git a/app/assets/javascripts/app/controllers/_channel/twitter.coffee b/app/assets/javascripts/app/controllers/_channel/twitter.coffee index d1a56598b..9becfbed4 100644 --- a/app/assets/javascripts/app/controllers/_channel/twitter.coffee +++ b/app/assets/javascripts/app/controllers/_channel/twitter.coffee @@ -1,4 +1,5 @@ class Index extends App.ControllerContent + requiredPermission: 'admin.channel_twitter' events: 'click .js-new': 'new' 'click .js-edit': 'edit' @@ -7,7 +8,6 @@ class Index extends App.ControllerContent constructor: -> super - return if !@authenticate(false, 'Admin') #@interval(@load, 60000) @load() @@ -227,4 +227,4 @@ class Index extends App.ControllerContent container: @el.closest('.content') ) -App.Config.set('Twitter', { prio: 5000, name: 'Twitter', parent: '#channels', target: '#channels/twitter', controller: Index, role: ['Admin'] }, 'NavBarAdmin') +App.Config.set('Twitter', { prio: 5000, name: 'Twitter', parent: '#channels', target: '#channels/twitter', controller: Index, permission: ['admin.channel_twitter'] }, 'NavBarAdmin') diff --git a/app/assets/javascripts/app/controllers/_channel/web.coffee b/app/assets/javascripts/app/controllers/_channel/web.coffee index e2abdc27e..6e5915855 100644 --- a/app/assets/javascripts/app/controllers/_channel/web.coffee +++ b/app/assets/javascripts/app/controllers/_channel/web.coffee @@ -1,4 +1,5 @@ class App.ChannelWeb extends App.ControllerTabs + requiredPermission: 'admin.channel_web' header: 'Web' constructor: -> super @@ -15,4 +16,4 @@ class App.ChannelWeb extends App.ControllerTabs @render() -App.Config.set( 'Web', { prio: 1000, name: 'Web', parent: '#channels', target: '#channels/web', controller: App.ChannelWeb, role: ['Admin'] }, 'NavBarAdmin' ) +App.Config.set('Web', { prio: 1000, name: 'Web', parent: '#channels', target: '#channels/web', controller: App.ChannelWeb, permission: ['admin.channel_web'] }, 'NavBarAdmin') diff --git a/app/assets/javascripts/app/controllers/_default_navbar.coffee b/app/assets/javascripts/app/controllers/_default_navbar.coffee index b6c5fb774..2cf205da8 100644 --- a/app/assets/javascripts/app/controllers/_default_navbar.coffee +++ b/app/assets/javascripts/app/controllers/_default_navbar.coffee @@ -8,12 +8,11 @@ App.Config.set('User', { return item target: '#current_user', class: 'user' - role: [ 'Agent', 'Customer' ] }, 'NavBarRight' ) -App.Config.set( 'Admin', { prio: 9000, parent: '', name: 'Admin', translate: true, target: '#manage', icon: 'cog', role: ['Admin'] }, 'NavBarRight' ) -App.Config.set( 'New', { prio: 20000, parent: '', name: 'New', translate: true, target: '#new', class: 'add' }, 'NavBarRight' ) -App.Config.set( 'Misc', { prio: 90000, parent: '', name: 'Tools', translate: true, target: '#tools', child: true, class: 'tools' }, 'NavBar' ) +App.Config.set('Admin', { prio: 9000, parent: '', name: 'Admin', translate: true, target: '#manage', icon: 'cog', permission: ['admin.*'] }, 'NavBarRight') +App.Config.set('New', { prio: 20000, parent: '', name: 'New', translate: true, target: '#new', class: 'add' }, 'NavBarRight') +App.Config.set('Misc', { prio: 90000, parent: '', name: 'Tools', translate: true, target: '#tools', child: true, class: 'tools' }, 'NavBar') # only for testing -#App.Config.set( 'Misc1', { prio: 1600, parent: '#tools', name: 'Test 1', target: '#test1', role: [ 'Admin' ] }, 'NavBar' ) -#App.Config.set( 'Misc2', { prio: 1700, parent: '#tools', name: 'Test 2', target: '#test2', role: [ 'Admin' ] }, 'NavBar' ) +#App.Config.set('Misc1', { prio: 1600, parent: '#tools', name: 'Test 1', target: '#test1', permission: ['admin'] }, 'NavBar') +#App.Config.set('Misc2', { prio: 1700, parent: '#tools', name: 'Test 2', target: '#test2', permission: ['admin'] }, 'NavBar') diff --git a/app/assets/javascripts/app/controllers/_integration/_base.coffee b/app/assets/javascripts/app/controllers/_integration/_base.coffee index 929f27c5e..07a9e02a5 100644 --- a/app/assets/javascripts/app/controllers/_integration/_base.coffee +++ b/app/assets/javascripts/app/controllers/_integration/_base.coffee @@ -13,7 +13,6 @@ class App.ControllerIntegrationBase extends App.Controller constructor: -> super - return if !@authenticate(false, 'Admin') @title @featureName, true @initalRender = true diff --git a/app/assets/javascripts/app/controllers/_integration/clearbit.coffee b/app/assets/javascripts/app/controllers/_integration/clearbit.coffee index 78fc6e1db..e13340953 100644 --- a/app/assets/javascripts/app/controllers/_integration/clearbit.coffee +++ b/app/assets/javascripts/app/controllers/_integration/clearbit.coffee @@ -29,9 +29,6 @@ class Form extends App.Controller constructor: -> super - # check authentication - return if !@authenticate() - @subscribeId = App.Setting.subscribe(@render, initFetch: true, clear: false) currentConfig: -> diff --git a/app/assets/javascripts/app/controllers/_integration/sipgate_io.coffee b/app/assets/javascripts/app/controllers/_integration/sipgate_io.coffee index 8998843bf..5d3197de7 100644 --- a/app/assets/javascripts/app/controllers/_integration/sipgate_io.coffee +++ b/app/assets/javascripts/app/controllers/_integration/sipgate_io.coffee @@ -28,10 +28,6 @@ class Form extends App.Controller constructor: -> super - - # check authentication - return if !@authenticate() - @subscribeId = App.Setting.subscribe(@render, initFetch: true, clear: false) currentConfig: -> diff --git a/app/assets/javascripts/app/controllers/_integration/slack.coffee b/app/assets/javascripts/app/controllers/_integration/slack.coffee index a579aa548..a34c01f6f 100644 --- a/app/assets/javascripts/app/controllers/_integration/slack.coffee +++ b/app/assets/javascripts/app/controllers/_integration/slack.coffee @@ -24,10 +24,10 @@ class Index extends App.ControllerIntegrationBase configureAttributes = [ { name: 'types', display: 'Trigger', tag: 'checkbox', options: options, 'null': false, class: 'vertical', note: 'Where notification is sent.' }, { name: 'group_id', display: 'Group', tag: 'select', relation: 'Group', multiple: true, 'null': false, note: 'Only for this groups.' }, - { name: 'webhook', display: 'Webhook', tag: 'input', type: 'url', limit: 200, 'null': false, placeholder: 'https://hooks.slack.com/services/...' }, + { name: 'webhook', display: 'Webhook', tag: 'input', type: 'url', limit: 200, 'null': false, placeholder: 'https://hooks.slack.com/services/...' }, { name: 'username', display: 'Username', tag: 'input', type: 'text', limit: 100, 'null': false, placeholder: 'username' }, { name: 'channel', display: 'Channel', tag: 'input', type: 'text', limit: 100, 'null': true, placeholder: '#channel' }, - { name: 'icon_url', display: 'Icon Url', tag: 'input', type: 'url', limit: 200, 'null': true, placeholder: 'https://example.com/logo.png' }, + { name: 'icon_url', display: 'Icon Url', tag: 'input', type: 'url', limit: 200, 'null': true, placeholder: 'https://example.com/logo.png' }, ] settings = [] diff --git a/app/assets/javascripts/app/controllers/_manage/branding.coffee b/app/assets/javascripts/app/controllers/_manage/branding.coffee index e92a9b06c..212277b8a 100644 --- a/app/assets/javascripts/app/controllers/_manage/branding.coffee +++ b/app/assets/javascripts/app/controllers/_manage/branding.coffee @@ -1,12 +1,13 @@ class Branding extends App.ControllerTabs + requiredPermission: 'admin.branding' header: 'Branding' constructor: -> super - return if !@authenticate(false, 'Admin') + @title 'Branding', true @tabs = [ { name: 'Base', 'target': 'base', controller: App.SettingsArea, params: { area: 'System::Branding' } } ] @render() -App.Config.set('SettingBranding', { prio: 1200, parent: '#settings', name: 'Branding', target: '#settings/branding', controller: Branding, role: ['Admin'] }, 'NavBarAdmin') +App.Config.set('SettingBranding', { prio: 1200, parent: '#settings', name: 'Branding', target: '#settings/branding', controller: Branding, permission: ['admin.branding'] }, 'NavBarAdmin') diff --git a/app/assets/javascripts/app/controllers/_manage/import.coffee b/app/assets/javascripts/app/controllers/_manage/import.coffee deleted file mode 100644 index afe42c73f..000000000 --- a/app/assets/javascripts/app/controllers/_manage/import.coffee +++ /dev/null @@ -1,13 +0,0 @@ -class Import extends App.ControllerTabs - header: 'Import' - constructor: -> - super - return if !@authenticate(false, 'Admin') - @title 'Import', true - @tabs = [ - { name: 'Base', 'target': 'base', controller: App.SettingsArea, params: { area: 'Import::Base' } } - { name: 'OTRS', 'target': 'otrs', controller: App.SettingsArea, params: { area: 'Import::OTRS' } } - ] - @render() - -App.Config.set('SettingImport', { prio: 1800, parent: '#settings', name: 'Import', target: '#settings/import', controller: Import, role: ['Admin'] }, 'NavBarAdmin') diff --git a/app/assets/javascripts/app/controllers/_manage/security.coffee b/app/assets/javascripts/app/controllers/_manage/security.coffee index 2465c92d9..37d245a4b 100644 --- a/app/assets/javascripts/app/controllers/_manage/security.coffee +++ b/app/assets/javascripts/app/controllers/_manage/security.coffee @@ -1,15 +1,17 @@ class Security extends App.ControllerTabs + requiredPermission: 'admin.security' header: 'Security' constructor: -> super - return if !@authenticate(false, 'Admin') + @title 'Security', true @tabs = [ { name: 'Base', 'target': 'base', controller: App.SettingsArea, params: { area: 'Security::Base' } } -# { name: 'Authentication', 'target': 'auth', controller: App.SettingsArea, params: { area: 'Security::Authentication' } } { name: 'Password', 'target': 'password', controller: App.SettingsArea, params: { area: 'Security::Password' } } - { name: 'Third-Party Applications', 'target': 'third_party_auth', controller: App.SettingsArea, params: { area: 'Security::ThirdPartyAuthentication' } } + #{ name: 'Authentication', 'target': 'auth', controller: App.SettingsArea, params: { area: 'Security::Authentication' } } + { name: 'Third-Party Applications', 'target': 'third_party_auth', controller: App.SettingsThirdPartyAuthentication, params: { area: 'Security::ThirdPartyAuthentication' } } ] @render() -App.Config.set('SettingSecurity', { prio: 1600, parent: '#settings', name: 'Security', target: '#settings/security', controller: Security, role: ['Admin'] }, 'NavBarAdmin') +App.Config.set('SettingSecurity', { prio: 1600, parent: '#settings', name: 'Security', target: '#settings/security', controller: Security, permission: ['admin.security'] }, 'NavBarAdmin') + diff --git a/app/assets/javascripts/app/controllers/_manage/system.coffee b/app/assets/javascripts/app/controllers/_manage/system.coffee index 8ce48de3c..95f61c83c 100644 --- a/app/assets/javascripts/app/controllers/_manage/system.coffee +++ b/app/assets/javascripts/app/controllers/_manage/system.coffee @@ -1,8 +1,9 @@ class System extends App.ControllerTabs + requiredPermission: 'admin.setting_system' header: 'System' constructor: -> super - return if !@authenticate(false, 'Admin') + @title 'System', true @tabs = [] if !App.Config.get('system_online_service') @@ -13,4 +14,4 @@ class System extends App.ControllerTabs @tabs.push { name: 'Frontend', 'target': 'ui', controller: App.SettingsArea, params: { area: 'System::UI' } } @render() -App.Config.set('SettingSystem', { prio: 1400, parent: '#settings', name: 'System', target: '#settings/system', controller: System, role: ['Admin'] }, 'NavBarAdmin') +App.Config.set('SettingSystem', { prio: 1400, parent: '#settings', name: 'System', target: '#settings/system', controller: System, permission: ['admin.setting_system'] }, 'NavBarAdmin') diff --git a/app/assets/javascripts/app/controllers/_manage/ticket.coffee b/app/assets/javascripts/app/controllers/_manage/ticket.coffee index 0b00cd808..7e5860358 100644 --- a/app/assets/javascripts/app/controllers/_manage/ticket.coffee +++ b/app/assets/javascripts/app/controllers/_manage/ticket.coffee @@ -1,8 +1,9 @@ class Ticket extends App.ControllerTabs + requiredPermission: 'admin.ticket' header: 'Ticket' constructor: -> super - return if !@authenticate(false, 'Admin') + @title 'Ticket', true @tabs = [ { name: 'Base', 'target': 'base', controller: App.SettingsArea, params: { area: 'Ticket::Base' } } @@ -10,4 +11,4 @@ class Ticket extends App.ControllerTabs ] @render() -App.Config.set('SettingTicket', { prio: 1700, parent: '#settings', name: 'Ticket', target: '#settings/ticket', controller: Ticket, role: ['Admin'] }, 'NavBarAdmin') +App.Config.set('SettingTicket', { prio: 1700, parent: '#settings', name: 'Ticket', target: '#settings/ticket', controller: Ticket, permission: ['admin.ticket'] }, 'NavBarAdmin') diff --git a/app/assets/javascripts/app/controllers/_profile/avatar.coffee b/app/assets/javascripts/app/controllers/_profile/avatar.coffee index 7abaec4ed..e7bbab7d3 100644 --- a/app/assets/javascripts/app/controllers/_profile/avatar.coffee +++ b/app/assets/javascripts/app/controllers/_profile/avatar.coffee @@ -1,4 +1,5 @@ -class Index extends App.Controller +class Index extends App.ControllerContent + requiredPermission: 'user_preferences.avatar' elements: '.js-upload': 'fileInput' '.avatar-gallery': 'avatarGallery' @@ -11,7 +12,6 @@ class Index extends App.Controller constructor: -> super - return if !@authenticate() @title 'Avatar', true @avatars = [] @loadAvatarList() @@ -143,7 +143,7 @@ class Index extends App.Controller reader.readAsDataURL(@) -App.Config.set('Avatar', { prio: 1100, name: 'Avatar', parent: '#profile', target: '#profile/avatar', controller: Index }, 'NavBarProfile') +App.Config.set('Avatar', { prio: 1100, name: 'Avatar', parent: '#profile', target: '#profile/avatar', controller: Index, permission: ['user_preferences.avatar'] }, 'NavBarProfile') class ImageCropper extends App.ControllerModal buttonClose: true diff --git a/app/assets/javascripts/app/controllers/_profile/calendar_subscriptions.coffee b/app/assets/javascripts/app/controllers/_profile/calendar_subscriptions.coffee index f9d67841a..c785404d0 100644 --- a/app/assets/javascripts/app/controllers/_profile/calendar_subscriptions.coffee +++ b/app/assets/javascripts/app/controllers/_profile/calendar_subscriptions.coffee @@ -1,4 +1,5 @@ -class CalendarSubscriptions extends App.Controller +class CalendarSubscriptions extends App.ControllerContent + requiredPermission: 'user_preferences.calendar+ticket.agent' elements: 'input[type=checkbox]': 'options' 'output': 'output' @@ -10,7 +11,6 @@ class CalendarSubscriptions extends App.Controller constructor: -> super - return if !@authenticate() @title 'Calendar', true @translationTable = @@ -91,4 +91,4 @@ class CalendarSubscriptions extends App.Controller msg: App.i18n.translateContent(data.message) ) -App.Config.set('CalendarSubscriptions', { prio: 3000, name: 'Calendar', parent: '#profile', target: '#profile/calendar_subscriptions', role: ['Agent'], controller: CalendarSubscriptions }, 'NavBarProfile') +App.Config.set('CalendarSubscriptions', { prio: 3000, name: 'Calendar', parent: '#profile', target: '#profile/calendar_subscriptions', permission: ['user_preferences.calendar+ticket.agent'], controller: CalendarSubscriptions }, 'NavBarProfile') diff --git a/app/assets/javascripts/app/controllers/_profile/devices.coffee b/app/assets/javascripts/app/controllers/_profile/devices.coffee index 284c27ed0..173a91f30 100644 --- a/app/assets/javascripts/app/controllers/_profile/devices.coffee +++ b/app/assets/javascripts/app/controllers/_profile/devices.coffee @@ -1,12 +1,11 @@ -class Index extends App.Controller +class Index extends App.ControllerContent + requiredPermission: 'user_preferences.device' events: 'click [data-type=delete]': 'delete' constructor: -> super - return if !@authenticate() @title 'Devices', true - @load() @interval( => @@ -56,4 +55,4 @@ class Index extends App.Controller msg: App.i18n.translateContent(data.message) ) -App.Config.set('Devices', { prio: 3100, name: 'Devices', parent: '#profile', target: '#profile/devices', controller: Index }, 'NavBarProfile') +App.Config.set('Devices', { prio: 3100, name: 'Devices', parent: '#profile', target: '#profile/devices', controller: Index, permission: ['user_preferences.device'] }, 'NavBarProfile') diff --git a/app/assets/javascripts/app/controllers/_profile/language.coffee b/app/assets/javascripts/app/controllers/_profile/language.coffee index 2a2ed2f8d..8218fde92 100644 --- a/app/assets/javascripts/app/controllers/_profile/language.coffee +++ b/app/assets/javascripts/app/controllers/_profile/language.coffee @@ -1,10 +1,10 @@ -class Index extends App.Controller +class Index extends App.ControllerContent + requiredPermission: 'user_preferences.language' events: 'submit form': 'update' constructor: -> super - return if !@authenticate() @title 'Language', true @render() @@ -40,7 +40,7 @@ class Index extends App.Controller @ajax( id: 'preferences' type: 'PUT' - url: @apiPath + '/users/preferences' + url: "#{@apiPath}/users/preferences" data: JSON.stringify({user:params}) processData: true success: @success @@ -69,4 +69,4 @@ class Index extends App.Controller msg: App.i18n.translateContent(data.message) ) -App.Config.set( 'Language', { prio: 1000, name: 'Language', parent: '#profile', target: '#profile/language', controller: Index }, 'NavBarProfile' ) +App.Config.set('Language', { prio: 1000, name: 'Language', parent: '#profile', target: '#profile/language', controller: Index, permission: ['user_preferences.language'] }, 'NavBarProfile') diff --git a/app/assets/javascripts/app/controllers/_profile/linked_accounts.coffee b/app/assets/javascripts/app/controllers/_profile/linked_accounts.coffee index 587b2132e..4bbab8d95 100644 --- a/app/assets/javascripts/app/controllers/_profile/linked_accounts.coffee +++ b/app/assets/javascripts/app/controllers/_profile/linked_accounts.coffee @@ -1,10 +1,10 @@ -class Index extends App.Controller +class Index extends App.ControllerContent + requiredPermission: 'user_preferences.linked_accounts' events: 'click .js-remove': 'remove' constructor: -> super - return if !@authenticate() @title 'Linked Accounts', true @render() @@ -78,4 +78,4 @@ class Index extends App.Controller msg: App.i18n.translateContent(data.message) ) -App.Config.set('LinkedAccounts', { prio: 4000, name: 'Linked Accounts', parent: '#profile', target: '#profile/linked', controller: Index }, 'NavBarProfile') +App.Config.set('LinkedAccounts', { prio: 4000, name: 'Linked Accounts', parent: '#profile', target: '#profile/linked', controller: Index, permission: ['user_preferences.linked_accounts'] }, 'NavBarProfile') diff --git a/app/assets/javascripts/app/controllers/_profile/notification.coffee b/app/assets/javascripts/app/controllers/_profile/notification.coffee index b2d75681f..4b8bd7d32 100644 --- a/app/assets/javascripts/app/controllers/_profile/notification.coffee +++ b/app/assets/javascripts/app/controllers/_profile/notification.coffee @@ -1,4 +1,5 @@ -class Index extends App.Controller +class Index extends App.ControllerContent + requiredPermission: 'user_preferences.notifications+ticket.agent' events: 'submit form': 'update' 'change .js-notificationSound': 'previewSound' @@ -44,7 +45,6 @@ class Index extends App.Controller constructor: -> super - return if !@authenticate(false, 'Agent') @title 'Notifications', true @render() @@ -193,5 +193,4 @@ class Index extends App.Controller return if !params.notification_sound.file App.OnlineNotification.play(params.notification_sound.file) - -App.Config.set( 'Notifications', { prio: 2600, name: 'Notifications', parent: '#profile', target: '#profile/notifications', role: ['Agent'], controller: Index }, 'NavBarProfile' ) +App.Config.set('Notifications', { prio: 2600, name: 'Notifications', parent: '#profile', target: '#profile/notifications', permission: ['user_preferences.notifications+ticket.agent'], controller: Index }, 'NavBarProfile') diff --git a/app/assets/javascripts/app/controllers/_profile/password.coffee b/app/assets/javascripts/app/controllers/_profile/password.coffee index dccafb7fe..d8ad6fb80 100644 --- a/app/assets/javascripts/app/controllers/_profile/password.coffee +++ b/app/assets/javascripts/app/controllers/_profile/password.coffee @@ -1,10 +1,10 @@ -class Index extends App.Controller +class Index extends App.ControllerContent + requiredPermission: 'user_preferences.password' events: 'submit form': 'update' constructor: -> super - return if !@authenticate() @title 'Password', true @render() @@ -78,4 +78,4 @@ class Index extends App.Controller removeAll: true @formEnable( @$('form') ) -App.Config.set( 'Password', { prio: 2000, name: 'Password', parent: '#profile', target: '#profile/password', controller: Index }, 'NavBarProfile' ) +App.Config.set('Password', { prio: 2000, name: 'Password', parent: '#profile', target: '#profile/password', controller: Index, permission: ['user_preferences.password'] }, 'NavBarProfile') diff --git a/app/assets/javascripts/app/controllers/_profile/token_access.coffee b/app/assets/javascripts/app/controllers/_profile/token_access.coffee index 4d18b549d..e02b88562 100644 --- a/app/assets/javascripts/app/controllers/_profile/token_access.coffee +++ b/app/assets/javascripts/app/controllers/_profile/token_access.coffee @@ -1,11 +1,11 @@ -class Index extends App.Controller +class Index extends App.ControllerContent + requiredPermission: 'user_preferences.access_token' events: 'click [data-type=delete]': 'delete' 'submit form.js-create': 'create' constructor: -> super - return if !@authenticate() @title 'Token Access', true @load() @@ -89,4 +89,4 @@ class Index extends App.Controller msg: App.i18n.translateContent(data.message) ) -App.Config.set('Token Access', { prio: 3200, name: 'Token Access', parent: '#profile', target: '#profile/token_access', controller: Index, role: [ 'Agent', 'Admin' ] }, 'NavBarProfile') +App.Config.set('Token Access', { prio: 3200, name: 'Token Access', parent: '#profile', target: '#profile/token_access', controller: Index, permission: ['user_preferences.access_token'] }, 'NavBarProfile') diff --git a/app/assets/javascripts/app/controllers/_settings/area.coffee b/app/assets/javascripts/app/controllers/_settings/area.coffee index 6861e027a..234a258de 100644 --- a/app/assets/javascripts/app/controllers/_settings/area.coffee +++ b/app/assets/javascripts/app/controllers/_settings/area.coffee @@ -3,8 +3,7 @@ class App.SettingsArea extends App.Controller super # check authentication - return if !@authenticate() - + @authenticateCheckRedirect() @subscribeId = App.Setting.subscribe(@render, initFetch: true, clear: false) render: => diff --git a/app/assets/javascripts/app/controllers/_settings/form.coffee b/app/assets/javascripts/app/controllers/_settings/form.coffee index a50528936..9328d876c 100644 --- a/app/assets/javascripts/app/controllers/_settings/form.coffee +++ b/app/assets/javascripts/app/controllers/_settings/form.coffee @@ -6,7 +6,7 @@ class App.SettingsForm extends App.Controller super # check authentication - return if !@authenticate() + @authenticateCheckRedirect() @subscribeId = App.Setting.subscribe(@render, initFetch: true, clear: false) diff --git a/app/assets/javascripts/app/controllers/_ui_element/permission.coffee b/app/assets/javascripts/app/controllers/_ui_element/permission.coffee new file mode 100644 index 000000000..6c8b87543 --- /dev/null +++ b/app/assets/javascripts/app/controllers/_ui_element/permission.coffee @@ -0,0 +1,40 @@ +# coffeelint: disable=camel_case_classes +class App.UiElement.permission extends App.UiElement.ApplicationUiElement + @render: (attribute, params) -> + + permissions = App.Permission.search(sortBy: 'name') + + item = $( App.view('generic/permission')( + attribute: attribute + params: params + permissions: permissions + ) ) + + # show/hide trees + item.find('[name=permission_ids]').bind('change', (e) -> + element = $(e.currentTarget) + checked = element.prop('checked') + permission_id = element.prop('value') + return if !permission_id + permission = App.Permission.find(permission_id) + return if !permission + if !permission.name.match(/\./) + + # show/hide sub permissions + for localPermission in permissions + regexp = new RegExp("^#{permission.name}") + if localPermission.name.match(regexp) + localElement = item.find("[name=permission_ids][value=#{localPermission.id}]").closest('.js-subPermissionList') + if checked + localElement.addClass('hide') + else + localElement.removeClass('hide') + if checked && permission.preferences.not + for localPermission in permission.preferences.not + lookupPermission = App.Permission.findByAttribute('name', localPermission) + if lookupPermission + item.find("[name=permission_ids][value=#{lookupPermission.id}]").prop('checked', false) + + ) + + item \ No newline at end of file diff --git a/app/assets/javascripts/app/controllers/_ui_element/user_permission.coffee b/app/assets/javascripts/app/controllers/_ui_element/user_permission.coffee index e8fb263a2..cbb9b8813 100644 --- a/app/assets/javascripts/app/controllers/_ui_element/user_permission.coffee +++ b/app/assets/javascripts/app/controllers/_ui_element/user_permission.coffee @@ -3,6 +3,25 @@ class App.UiElement.user_permission @render: (attribute, params = {}) -> attribute.options = {} + # take defaults users selected, select all groups + if _.isEmpty(params) && !_.isEmpty(attribute.value) + params.role_ids = attribute.value + selectAllGroups = false + for localRoleId in params.role_ids + role = App.Role.find(localRoleId) + if role + for permission_id in role.permission_ids + localPermission = App.Permission.find(permission_id) + if localPermission + if localPermission.name is 'ticket.agent' + selectAllGroups = true + break + if selectAllGroups + params.group_ids = [] + groupsRaw = App.Group.search(sortBy: 'name') + for group in groupsRaw + params.group_ids.push group.id + # get selectable roles and selected roles roles = [] rolesSelected = {} @@ -32,30 +51,14 @@ class App.UiElement.user_permission if groups.length <= 1 hideGroups = true - if attribute.hideMode - if attribute.hideMode.rolesSelected - roles = [] - rolesSelected = {} - for roleName in attribute.hideMode.rolesSelected - role = App.Role.findByAttribute('name', roleName) - if role - roles.push role - rolesSelected[role.id] = true - if attribute.hideMode.rolesNot - for roleRaw in rolesRaw - hit = false - for roleName in attribute.hideMode.rolesNot - if roleRaw.active && roleRaw.name is roleName - hit = true - if !hit - roles.push roleRaw - - # if agent is on new users selected, select all groups - if _.isEmpty(attribute.value) - agentRole = App.Role.findByAttribute('name', 'Agent') - if rolesSelected[agentRole.id] - for group in groups - groupsSelected[group.id] = true + # get roles with group plugin + rolesWithGroupPlugin = {} + for role in rolesRaw + if role.active + for permission_id in role.permission_ids + localPermission = App.Permission.find(permission_id) + if localPermission && localPermission.preferences && _.contains(localPermission.preferences.plugin, 'groups') + rolesWithGroupPlugin[role.id] = 'group' # uniq and sort roles roles = _.indexBy(roles, 'name') @@ -71,19 +74,6 @@ class App.UiElement.user_permission hideGroups: hideGroups ) ) - getCurrentRoles = -> - currentRoles = [] - item.find('[name=role_ids]').each( -> - element = $(@) - checked = element.prop('checked') - return if !checked - role_id = element.prop('value') - role = App.Role.find(role_id) - return if !role - currentRoles.push role - ) - currentRoles - # if customer, remove admin and agent item.find('[name=role_ids]').bind('change', (e) -> element = $(e.currentTarget) @@ -92,34 +82,34 @@ class App.UiElement.user_permission return if !role_id role = App.Role.find(role_id) return if !role + triggers = [] - # if agent got deselected - # - hide groups + # deselect conflicting roles + if checked + if role && role.preferences && role.preferences.not + for notRole in role.preferences.not + localRole = App.Role.findByAttribute('name', notRole) + if localRole + localElement = item.find("[name=role_ids][value=#{localRole.id}]") + if localElement.prop('checked') + if !confirm(App.i18n.translateInline('Role %s is conflicting with role %s, do you to continue?', role.name, localRole.name, localRole.name)) + item.find("[name=role_ids][value=#{role_id}]").prop('checked', false) + return + item.find("[name=role_ids][value=#{localRole.id}]").prop('checked', false) + triggers.push item.find("[name=role_ids][value=#{localRole.id}]") + + # if role with groups plugin is deselected, hide group selection if !checked - if role.name is 'Agent' + if rolesWithGroupPlugin[role_id] is 'group' item.find('.js-groupList').addClass('hidden') return - # if agent is selected - # - show groups - if role.name is 'Agent' + # if role with groups plugin is selected, show group selection + if rolesWithGroupPlugin[role_id] is 'group' item.find('.js-groupList:not(.js-groupListHide)').removeClass('hidden') - # if role customer is selected - # - deselect agent & admin - # - hide groups - if role.name is 'Customer' - for currentRole in getCurrentRoles() - if currentRole.name is 'Admin' || currentRole.name is 'Agent' - item.find("[name=role_ids][value=#{currentRole.id}]").prop('checked', false) - item.find('.js-groupList').addClass('hidden') - - # if role agent or admin is selected - # - deselect customer - else if role.name is 'Agent' || role.name is 'Admin' - for currentRole in getCurrentRoles() - if currentRole.name is 'Customer' - item.find("[name=role_ids][value=#{currentRole.id}]").prop('checked', false) + for trigger in triggers + trigger.trigger('change') ) item diff --git a/app/assets/javascripts/app/controllers/agent_ticket_create.coffee b/app/assets/javascripts/app/controllers/agent_ticket_create.coffee index 774a9f3d2..72fb148d7 100644 --- a/app/assets/javascripts/app/controllers/agent_ticket_create.coffee +++ b/app/assets/javascripts/app/controllers/agent_ticket_create.coffee @@ -10,11 +10,6 @@ class App.TicketCreate extends App.Controller constructor: (params) -> super - # check authentication - if !@authenticate(false, 'Agent') - App.TaskManager.remove(@task_key) - return - # define default type @default_type = 'phone-in' @@ -36,7 +31,7 @@ class App.TicketCreate extends App.Controller # rerender view, e. g. on langauge change @bind 'ui:rerender', => - return if !@authenticate(true) + return if !@authenticateCheck() @render() release: => @@ -137,7 +132,10 @@ class App.TicketCreate extends App.Controller autosaveStart: => if !@autosaveLast - @autosaveLast = App.TaskManager.get(@task_key).state || {} + state = App.TaskManager.get(@task_key) + if !state + state = {} + @autosaveLast = state || {} update = => data = @formParam(@$('.ticket-create')) return if _.isEmpty(data) @@ -213,8 +211,8 @@ class App.TicketCreate extends App.Controller @html App.view('agent_ticket_create')( head: 'New Ticket' - agent: @isRole('Agent') - admin: @isRole('Admin') + agent: @permissionCheck('ticket.agent') + admin: @permissionCheck('admin') form_id: @form_id ) @@ -593,6 +591,7 @@ class Sidebar extends App.Controller ) class Router extends App.ControllerPermanent + requiredPermission: 'ticket.agent' constructor: (params) -> super @@ -631,4 +630,4 @@ App.Config.set('ticket/create/:ticket_id/:article_id', Router, 'Routes') App.Config.set('ticket/create/id/:id/:ticket_id/:article_id', Router, 'Routes') # set new actions -App.Config.set('TicketCreate', { prio: 8003, parent: '#new', name: 'New Ticket', translate: true, target: '#ticket/create', role: ['Agent'], divider: true }, 'NavBarRight') +App.Config.set('TicketCreate', { prio: 8003, parent: '#new', name: 'New Ticket', translate: true, target: '#ticket/create', permission: ['ticket.agent'], divider: true }, 'NavBarRight') diff --git a/app/assets/javascripts/app/controllers/calendar.coffee b/app/assets/javascripts/app/controllers/calendar.coffee index 46e979380..fc2006757 100644 --- a/app/assets/javascripts/app/controllers/calendar.coffee +++ b/app/assets/javascripts/app/controllers/calendar.coffee @@ -1,4 +1,5 @@ class Index extends App.ControllerContent + requiredPermission: 'admin.calendar' events: 'click .js-new': 'new' 'click .js-edit': 'edit' @@ -8,10 +9,6 @@ class Index extends App.ControllerContent constructor: -> super - - # check authentication - return if !@authenticate(false, 'Admin') - @subscribeId = App.Calendar.subscribe(@render) callback = (data) => @@ -127,4 +124,4 @@ class Index extends App.ControllerContent container: @el.closest('.content') ) -App.Config.set( 'Calendars', { prio: 2400, name: 'Calendars', parent: '#manage', target: '#manage/calendars', controller: Index, role: ['Admin'] }, 'NavBarAdmin' ) \ No newline at end of file +App.Config.set('Calendars', { prio: 2400, name: 'Calendars', parent: '#manage', target: '#manage/calendars', controller: Index, permission: ['admin.calendar'] }, 'NavBarAdmin') diff --git a/app/assets/javascripts/app/controllers/chat.coffee b/app/assets/javascripts/app/controllers/chat.coffee index 0f1077776..ec8efae01 100644 --- a/app/assets/javascripts/app/controllers/chat.coffee +++ b/app/assets/javascripts/app/controllers/chat.coffee @@ -61,7 +61,7 @@ class App.CustomerChat extends App.Controller # rerender view, e. g. on langauge change @bind('ui:rerender chat:rerender', => - return if !@authenticate(true) + return if !@authenticateCheck() for session_id, chat of @chatWindows chat.el.remove() @chatWindows = {} @@ -90,7 +90,7 @@ class App.CustomerChat extends App.Controller false render: -> - if !@isRole('Chat') + if !@permissionCheck('chat.agent') @renderScreenUnauthorized(objectName: 'Chat') return if !@Config.get('chat') @@ -319,12 +319,10 @@ class App.CustomerChat extends App.Controller @idleTimeoutId = undefined class CustomerChatRouter extends App.ControllerPermanent + requiredPermission: 'chat.agent' constructor: (params) -> super - # check authentication - return if !@authenticate(false, 'Chat') - App.TaskManager.execute( key: 'CustomerChat' controller: 'CustomerChat' @@ -771,6 +769,6 @@ class Setting extends App.ControllerModal msg: App.i18n.translateContent(data.message) ) -App.Config.set( 'customer_chat', CustomerChatRouter, 'Routes' ) -App.Config.set( 'CustomerChat', { controller: 'CustomerChat', authentication: true }, 'permanentTask' ) -App.Config.set( 'CustomerChat', { prio: 1200, parent: '', name: 'Customer Chat', target: '#customer_chat', key: 'CustomerChat', shown: false, role: ['Chat'], class: 'chat' }, 'NavBar' ) +App.Config.set('customer_chat', CustomerChatRouter, 'Routes') +App.Config.set('CustomerChat', { controller: 'CustomerChat', authentication: true }, 'permanentTask') +App.Config.set('CustomerChat', { prio: 1200, parent: '', name: 'Customer Chat', target: '#customer_chat', key: 'CustomerChat', shown: false, permission: ['chat.agent'], class: 'chat' }, 'NavBar') diff --git a/app/assets/javascripts/app/controllers/cti.coffee b/app/assets/javascripts/app/controllers/cti.coffee index 00c672cd8..cfea89af1 100644 --- a/app/assets/javascripts/app/controllers/cti.coffee +++ b/app/assets/javascripts/app/controllers/cti.coffee @@ -5,8 +5,6 @@ class App.CTI extends App.Controller constructor: -> super - return if !@isRole('CTI') - @list = [] @backends = [] @meta = @@ -84,11 +82,12 @@ class App.CTI extends App.Controller title: title ) - featureActive: -> - true + featureActive: => + return true if @Config.get('sipgate_integration') + false render: -> - if !@isRole('CTI') + if !@permissionCheck('cti.agent') @renderScreenUnauthorized(objectName: 'CTI') return @@ -100,7 +99,7 @@ class App.CTI extends App.Controller if !backendEnabled @html App.view('cti/not_configured')( backends: @backends - isAdmin: @isRole('Admin') + isAdmin: @permissionCheck('admin.integration') ) @updateNavMenu() return @@ -193,12 +192,10 @@ class App.CTI extends App.Controller ) class CTIRouter extends App.ControllerPermanent + requiredPermission: 'cti.agent' constructor: (params) -> super - # check authentication - return if !@authenticate(false, 'CTI') - App.TaskManager.execute( key: 'CTI' controller: 'CTI' @@ -209,4 +206,4 @@ class CTIRouter extends App.ControllerPermanent App.Config.set('cti', CTIRouter, 'Routes') App.Config.set('CTI', { controller: 'CTI', authentication: true }, 'permanentTask') -App.Config.set('CTI', { prio: 1300, parent: '', name: 'Phone', target: '#cti', key: 'CTI', shown: false, role: ['CTI'], class: 'phone' }, 'NavBar') +App.Config.set('CTI', { prio: 1300, parent: '', name: 'Phone', target: '#cti', key: 'CTI', shown: false, permission: ['cti.agent'], class: 'phone' }, 'NavBar') diff --git a/app/assets/javascripts/app/controllers/customer_ticket_create.coffee b/app/assets/javascripts/app/controllers/customer_ticket_create.coffee index 232199803..b47b3da7e 100644 --- a/app/assets/javascripts/app/controllers/customer_ticket_create.coffee +++ b/app/assets/javascripts/app/controllers/customer_ticket_create.coffee @@ -1,4 +1,5 @@ class Index extends App.ControllerContent + requiredPermission: 'ticket.customer' events: 'submit form': 'submit', 'click .submit': 'submit', @@ -7,9 +8,6 @@ class Index extends App.ControllerContent constructor: (params) -> super - # check authentication - return if !@authenticate(false, 'Customer') - # set title @title 'New Ticket' @form_id = App.ControllerForm.formId() @@ -184,5 +182,5 @@ class Index extends App.ControllerContent ui.formEnable(e) ) -App.Config.set( 'customer_ticket_new', Index, 'Routes' ) -App.Config.set( 'CustomerTicketNew', { prio: 8003, parent: '#new', name: 'New Ticket', translate: true, target: '#customer_ticket_new', role: ['Customer'], divider: true }, 'NavBarRight' ) +App.Config.set('customer_ticket_new', Index, 'Routes') +App.Config.set('CustomerTicketNew', { prio: 8003, parent: '#new', name: 'New Ticket', translate: true, target: '#customer_ticket_new', permission: ['ticket.customer'], divider: true }, 'NavBarRight') diff --git a/app/assets/javascripts/app/controllers/dashboard.coffee b/app/assets/javascripts/app/controllers/dashboard.coffee index 66977ba5a..67e97464d 100644 --- a/app/assets/javascripts/app/controllers/dashboard.coffee +++ b/app/assets/javascripts/app/controllers/dashboard.coffee @@ -7,7 +7,7 @@ class App.Dashboard extends App.Controller constructor: -> super - if @isRole('Customer') + if @permissionCheck('ticket.customer') @clueAccess = false return @@ -16,7 +16,7 @@ class App.Dashboard extends App.Controller # rerender view, e. g. on language change @bind 'ui:rerender', => - return if !@authenticate(true) + return if !@authenticateCheck() @render() @mayBeClues() @@ -25,7 +25,7 @@ class App.Dashboard extends App.Controller localEl = $( App.view('dashboard')( head: 'Dashboard' - isAdmin: @isRole('Admin') + isAdmin: @permissionCheck('admin') ) ) new App.DashboardStats( @@ -69,7 +69,7 @@ class App.Dashboard extends App.Controller show: (params) => - if @isRole('Customer') + if @permissionCheck('ticket.customer') @navigate '#', true return @@ -97,7 +97,7 @@ class DashboardRouter extends App.ControllerPermanent super # check authentication - return if !@authenticate() + @authenticateCheckRedirect() App.TaskManager.execute( key: 'Dashboard' @@ -108,5 +108,5 @@ class DashboardRouter extends App.ControllerPermanent ) App.Config.set('dashboard', DashboardRouter, 'Routes') -App.Config.set('Dashboard', { prio: 100, parent: '', name: 'Dashboard', target: '#dashboard', key: 'Dashboard', role: ['Agent'], class: 'dashboard' }, 'NavBar') +App.Config.set('Dashboard', { prio: 100, parent: '', name: 'Dashboard', target: '#dashboard', key: 'Dashboard', permission: ['ticket.agent'], class: 'dashboard' }, 'NavBar') App.Config.set('Dashboard', { controller: 'Dashboard', authentication: true }, 'permanentTask') diff --git a/app/assets/javascripts/app/controllers/default_route.coffee b/app/assets/javascripts/app/controllers/default_route.coffee index 23d57eedc..faeb3877f 100644 --- a/app/assets/javascripts/app/controllers/default_route.coffee +++ b/app/assets/javascripts/app/controllers/default_route.coffee @@ -18,7 +18,7 @@ class DefaultRouter extends App.Controller return # check role - if @isRole('Customer') + if @permissionCheck('ticket.customer') @navigate '#ticket/view/my_tickets', true return diff --git a/app/assets/javascripts/app/controllers/email_verify.coffee b/app/assets/javascripts/app/controllers/email_verify.coffee index 4e8c60f6e..a7b1946db 100644 --- a/app/assets/javascripts/app/controllers/email_verify.coffee +++ b/app/assets/javascripts/app/controllers/email_verify.coffee @@ -1,14 +1,14 @@ class Index extends App.Controller constructor: -> super - return if !@authenticate() + @authenticateCheckRedirect() @verifyCall() verifyCall: => @ajax( id: 'email_verify' type: 'POST' - url: @apiPath + '/users/email_verify' + url: "#{@apiPath}/users/email_verify" data: JSON.stringify(token: @token) processData: true success: @success diff --git a/app/assets/javascripts/app/controllers/getting_started.coffee b/app/assets/javascripts/app/controllers/getting_started.coffee index 38dc7ddad..76909cda7 100644 --- a/app/assets/javascripts/app/controllers/getting_started.coffee +++ b/app/assets/javascripts/app/controllers/getting_started.coffee @@ -2,7 +2,7 @@ class Index extends App.WizardFullScreen constructor: -> super - if @authenticate(true, 'Admin') + if !@permissionCheck('admin.wizard') @navigate '#' return @@ -63,7 +63,7 @@ class AutoWizard extends App.WizardFullScreen super # if already logged in, got to # - if @authenticate(true, 'Admin') + if !@permissionCheck('admin.wizard') @navigate '#' return @@ -139,7 +139,7 @@ class Admin extends App.WizardFullScreen constructor: -> super - if @authenticate(true, 'Admin') + if !@permissionCheck('admin.wizard') @navigate '#' return @@ -257,7 +257,7 @@ class Base extends App.WizardFullScreen super # redirect if we are not admin - if !@authenticate(true, 'Admin') + if !@permissionCheck('admin.wizard') @navigate '#' return @@ -389,7 +389,7 @@ class EmailNotification extends App.WizardFullScreen super # redirect if we are not admin - if !@authenticate(true, 'Admin') + if !@permissionCheck('admin.wizard') @navigate '#' return @@ -504,7 +504,7 @@ class Channel extends App.WizardFullScreen super # redirect if we are not admin - if !@authenticate(true, 'Admin') + if !@permissionCheck('admin.wizard') @navigate '#' return @@ -555,7 +555,7 @@ class ChannelEmailPreConfigured extends App.WizardFullScreen super # redirect if we are not admin - if !@authenticate(true, 'Admin') + if !@permissionCheck('admin.wizard') @navigate '#' return @@ -605,7 +605,7 @@ class ChannelEmail extends App.WizardFullScreen super # redirect if we are not admin - if !@authenticate(true, 'Admin') + if !@permissionCheck('admin.wizard') @navigate '#' return @@ -890,12 +890,10 @@ class Agent extends App.WizardFullScreen constructor: -> super - - return if !@authenticate() + @authenticateCheckRedirect() # set title @title 'Invite Agents' - @fetch() release: => @@ -986,12 +984,10 @@ App.Config.set('getting_started/agents', Agent, 'Routes') class Channel extends App.WizardFullScreen constructor: -> super - - return if !@authenticate() + @authenticateCheckRedirect() # set title @title 'Setup Finished' - @render() release: => diff --git a/app/assets/javascripts/app/controllers/groups.coffee b/app/assets/javascripts/app/controllers/groups.coffee index 897d2c503..49737e87f 100644 --- a/app/assets/javascripts/app/controllers/groups.coffee +++ b/app/assets/javascripts/app/controllers/groups.coffee @@ -1,10 +1,8 @@ class Index extends App.ControllerContent + requiredPermission: 'admin.group' constructor: -> super - # check authentication - return if !@authenticate(false, 'Admin') - new App.ControllerGenericIndex( el: @el id: @id @@ -19,9 +17,9 @@ class Index extends App.ControllerContent 'Groups are ...' ] buttons: [ - { name: 'New Group', 'data-type': 'new', class: 'btn--success' }, + { name: 'New Group', 'data-type': 'new', class: 'btn--success' } ] container: @el.closest('.content') ) -App.Config.set( 'Group', { prio: 1500, name: 'Groups', parent: '#manage', target: '#manage/groups', controller: Index, role: ['Admin'] }, 'NavBarAdmin' ) \ No newline at end of file +App.Config.set('Group', { prio: 1500, name: 'Groups', parent: '#manage', target: '#manage/groups', controller: Index, permission: ['admin.group'] }, 'NavBarAdmin') diff --git a/app/assets/javascripts/app/controllers/integrations.coffee b/app/assets/javascripts/app/controllers/integrations.coffee index 57570bf1c..a650e85c4 100644 --- a/app/assets/javascripts/app/controllers/integrations.coffee +++ b/app/assets/javascripts/app/controllers/integrations.coffee @@ -1,10 +1,8 @@ class Index extends App.ControllerContent + requiredPermission: 'admin.integration' constructor: -> super - # check authentication - return if !@authenticate(false, 'Admin') - @title 'Integrations', true @integrationItems = App.Config.get('NavBarIntegrations') @@ -38,4 +36,4 @@ class Index extends App.ControllerContent if @subscribeId App.Setting.unsubscribe(@subscribeId) -App.Config.set('Integration', { prio: 1000, name: 'Integrations', parent: '#system', target: '#system/integration', controller: Index, role: ['Admin'] }, 'NavBarAdmin') +App.Config.set('Integration', { prio: 1000, name: 'Integrations', parent: '#system', target: '#system/integration', controller: Index, permission: ['admin.integration'] }, 'NavBarAdmin') diff --git a/app/assets/javascripts/app/controllers/job.coffee b/app/assets/javascripts/app/controllers/job.coffee index a7fff60bf..3d56bb87f 100644 --- a/app/assets/javascripts/app/controllers/job.coffee +++ b/app/assets/javascripts/app/controllers/job.coffee @@ -1,10 +1,8 @@ class Index extends App.ControllerContent + requiredPermission: 'admin.scheduler' constructor: -> super - # check authentication - return if !@authenticate(false, 'Admin') - new App.ControllerGenericIndex( el: @el id: @id @@ -26,4 +24,4 @@ class Index extends App.ControllerContent large: true ) -App.Config.set('Job', { prio: 3400, name: 'Scheduler', parent: '#manage', target: '#manage/job', controller: Index, role: ['Admin'] }, 'NavBarAdmin') +App.Config.set('Job', { prio: 3400, name: 'Scheduler', parent: '#manage', target: '#manage/job', controller: Index, permission: ['admin.scheduler'] }, 'NavBarAdmin') diff --git a/app/assets/javascripts/app/controllers/keyboard_shortcurs.coffee b/app/assets/javascripts/app/controllers/keyboard_shortcurs.coffee index 44e34a68a..53d6b295d 100644 --- a/app/assets/javascripts/app/controllers/keyboard_shortcurs.coffee +++ b/app/assets/javascripts/app/controllers/keyboard_shortcurs.coffee @@ -3,4 +3,4 @@ class Index new App.KeyboardShortcutModal() App.Config.set('keyboard_shortcuts', Index, 'Routes') -App.Config.set('KeyboardShortcuts', { prio: 1700, parent: '#current_user', name: 'Keyboard Shortcuts', translate: true, target: '#keyboard_shortcuts', role: [ 'Admin', 'Agent' ] }, 'NavBarRight') +App.Config.set('KeyboardShortcuts', { prio: 1700, parent: '#current_user', name: 'Keyboard Shortcuts', translate: true, target: '#keyboard_shortcuts', permission: ['admin', 'ticket.agent'] }, 'NavBarRight') diff --git a/app/assets/javascripts/app/controllers/layout_ref.coffee b/app/assets/javascripts/app/controllers/layout_ref.coffee index 794d8a196..ba262572d 100644 --- a/app/assets/javascripts/app/controllers/layout_ref.coffee +++ b/app/assets/javascripts/app/controllers/layout_ref.coffee @@ -1897,7 +1897,7 @@ class CustomerChatRef extends App.Controller # super # # check authentication -# return if !@authenticate() +# @authenticateCheckRedirect() # App.TaskManager.execute( # key: 'CustomerChatRef' @@ -2226,7 +2226,5 @@ class ChatToTicketRef extends App.ControllerContent y1: y1 y2: y1 + @attachments.outerHeight() -App.Config.set( 'layout_ref/chat_to_ticket', ChatToTicketRef, 'Routes' ) - - -App.Config.set( 'LayoutRef', { prio: 1600, parent: '#current_user', name: 'Layout Reference', translate: true, target: '#layout_ref', role: [ 'Admin' ] }, 'NavBarRight' ) \ No newline at end of file +App.Config.set('layout_ref/chat_to_ticket', ChatToTicketRef, 'Routes') +App.Config.set('LayoutRef', { prio: 1600, parent: '#current_user', name: 'Layout Reference', translate: true, target: '#layout_ref', permission: [ 'admin' ] }, 'NavBarRight') diff --git a/app/assets/javascripts/app/controllers/macro.coffee b/app/assets/javascripts/app/controllers/macro.coffee index 6f17216d8..122766445 100644 --- a/app/assets/javascripts/app/controllers/macro.coffee +++ b/app/assets/javascripts/app/controllers/macro.coffee @@ -1,10 +1,8 @@ class Index extends App.ControllerContent + requiredPermission: 'admin.macro' constructor: -> super - # check authentication - return if !@authenticate(false, 'Admin') - new App.ControllerGenericIndex( el: @el id: @id @@ -24,4 +22,4 @@ class Index extends App.ControllerContent container: @el.closest('.content') ) -App.Config.set( 'Macros', { prio: 2310, name: 'Macros', parent: '#manage', target: '#manage/macros', controller: Index, role: ['Admin'] }, 'NavBarAdmin' ) \ No newline at end of file +App.Config.set('Macros', { prio: 2310, name: 'Macros', parent: '#manage', target: '#manage/macros', controller: Index, permission: ['admin.macro'] }, 'NavBarAdmin') diff --git a/app/assets/javascripts/app/controllers/maintenance.coffee b/app/assets/javascripts/app/controllers/maintenance.coffee index 666be1929..b85117d3b 100644 --- a/app/assets/javascripts/app/controllers/maintenance.coffee +++ b/app/assets/javascripts/app/controllers/maintenance.coffee @@ -1,4 +1,5 @@ class Index extends App.ControllerContent + requiredPermission: 'admin.maintenance' events: 'change .js-modeSetting input': 'setMode' 'change .js-loginSetting input': 'setLogin' @@ -12,9 +13,6 @@ class Index extends App.ControllerContent constructor: -> super - # check authentication - return if !@authenticate(false, 'Admin') - @title 'Maintenance', true @subscribeId = App.Setting.subscribe(@render, initFetch: true, clear: false) @@ -76,4 +74,4 @@ class Index extends App.ControllerContent removeAll: true @render() -App.Config.set('Maintenance', { prio: 3600, name: 'Maintenance', parent: '#system', target: '#system/maintenance', controller: Index, role: ['Admin'] }, 'NavBarAdmin') +App.Config.set('Maintenance', { prio: 3600, name: 'Maintenance', parent: '#system', target: '#system/maintenance', controller: Index, permission: ['admin.maintenance'] }, 'NavBarAdmin') diff --git a/app/assets/javascripts/app/controllers/navigation.coffee b/app/assets/javascripts/app/controllers/navigation.coffee index 5dd035888..d951aab98 100644 --- a/app/assets/javascripts/app/controllers/navigation.coffee +++ b/app/assets/javascripts/app/controllers/navigation.coffee @@ -72,7 +72,7 @@ class App.Navigation extends App.ControllerWidgetPermanent @notificationWidget = undefined renderMenu: => - items = @getItems( navbar: @Config.get('NavBar') ) + items = @getItems(navbar: @Config.get('NavBar')) # apply counter and switch info from persistant controllers (if exists) activeTab = {} @@ -124,7 +124,7 @@ class App.Navigation extends App.ControllerWidgetPermanent renderPersonal: => @recentViewNavbarItemsRebuild() - items = @getItems( navbar: @Config.get( 'NavBarRight' ) ) + items = @getItems(navbar: @Config.get('NavBarRight')) # get open tabs to repopen on rerender open_tab = {} @@ -305,7 +305,9 @@ class App.Navigation extends App.ControllerWidgetPermanent level1 = [] dropdown = {} - roles = App.Session.get('roles') + user = undefined + if App.Session.get('id') + user = App.User.find(App.Session.get('id')) for item in navbar if typeof item.callback is 'function' @@ -313,16 +315,12 @@ class App.Navigation extends App.ControllerWidgetPermanent for key, value of data item[key] = value if !item.parent - match = 0 - if !item.role - match = 1 - if !roles && item.role - match = _.include(item.role, 'Anybody') - if roles - for role in roles - if !match - match = _.include(item.role, role.name) - + match = true + if item.permission + match = false + for permissionName in item.permission + if !match && user && user.permission(permissionName) + match = true if match level1.push item @@ -333,16 +331,12 @@ class App.Navigation extends App.ControllerWidgetPermanent # find all childs and order for itemSub in navbar if itemSub.parent is item.parent - match = 0 - if !itemSub.role - match = 1 - if !roles - match = _.include(itemSub.role, 'Anybody') - if roles - for role in roles - if !match - match = _.include(itemSub.role, role.name) - + match = true + if itemSub.permission + match = false + for permissionName in itemSub.permission + if !match && user && user.permission(permissionName) + match = true if match dropdown[ item.parent ].push itemSub diff --git a/app/assets/javascripts/app/controllers/object_manager.coffee b/app/assets/javascripts/app/controllers/object_manager.coffee index 88927a093..9ea95dba8 100644 --- a/app/assets/javascripts/app/controllers/object_manager.coffee +++ b/app/assets/javascripts/app/controllers/object_manager.coffee @@ -1,12 +1,10 @@ # coffeelint: disable=duplicate_key class Index extends App.ControllerTabs + requiredPermission: 'admin.object' header: 'Object Manager' constructor: -> super - # check authentication - return if !@authenticate(false, 'Admin') - @title 'Objects', true # get data @@ -44,10 +42,6 @@ class Items extends App.ControllerContent constructor: -> super - - # check authentication - return if !@authenticate() - @subscribeId = App.ObjectManagerAttribute.subscribe(@render) App.ObjectManagerAttribute.fetch() @@ -225,4 +219,4 @@ class Edit extends App.ControllerGenericEdit ui.controller.showAlert(details.error_human || details.error || 'Unable to update object!') ) -App.Config.set( 'SystemObject', { prio: 1700, parent: '#system', name: 'Objects', target: '#system/object_manager', controller: Index, role: ['Admin'] }, 'NavBarAdmin' ) +App.Config.set('SystemObject', { prio: 1700, parent: '#system', name: 'Objects', target: '#system/object_manager', controller: Index, permission: ['admin.object'] }, 'NavBarAdmin') diff --git a/app/assets/javascripts/app/controllers/organization_profile.coffee b/app/assets/javascripts/app/controllers/organization_profile.coffee index 2c4f25f15..4f313a166 100644 --- a/app/assets/javascripts/app/controllers/organization_profile.coffee +++ b/app/assets/javascripts/app/controllers/organization_profile.coffee @@ -2,10 +2,7 @@ class App.OrganizationProfile extends App.Controller constructor: (params) -> super - # check authentication - if !@authenticate() - App.TaskManager.remove(@task_key) - return + @authenticateCheckRedirect(true) # fetch new data if needed App.Organization.full(@organization_id, @render) @@ -194,6 +191,7 @@ class Member extends App.ObserverController ) class Router extends App.ControllerPermanent + requiredPermission: 'ticket.agent' constructor: (params) -> super @@ -202,7 +200,7 @@ class Router extends App.ControllerPermanent organization_id: params.organization_id App.TaskManager.execute( - key: 'Organization-' + @organization_id + key: "Organization-#{@organization_id}" controller: 'OrganizationProfile' params: clean_params show: true diff --git a/app/assets/javascripts/app/controllers/organizations.coffee b/app/assets/javascripts/app/controllers/organizations.coffee index 81975f653..0942363f8 100644 --- a/app/assets/javascripts/app/controllers/organizations.coffee +++ b/app/assets/javascripts/app/controllers/organizations.coffee @@ -1,10 +1,8 @@ class Index extends App.ControllerContent + requiredPermission: 'admin.organization' constructor: -> super - # check authentication - return if !@authenticate() - new App.ControllerGenericIndex( el: @el id: @id @@ -24,4 +22,4 @@ class Index extends App.ControllerContent container: @el.closest('.content') ) -App.Config.set( 'Organization', { prio: 2000, name: 'Organizations', parent: '#manage', target: '#manage/organizations', controller: Index, role: ['Admin'] }, 'NavBarAdmin' ) \ No newline at end of file +App.Config.set('Organization', { prio: 2000, name: 'Organizations', parent: '#manage', target: '#manage/organizations', controller: Index, permission: ['admin.organization'] }, 'NavBarAdmin') diff --git a/app/assets/javascripts/app/controllers/overview.coffee b/app/assets/javascripts/app/controllers/overview.coffee index 37cd09cf9..ce4c31182 100644 --- a/app/assets/javascripts/app/controllers/overview.coffee +++ b/app/assets/javascripts/app/controllers/overview.coffee @@ -1,10 +1,8 @@ class Index extends App.ControllerContent + requiredPermission: 'admin.overview' constructor: -> super - # check authentication - return if !@authenticate(false, 'Admin') - new App.ControllerGenericIndex( el: @el id: @id @@ -38,4 +36,4 @@ class Index extends App.ControllerContent overview.save() ) -App.Config.set( 'Overview', { prio: 2300, name: 'Overviews', parent: '#manage', target: '#manage/overviews', controller: Index, role: ['Admin'] }, 'NavBarAdmin' ) \ No newline at end of file +App.Config.set('Overview', { prio: 2300, name: 'Overviews', parent: '#manage', target: '#manage/overviews', controller: Index, permission: ['admin.overview'] }, 'NavBarAdmin') diff --git a/app/assets/javascripts/app/controllers/package.coffee b/app/assets/javascripts/app/controllers/package.coffee index bfc6074f0..650f06683 100644 --- a/app/assets/javascripts/app/controllers/package.coffee +++ b/app/assets/javascripts/app/controllers/package.coffee @@ -1,15 +1,11 @@ class Index extends App.ControllerContent + requiredPermission: 'admin.package' events: 'click .action': 'action' constructor: -> super - - # check authentication - return if !@authenticate(false, 'Admin') - @title 'Packages', true - @load() load: -> @@ -58,4 +54,4 @@ class Index extends App.ControllerContent @load() ) -App.Config.set('Packages', { prio: 3600, name: 'Packages', parent: '#system', target: '#system/package', controller: Index, role: ['Admin'] }, 'NavBarAdmin') +App.Config.set('Packages', { prio: 3600, name: 'Packages', parent: '#system', target: '#system/package', controller: Index, permission: ['admin.package'] }, 'NavBarAdmin') diff --git a/app/assets/javascripts/app/controllers/password_reset.coffee b/app/assets/javascripts/app/controllers/password_reset.coffee index 8373c1d75..eb11c33ff 100644 --- a/app/assets/javascripts/app/controllers/password_reset.coffee +++ b/app/assets/javascripts/app/controllers/password_reset.coffee @@ -13,9 +13,7 @@ class Index extends App.ControllerContent return # if we are logged in, no passwort reset is wanted, redirect to app - if @authenticate(true) - @navigate '#' - return + @authenticateCheckRedirect() @navHide() @@ -27,7 +25,7 @@ class Index extends App.ControllerContent render: (params) -> configure_attributes = [ - { name: 'username', display: 'Enter your username or email address', tag: 'input', type: 'text', limit: 100, null: false, class: 'input span4', }, + { name: 'username', display: 'Enter your username or email address', tag: 'input', type: 'text', limit: 100, null: false, class: 'input span4' } ] @html App.view('password/reset')(params) @@ -51,7 +49,7 @@ class Index extends App.ControllerContent @ajax( id: 'password_reset' type: 'POST' - url: @apiPath + '/users/password_reset' + url: "#{@apiPath}/users/password_reset" data: JSON.stringify(params) processData: true success: @success @@ -71,7 +69,7 @@ class Index extends App.ControllerContent @$('[name=username]').val('') @notify( type: 'error' - msg: App.i18n.translateContent( 'Username or email address invalid, please try again.' ) + msg: App.i18n.translateContent('Username or email address invalid, please try again.') ) @formEnable( @el.find('.form-password') ) @@ -86,9 +84,7 @@ class Verify extends App.ControllerContent super # if we are logged in, no passwort reset is wanted, redirect to app - if @authenticate(true) - @navigate '#' - return + @authenticateCheckRedirect() @navHide() @@ -102,7 +98,7 @@ class Verify extends App.ControllerContent @ajax( id: 'password_reset_verify' type: 'POST' - url: @apiPath + '/users/password_reset_verify' + url: "#{@apiPath}/users/password_reset_verify" data: JSON.stringify(params) processData: true success: @renderChange @@ -111,7 +107,7 @@ class Verify extends App.ControllerContent renderChange: (data) => if data.message is 'ok' configure_attributes = [ - { name: 'password', display: 'Password', tag: 'input', type: 'password', limit: 100, null: false, class: 'input', }, + { name: 'password', display: 'Password', tag: 'input', type: 'password', limit: 100, null: false, class: 'input' } ] @html App.view('password/reset_change')() @@ -158,7 +154,7 @@ class Verify extends App.ControllerContent @ajax( id: 'password_reset_verify' type: 'POST' - url: @apiPath + '/users/password_reset_verify' + url: "#{@apiPath}/users/password_reset_verify" data: JSON.stringify(params) processData: true success: @renderChanged diff --git a/app/assets/javascripts/app/controllers/profile.coffee b/app/assets/javascripts/app/controllers/profile.coffee index a4b4c8938..afec160b6 100644 --- a/app/assets/javascripts/app/controllers/profile.coffee +++ b/app/assets/javascripts/app/controllers/profile.coffee @@ -2,9 +2,8 @@ class Index extends App.ControllerNavSidbar authenticateRequired: true configKey: 'NavBarProfile' -App.Config.set( 'profile', Index, 'Routes' ) -App.Config.set( 'profile/:target', Index, 'Routes' ) +App.Config.set('profile', Index, 'Routes') +App.Config.set('profile/:target', Index, 'Routes') -App.Config.set( 'Profile', { prio: 1000, name: 'Profile', target: '#profile' }, 'NavBarProfile' ) - -App.Config.set( 'Profile', { prio: 1700, parent: '#current_user', name: 'Profile', target: '#profile', translate: true, role: [ 'Agent', 'Customer' ] }, 'NavBarRight' ) +App.Config.set('Profile', { prio: 1000, name: 'Profile', target: '#profile' }, 'NavBarProfile') +App.Config.set('Profile', { prio: 1700, parent: '#current_user', name: 'Profile', target: '#profile', translate: true }, 'NavBarRight') diff --git a/app/assets/javascripts/app/controllers/report.js.coffee b/app/assets/javascripts/app/controllers/report.js.coffee index fc65afbd3..2fc5d7c96 100644 --- a/app/assets/javascripts/app/controllers/report.js.coffee +++ b/app/assets/javascripts/app/controllers/report.js.coffee @@ -1,17 +1,15 @@ class Index extends App.ControllerContent + requiredPermission: 'report' + constructor: -> super - - # check authentication - return if !@authenticate() - @title 'Reporting' @navupdate '#report' @startLoading() @ajax( - type: 'GET', - url: @apiPath + '/reports/config', - processData: true, + type: 'GET' + url: "#{@apiPath}/reports/config" + processData: true success: (data) => @stopLoading() @config = data.config @@ -131,7 +129,7 @@ class Graph extends App.ControllerContent ui: @ui ) - url = @apiPath + '/reports/generate' + url = "#{@apiPath}/reports/generate" interval = 5 * 60000 if @params.timeRange is 'year' interval = 5 * 60000 @@ -519,4 +517,4 @@ class Sidebar extends App.Controller @ui.storeParams() App.Config.set('report', Index, 'Routes') -App.Config.set('Reporting', { prio: 8000, parent: '', name: 'Reporing', translate: true, target: '#report', icon: 'report', role: ['Report'] }, 'NavBarRight') +App.Config.set('Reporting', { prio: 8000, parent: '', name: 'Reporing', translate: true, target: '#report', icon: 'report', permission: ['report'] }, 'NavBarRight') diff --git a/app/assets/javascripts/app/controllers/report_profile.js.coffee b/app/assets/javascripts/app/controllers/report_profile.js.coffee index aa00ec31f..e250b60b4 100644 --- a/app/assets/javascripts/app/controllers/report_profile.js.coffee +++ b/app/assets/javascripts/app/controllers/report_profile.js.coffee @@ -1,10 +1,8 @@ class Index extends App.ControllerContent + requiredPermission: 'admin.report_profile' constructor: -> super - # check authentication - return if !@authenticate() - new App.ControllerGenericIndex( el: @el id: @id @@ -24,4 +22,4 @@ class Index extends App.ControllerContent container: @el.closest('.content') ) -App.Config.set( 'ReportProfile', { prio: 8000, name: 'Report Profiles', parent: '#manage', target: '#manage/report_profiles', controller: Index, role: ['Admin'] }, 'NavBarAdmin' ) +App.Config.set('ReportProfile', { prio: 8000, name: 'Report Profiles', parent: '#manage', target: '#manage/report_profiles', controller: Index, permission: ['admin.report_profile'] }, 'NavBarAdmin') diff --git a/app/assets/javascripts/app/controllers/search.coffee b/app/assets/javascripts/app/controllers/search.coffee index 4908bad2e..a93bad33a 100644 --- a/app/assets/javascripts/app/controllers/search.coffee +++ b/app/assets/javascripts/app/controllers/search.coffee @@ -14,9 +14,7 @@ class App.Search extends App.Controller super # check authentication - if !@authenticate(false) - App.TaskManager.remove(@task_key) - return + @authenticateCheckRedirect(true) current = App.TaskManager.get(@task_key).state if current && current.query diff --git a/app/assets/javascripts/app/controllers/session.coffee b/app/assets/javascripts/app/controllers/session.coffee index 479486566..d1e5af483 100644 --- a/app/assets/javascripts/app/controllers/session.coffee +++ b/app/assets/javascripts/app/controllers/session.coffee @@ -1,15 +1,11 @@ class Index extends App.ControllerContent + requiredPermission: 'admin.session' events: 'click .js-delete': 'destroy' constructor: -> super - - # check authentication - return if !@authenticate(false, 'Admin') - @title 'Sessions', true - @load() @interval( => @@ -23,7 +19,7 @@ class Index extends App.ControllerContent @ajax( id: 'sessions' type: 'GET' - url: @apiPath + '/sessions' + url: "#{@apiPath}/sessions" success: (data) => @stopLoading() App.Collection.loadAssets(data.assets) @@ -46,11 +42,11 @@ class Index extends App.ControllerContent e.preventDefault() sessionId = $(e.target ).closest('a').data('session-id') @ajax( - id: 'sessions/' + sessionId + id: "sessions/#{sessionId}" type: 'DELETE' - url: @apiPath + '/sessions/' + sessionId + url: "#{@apiPath}/sessions/#{sessionId}" success: (data) => @load() ) -App.Config.set('Session', { prio: 3800, name: 'Sessions', parent: '#system', target: '#system/sessions', controller: Index, role: ['Admin'] }, 'NavBarAdmin' ) \ No newline at end of file +App.Config.set('Session', { prio: 3800, name: 'Sessions', parent: '#system', target: '#system/sessions', controller: Index, permission: ['admin.session'] }, 'NavBarAdmin' ) diff --git a/app/assets/javascripts/app/controllers/sla.coffee b/app/assets/javascripts/app/controllers/sla.coffee index 8c2e105e0..33a9dc373 100644 --- a/app/assets/javascripts/app/controllers/sla.coffee +++ b/app/assets/javascripts/app/controllers/sla.coffee @@ -1,4 +1,5 @@ class Index extends App.ControllerContent + requiredPermission: 'admin.sla' events: 'click .js-new': 'new' 'click .js-edit': 'edit' @@ -7,10 +8,6 @@ class Index extends App.ControllerContent constructor: -> super - - # check authentication - return if !@authenticate(false, 'Admin') - @subscribeCalendarId = App.Calendar.subscribe(@render) @subscribeSlaId = App.Sla.subscribe(@render) @@ -114,4 +111,4 @@ class Index extends App.ControllerContent "#{hours}:#{minutes}" -App.Config.set( 'Sla', { prio: 2900, name: 'SLAs', parent: '#manage', target: '#manage/slas', controller: Index, role: ['Admin'] }, 'NavBarAdmin' ) \ No newline at end of file +App.Config.set('Sla', { prio: 2900, name: 'SLAs', parent: '#manage', target: '#manage/slas', controller: Index, permission: ['admin.sla'] }, 'NavBarAdmin') diff --git a/app/assets/javascripts/app/controllers/tag.coffee b/app/assets/javascripts/app/controllers/tag.coffee index 7e7696841..1c322ea8f 100644 --- a/app/assets/javascripts/app/controllers/tag.coffee +++ b/app/assets/javascripts/app/controllers/tag.coffee @@ -1,4 +1,5 @@ class Index extends App.ControllerContent + requiredPermission: 'admin.tag' events: 'change .js-newTagSetting input': 'setTagNew' 'submit .js-create': 'create' @@ -8,12 +9,7 @@ class Index extends App.ControllerContent constructor: -> super - - # check authentication - return if !@authenticate(false, 'Admin') - @title 'Tags', true - @subscribeId = App.Setting.subscribe(@render, initFetch: true, clear: false) release: => @@ -154,4 +150,4 @@ class DestroyConfirm extends App.ControllerModal @close() ) -App.Config.set('Tags', { prio: 2320, name: 'Tags', parent: '#manage', target: '#manage/tags', controller: Index, role: ['Admin'] }, 'NavBarAdmin') +App.Config.set('Tags', { prio: 2320, name: 'Tags', parent: '#manage', target: '#manage/tags', controller: Index, permission: ['admin.tag'] }, 'NavBarAdmin') diff --git a/app/assets/javascripts/app/controllers/text_module.coffee b/app/assets/javascripts/app/controllers/text_module.coffee index 22e37abb1..98ecde19f 100644 --- a/app/assets/javascripts/app/controllers/text_module.coffee +++ b/app/assets/javascripts/app/controllers/text_module.coffee @@ -1,10 +1,8 @@ class Index extends App.ControllerContent + requiredPermission: 'admin.text_module' constructor: -> super - # check authentication - return if !@authenticate() - new App.ControllerGenericIndex( el: @el id: @id @@ -24,4 +22,4 @@ class Index extends App.ControllerContent container: @el.closest('.content') ) -App.Config.set( 'TextModule', { prio: 2300, name: 'TextModules', parent: '#manage', target: '#manage/text_modules', controller: Index, role: ['Admin'] }, 'NavBarAdmin' ) \ No newline at end of file +App.Config.set('TextModule', { prio: 2300, name: 'TextModules', parent: '#manage', target: '#manage/text_modules', controller: Index, permission: ['admin.text_module'] }, 'NavBarAdmin') diff --git a/app/assets/javascripts/app/controllers/ticket_overview.coffee b/app/assets/javascripts/app/controllers/ticket_overview.coffee index 532501efe..a86a1f9d7 100644 --- a/app/assets/javascripts/app/controllers/ticket_overview.coffee +++ b/app/assets/javascripts/app/controllers/ticket_overview.coffee @@ -132,7 +132,7 @@ class Navbar extends App.Controller items = App.OverviewIndexCollection.get() @html App.view("agent_ticket_view/navbar#{ if @vertical then '_vertical' }") items: items - isAgent: @isRole('Agent') + isAgent: @permissionCheck('ticket.agent') while @clone.width() > @tabsHolder.width() @tabClone.not('.hide').last().addClass('hide') @@ -203,7 +203,7 @@ class Table extends App.Controller # rerender view, e. g. on langauge change @bind 'ui:rerender', => - return if !@authenticate(true) + return if !@authenticateCheck() @render(App.OverviewListCollection.get(@view)) release: => @@ -237,7 +237,7 @@ class Table extends App.Controller ticket_list_show.push App.Ticket.fullLocal(ticket.id) # if customer and no ticket exists, show the following message only - if !ticket_list_show[0] && @isRole('Customer') + if !ticket_list_show[0] && @permissionCheck('ticket.customer') @html App.view('customer_not_ticket_exists')() return @@ -249,9 +249,9 @@ class Table extends App.Controller # render init page checkbox = true edit = false - if @isRole('Admin') + if @permissionCheck('admin') edit = true - if @isRole('Customer') + if @permissionCheck('ticket.customer') checkbox = false edit = false view_modes = [ @@ -266,7 +266,7 @@ class Table extends App.Controller class: 'active' if @view_mode is 'm' } ] - if @isRole('Customer') + if @permissionCheck('ticket.customer') view_modes = [] html = App.view('agent_ticket_view/content')( overview: @overview @@ -768,12 +768,11 @@ class App.OverviewSettings extends App.ControllerModal ) class TicketOverviewRouter extends App.ControllerPermanent + requiredPermission: ['ticket.agent', 'ticket.customer'] + constructor: (params) -> super - # check authentication - return if !@authenticate() - # cleanup params clean_params = view: params.view @@ -789,4 +788,4 @@ class TicketOverviewRouter extends App.ControllerPermanent App.Config.set('ticket/view', TicketOverviewRouter, 'Routes') App.Config.set('ticket/view/:view', TicketOverviewRouter, 'Routes') App.Config.set('TicketOverview', { controller: 'TicketOverview', authentication: true }, 'permanentTask') -App.Config.set('TicketOverview', { prio: 1000, parent: '', name: 'Overviews', target: '#ticket/view', key: 'TicketOverview', role: ['Agent', 'Customer'], class: 'overviews' }, 'NavBar') +App.Config.set('TicketOverview', { prio: 1000, parent: '', name: 'Overviews', target: '#ticket/view', key: 'TicketOverview', permission: ['ticket.agent', 'ticket.customer'], class: 'overviews' }, 'NavBar') diff --git a/app/assets/javascripts/app/controllers/ticket_zoom.coffee b/app/assets/javascripts/app/controllers/ticket_zoom.coffee index 2f53353e7..ec61ad2b2 100644 --- a/app/assets/javascripts/app/controllers/ticket_zoom.coffee +++ b/app/assets/javascripts/app/controllers/ticket_zoom.coffee @@ -14,9 +14,7 @@ class App.TicketZoom extends App.Controller super # check authentication - if !@authenticate() - App.TaskManager.remove(@task_key) - return + @authenticateCheckRedirect(true) @formMeta = undefined @ticket_id = params.ticket_id @@ -344,7 +342,7 @@ class App.TicketZoom extends App.Controller elLocal = $(App.view('ticket_zoom') ticket: @ticket nav: @nav - isCustomer: @isRole('Customer') + isCustomer: @permissionCheck('ticket.customer') scrollbarWidth: App.Utils.getScrollBarWidth() ) @@ -523,7 +521,7 @@ class App.TicketZoom extends App.Controller internal: 'true' in_reply_to: '' - if @isRole('Customer') + if @permissionCheck('ticket.customer') currentStore.article.internal = '' currentStore @@ -653,7 +651,7 @@ class App.TicketZoom extends App.Controller ticket[attributes[1]] = content.value # set defaults - if !@isRole('Customer') + if !@permissionCheck('ticket.customer') if !ticket['owner_id'] ticket['owner_id'] = 1 @@ -811,6 +809,7 @@ class App.TicketZoom extends App.Controller App.TaskManager.update(@task_key, { 'state': @localTaskData }) class TicketZoomRouter extends App.ControllerPermanent + requiredPermission: ['ticket.agent', 'ticket.customer'] constructor: (params) -> super diff --git a/app/assets/javascripts/app/controllers/ticket_zoom/article_actions.coffee b/app/assets/javascripts/app/controllers/ticket_zoom/article_actions.coffee index de57ef9dd..245799ec0 100644 --- a/app/assets/javascripts/app/controllers/ticket_zoom/article_actions.coffee +++ b/app/assets/javascripts/app/controllers/ticket_zoom/article_actions.coffee @@ -45,7 +45,7 @@ class App.TicketZoomArticleActions extends App.Controller @render() actionRow: (article) -> - if @isRole('Customer') + if @permissionCheck('ticket.customer') return [] actions = [] diff --git a/app/assets/javascripts/app/controllers/ticket_zoom/article_new.coffee b/app/assets/javascripts/app/controllers/ticket_zoom/article_new.coffee index 533ebbd08..20c2e183c 100644 --- a/app/assets/javascripts/app/controllers/ticket_zoom/article_new.coffee +++ b/app/assets/javascripts/app/controllers/ticket_zoom/article_new.coffee @@ -103,7 +103,7 @@ class App.TicketZoomArticleNew extends App.Controller features: ['attachment'] } - if @isRole('Customer') + if @permissionCheck('ticket.customer') @type = 'note' @articleTypes = [ { @@ -177,7 +177,7 @@ class App.TicketZoomArticleNew extends App.Controller articleTypes: @articleTypes article: @defaults form_id: @form_id - isCustomer: @isRole('Customer') + isCustomer: @permissionCheck('ticket.customer') ) @setArticleType(@type) @@ -254,7 +254,7 @@ class App.TicketZoomArticleNew extends App.Controller ) # show text module UI - if !@isRole('Customer') + if !@permissionCheck('ticket.customer') textModule = new App.WidgetTextModule( el: @$('.js-textarea').parent() data: @@ -281,7 +281,7 @@ class App.TicketZoomArticleNew extends App.Controller if !params['internal'] params['internal'] = false - if @isRole('Customer') + if @permissionCheck('ticket.customer') sender = App.TicketArticleSender.findByAttribute('name', 'Customer') type = App.TicketArticleType.findByAttribute('name', 'web') params.type_id = type.id diff --git a/app/assets/javascripts/app/controllers/ticket_zoom/article_view.coffee b/app/assets/javascripts/app/controllers/ticket_zoom/article_view.coffee index 8e967c390..bdab85504 100644 --- a/app/assets/javascripts/app/controllers/ticket_zoom/article_view.coffee +++ b/app/assets/javascripts/app/controllers/ticket_zoom/article_view.coffee @@ -125,7 +125,7 @@ class ArticleViewItem extends App.ObserverController @html App.view('ticket_zoom/article_view_delivery_failed')( ticket: @ticket article: article - isCustomer: @isRole('Customer') + isCustomer: @permissionCheck('ticket.customer') ) return if article.sender.name is 'System' @@ -133,13 +133,13 @@ class ArticleViewItem extends App.ObserverController @html App.view('ticket_zoom/article_view_system')( ticket: @ticket article: article - isCustomer: @isRole('Customer') + isCustomer: @permissionCheck('ticket.customer') ) return @html App.view('ticket_zoom/article_view')( ticket: @ticket article: article - isCustomer: @isRole('Customer') + isCustomer: @permissionCheck('ticket.customer') ) new App.WidgetAvatar( diff --git a/app/assets/javascripts/app/controllers/ticket_zoom/attribute_bar.coffee b/app/assets/javascripts/app/controllers/ticket_zoom/attribute_bar.coffee index c2f2f58af..87b94863a 100644 --- a/app/assets/javascripts/app/controllers/ticket_zoom/attribute_bar.coffee +++ b/app/assets/javascripts/app/controllers/ticket_zoom/attribute_bar.coffee @@ -37,7 +37,7 @@ class App.TicketZoomAttributeBar extends App.Controller macros = App.Macro.all() @macroLastUpdated = App.Macro.lastUpdatedAt() - if _.isEmpty(macros) || !@isRole('Agent') + if _.isEmpty(macros) || !@permissionCheck('ticket.agent') macroDisabled = true localeEl = $(App.view('ticket_zoom/attribute_bar')( diff --git a/app/assets/javascripts/app/controllers/ticket_zoom/higlighter.coffee b/app/assets/javascripts/app/controllers/ticket_zoom/higlighter.coffee index 7cb1ffcd1..5aa77a689 100644 --- a/app/assets/javascripts/app/controllers/ticket_zoom/higlighter.coffee +++ b/app/assets/javascripts/app/controllers/ticket_zoom/higlighter.coffee @@ -36,7 +36,7 @@ class App.TicketZoomHighlighter extends App.Controller constructor: -> super - return if !@isRole('Agent') + return if !@permissionCheck('ticket.agent') @currentHighlights = {} @@ -93,7 +93,7 @@ class App.TicketZoomHighlighter extends App.Controller # for testing purposes the highlights get stored in atrticle preferences loadHighlights: (ticket_article_id) -> - return if !@isRole('Agent') + return if !@permissionCheck('ticket.agent') article = App.TicketArticle.find(ticket_article_id) return if !article.preferences return if !article.preferences.highlight diff --git a/app/assets/javascripts/app/controllers/ticket_zoom/meta.coffee b/app/assets/javascripts/app/controllers/ticket_zoom/meta.coffee index b707a1861..a5cab432e 100644 --- a/app/assets/javascripts/app/controllers/ticket_zoom/meta.coffee +++ b/app/assets/javascripts/app/controllers/ticket_zoom/meta.coffee @@ -8,5 +8,5 @@ class App.TicketZoomMeta extends App.ObserverController render: (ticket) => @html App.view('ticket_zoom/meta')( ticket: ticket - isCustomer: @isRole('Customer') + isCustomer: @permissionCheck('ticket.customer') ) diff --git a/app/assets/javascripts/app/controllers/ticket_zoom/sidebar.coffee b/app/assets/javascripts/app/controllers/ticket_zoom/sidebar.coffee index b1d734ed2..745f95859 100644 --- a/app/assets/javascripts/app/controllers/ticket_zoom/sidebar.coffee +++ b/app/assets/javascripts/app/controllers/ticket_zoom/sidebar.coffee @@ -53,7 +53,7 @@ class App.TicketZoomSidebar extends App.ObserverController markForm: @markForm ) - if !@isRole('Customer') + if !@permissionCheck('ticket.customer') @tagWidget = new App.WidgetTag( el: @el.find('.tags') object_type: 'Ticket' @@ -91,7 +91,7 @@ class App.TicketZoomSidebar extends App.ObserverController callback: editTicket } ] - if !@isRole('Customer') + if !@permissionCheck('ticket.customer') @sidebarItems[0]['actions'] = [ { name: 'ticket-history' @@ -109,7 +109,7 @@ class App.TicketZoomSidebar extends App.ObserverController callback: changeCustomer }, ] - if !@isRole('Customer') + if !@permissionCheck('ticket.customer') editCustomer = (e, el) => new App.ControllerGenericEdit( id: ticket.customer_id diff --git a/app/assets/javascripts/app/controllers/translation.coffee b/app/assets/javascripts/app/controllers/translation.coffee index aa0791de7..fe9d0f806 100644 --- a/app/assets/javascripts/app/controllers/translation.coffee +++ b/app/assets/javascripts/app/controllers/translation.coffee @@ -1,4 +1,5 @@ class Index extends App.ControllerContent + requiredPermission: 'admin.translation' events: 'click .js-pushChanges': 'pushChanges' 'click .js-resetChanges': 'resetChanges' @@ -7,9 +8,6 @@ class Index extends App.ControllerContent constructor: -> super - # check authentication - return if !@authenticate(false, 'Admin') - @title 'Translations', true @locale = App.i18n.get() @render() @@ -337,4 +335,4 @@ class TranslationList extends App.Controller reset.addClass('hidden') reset.closest('tr').removeClass('warning') -App.Config.set('Translation', { prio: 1800, parent: '#system', name: 'Translations', target: '#system/translation', controller: Index, role: ['Admin'] }, 'NavBarAdmin' ) +App.Config.set('Translation', { prio: 1800, parent: '#system', name: 'Translations', target: '#system/translation', controller: Index, permission: ['admin.translation'] }, 'NavBarAdmin' ) diff --git a/app/assets/javascripts/app/controllers/trigger.coffee b/app/assets/javascripts/app/controllers/trigger.coffee index b58841385..c8758aeb9 100644 --- a/app/assets/javascripts/app/controllers/trigger.coffee +++ b/app/assets/javascripts/app/controllers/trigger.coffee @@ -1,10 +1,8 @@ class Index extends App.ControllerContent + requiredPermission: 'admin.trigger' constructor: -> super - # check authentication - return if !@authenticate(false, 'Admin') - new App.ControllerGenericIndex( el: @el id: @id @@ -26,4 +24,4 @@ class Index extends App.ControllerContent large: true ) -App.Config.set('Trigger', { prio: 3300, name: 'Trigger', parent: '#manage', target: '#manage/trigger', controller: Index, role: ['Admin'] }, 'NavBarAdmin') +App.Config.set('Trigger', { prio: 3300, name: 'Trigger', parent: '#manage', target: '#manage/trigger', controller: Index, permission: ['admin.trigger'] }, 'NavBarAdmin') diff --git a/app/assets/javascripts/app/controllers/user_profile.coffee b/app/assets/javascripts/app/controllers/user_profile.coffee index 72cffa4df..b509a665e 100644 --- a/app/assets/javascripts/app/controllers/user_profile.coffee +++ b/app/assets/javascripts/app/controllers/user_profile.coffee @@ -3,9 +3,7 @@ class App.UserProfile extends App.Controller super # check authentication - if !@authenticate() - App.TaskManager.remove(@task_key) - return + @authenticateCheckRedirect(true) # fetch new data if needed App.User.full(@user_id, @render) @@ -188,6 +186,7 @@ class Organization extends App.ObserverController ) class Router extends App.ControllerPermanent + requiredPermission: 'ticket.agent' constructor: (params) -> super diff --git a/app/assets/javascripts/app/controllers/users.coffee b/app/assets/javascripts/app/controllers/users.coffee index 9432df550..0746fccd7 100644 --- a/app/assets/javascripts/app/controllers/users.coffee +++ b/app/assets/javascripts/app/controllers/users.coffee @@ -1,4 +1,5 @@ -class Index extends App.Controller +class Index extends App.ControllerContent + requiredPermission: 'admin.user' elements: '.js-search': 'searchInput' events: @@ -7,9 +8,6 @@ class Index extends App.Controller constructor: -> super - # check authentication - return if !@authenticate() - # set title @title 'Users', true @@ -167,7 +165,7 @@ class Index extends App.Controller App.Ajax.request( id: 'search' type: 'GET' - url: @apiPath + '/users/recent' + url: "#{@apiPath}/users/recent" data: limit: 40 role_ids: role_ids @@ -194,4 +192,4 @@ class Index extends App.Controller callback: @recent ) -App.Config.set( 'User', { prio: 1000, name: 'Users', parent: '#manage', target: '#manage/users', controller: Index, role: ['Admin'] }, 'NavBarAdmin' ) \ No newline at end of file +App.Config.set( 'User', { prio: 1000, name: 'Users', parent: '#manage', target: '#manage/users', controller: Index, permission: ['admin.user'] }, 'NavBarAdmin' ) diff --git a/app/assets/javascripts/app/controllers/widget/maintenance.coffee b/app/assets/javascripts/app/controllers/widget/maintenance.coffee index d6b9d47c4..3f1ea0e46 100644 --- a/app/assets/javascripts/app/controllers/widget/maintenance.coffee +++ b/app/assets/javascripts/app/controllers/widget/maintenance.coffee @@ -41,7 +41,7 @@ class Widget extends App.Controller maintanaceMode: (data = {}) => return if data.on isnt true - return if !@authenticate(true) + @authenticateCheckRedirect() @navigate '#logout' #App.Event.trigger('maintenance', {type:'restart_auto'}) diff --git a/app/assets/javascripts/app/controllers/widget/ticket_stats.coffee b/app/assets/javascripts/app/controllers/widget/ticket_stats.coffee index e0f3773f2..98752cd16 100644 --- a/app/assets/javascripts/app/controllers/widget/ticket_stats.coffee +++ b/app/assets/javascripts/app/controllers/widget/ticket_stats.coffee @@ -20,7 +20,7 @@ class App.TicketStats extends App.Controller # rerender view, e. g. on langauge change @bind 'ui:rerender', => - return if !@authenticate(true) + return if !@authenticateCheck() @render() release: => diff --git a/app/assets/javascripts/app/controllers/widget/translation_inline.coffee b/app/assets/javascripts/app/controllers/widget/translation_inline.coffee index 6a3da846a..474871faf 100644 --- a/app/assets/javascripts/app/controllers/widget/translation_inline.coffee +++ b/app/assets/javascripts/app/controllers/widget/translation_inline.coffee @@ -9,7 +9,7 @@ class Widget extends App.Controller $(document).off('keydown.translation') # only admins can do this - return if !@isRole('Admin') + return if !@permissionCheck('admin.translation') # bind on key down # if ctrl+alt+t is pressed, enable translation_inline and fire ui:rerender diff --git a/app/assets/javascripts/app/controllers/widget/translation_support.coffee b/app/assets/javascripts/app/controllers/widget/translation_support.coffee index 3fe212c02..6ee5318e9 100644 --- a/app/assets/javascripts/app/controllers/widget/translation_support.coffee +++ b/app/assets/javascripts/app/controllers/widget/translation_support.coffee @@ -11,7 +11,7 @@ class TranslationSupport extends App.Controller return if !App.i18n.notTranslatedFeatureEnabled(App.i18n.get()) # only show for admins - return if !@isRole('Admin') + return if !@permissionCheck('admin.translation') # do not show in setup screens return if window.location.hash.toString().match(/getting/) diff --git a/app/assets/javascripts/app/models/permission.coffee b/app/assets/javascripts/app/models/permission.coffee new file mode 100644 index 000000000..55fe545b0 --- /dev/null +++ b/app/assets/javascripts/app/models/permission.coffee @@ -0,0 +1,4 @@ +class App.Permission extends App.Model + @configure 'Role', 'name', 'note', 'active', 'updated_at' + @extend Spine.Model.Ajax + @url: @apiPath + '/permissions' diff --git a/app/assets/javascripts/app/models/role.coffee b/app/assets/javascripts/app/models/role.coffee index 0800e15b1..3845e7edb 100644 --- a/app/assets/javascripts/app/models/role.coffee +++ b/app/assets/javascripts/app/models/role.coffee @@ -1,18 +1,20 @@ class App.Role extends App.Model - @configure 'Role', 'name', 'note', 'active', 'updated_at' + @configure 'Role', 'name', 'permission_ids', 'default_at_signup', 'note', 'active', 'updated_at' @extend Spine.Model.Ajax @url: @apiPath + '/roles' @configure_attributes = [ - { name: 'name', display: 'Name', tag: 'input', type: 'text', limit: 100, null: false }, - { name: 'note', display: 'Note', tag: 'textarea', note: 'Notes are visible to agents only, never to customers.', limit: 250, null: true }, - { name: 'active', display: 'Active', tag: 'active', default: true }, - { name: 'created_by_id', display: 'Created by', relation: 'User', readonly: 1 }, - { name: 'created_at', display: 'Created', tag: 'datetime', readonly: 1 }, - { name: 'updated_by_id', display: 'Updated by', relation: 'User', readonly: 1 }, - { name: 'updated_at', display: 'Updated', tag: 'datetime', readonly: 1 }, + { name: 'name', display: 'Name', tag: 'input', type: 'text', limit: 100, null: false }, + { name: 'permission_ids', display: 'Permissions', tag: 'permission', item_class: 'checkbox' }, + { name: 'default_at_signup', display: 'Default at Signup', tag: 'boolean', default: false, translate: true }, + { name: 'note', display: 'Note', tag: 'textarea', note: 'Notes are visible to agents only, never to customers.', limit: 250, null: true }, + { name: 'active', display: 'Active', tag: 'active', default: true }, + { name: 'created_by_id', display: 'Created by', relation: 'User', readonly: 1 }, + { name: 'created_at', display: 'Created', tag: 'datetime', readonly: 1 }, + { name: 'updated_by_id', display: 'Updated by', relation: 'User', readonly: 1 }, + { name: 'updated_at', display: 'Updated', tag: 'datetime', readonly: 1 }, ] @configure_overview = [ - 'name', + 'name', 'default_at_signup', ] activityMessage: (item) -> @@ -21,3 +23,14 @@ class App.Role extends App.Model else if item.type is 'update' return App.i18n.translateContent('%s updated Role |%s|', item.created_by.displayName(), item.title) return "Unknow action for (#{@objectDisplayName()}/#{item.type}), extend activityMessage() of model." + + @_fillUp: (data) -> + + if data['permission_ids'] + data['permissions'] = [] + for permission_id in data['permission_ids'] + if App.Permission.exists(permission_id) + permission = App.Permission.find(permission_id) + data['permissions'].push permission + + data diff --git a/app/assets/javascripts/app/models/user.coffee b/app/assets/javascripts/app/models/user.coffee index 499baf2e6..dbea75fa5 100644 --- a/app/assets/javascripts/app/models/user.coffee +++ b/app/assets/javascripts/app/models/user.coffee @@ -125,25 +125,25 @@ class App.User extends App.Model if data['role_ids'] data['roles'] = [] for role_id in data['role_ids'] - if App.Role.exists( role_id ) - role = App.Role.find( role_id ) + if App.Role.exists(role_id) + role = App.Role.find(role_id) data['roles'].push role if data['group_ids'] data['groups'] = [] for group_id in data['group_ids'] - if App.Group.exists( group_id ) - group = App.Group.find( group_id ) + if App.Group.exists(group_id) + group = App.Group.find(group_id) data['groups'].push group data searchResultAttributes: -> - display: "#{@displayName()}" - id: @id - class: 'user user-popover' - url: @uiUrl() - icon: 'user' + display: "#{@displayName()}" + id: @id + class: 'user user-popover' + url: @uiUrl() + icon: 'user' activityMessage: (item) -> if item.type is 'create' @@ -163,3 +163,50 @@ class App.User extends App.Model to = item.objectNative.displayName() return App.i18n.translateContent('%s ended switch to |%s|!', item.created_by.displayName(), to) return "Unknow action for (#{@objectDisplayName()}/#{item.type}), extend activityMessage() of model." + + ### + + user = App.User.find(3) + result = user.permission('ticket.agent') # access to certain permission key + result = user.permission(['ticket.agent', 'ticket.customer']) # access to one of permission keys + + result = user.permission('user_preferences.calendar+ticket.agent') # access must have two permission keys + + returns + + true|false + + ### + + permission: (key) -> + keys = key + if !_.isArray(key) + keys = [key] + + # get all permissions of user + permissions = {} + for role_id in @role_ids + role = App.Role.find(role_id) + for permission_id in role.permission_ids + permission = App.Permission.find(permission_id) + permissions[permission.name] = true + + for localKey in keys + requiredPermissions = localKey.split('+') + access = false + for requiredPermission in requiredPermissions + localAccess = false + partString = '' + for part in requiredPermission.split('.') + if partString isnt '' + partString += '.' + partString += part + if permissions[partString] + localAccess = true + if localAccess + access = true + else + access = false + break + return access if access + false diff --git a/app/assets/javascripts/app/views/generic/permission.jst.eco b/app/assets/javascripts/app/views/generic/permission.jst.eco new file mode 100644 index 000000000..20646a163 --- /dev/null +++ b/app/assets/javascripts/app/views/generic/permission.jst.eco @@ -0,0 +1,21 @@ +
+<% for permission in @permissions: %> + <% if !permission.name.match(/\./): %> + + <% else: %> +
+ +
+ <% end %> +<% end %> +
diff --git a/app/assets/javascripts/app/views/generic/user_permission.jst.eco b/app/assets/javascripts/app/views/generic/user_permission.jst.eco index 102de2943..06489aa6f 100644 --- a/app/assets/javascripts/app/views/generic/user_permission.jst.eco +++ b/app/assets/javascripts/app/views/generic/user_permission.jst.eco @@ -6,7 +6,9 @@ <%- @Icon('checkbox-checked', 'icon-checked') %> <%= role.displayName() %> <% if role.note: %>- <%= role.note %><% end %> - <% if role.name is 'Agent': %> + <% if role.permissions: %> + <% for permission in role.permissions: %> + <% if _.contains(permission.preferences.plugin, 'groups'): %>
<% for group in @groups: %> <% end %>
+ <% break %> + <% end %> + <% end %> <% end %> <% end %> \ No newline at end of file diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 82ef77e36..3b0fcde82 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -8,7 +8,6 @@ class ApplicationController < ActionController::Base :authentication_check, :config_frontend, :http_log_config, - :role?, :model_create_render, :model_update_render, :model_restory_render, @@ -171,6 +170,7 @@ class ApplicationController < ActionController::Base switched_from_user_id = ENV['SWITCHED_FROM_USER_ID'] || session[:switched_from_user_id] return true if switched_from_user_id return true if !user + return true if !user.permissions?('user_preferences.device') time_to_check = true user_device_updated_at = session[:user_device_updated_at] @@ -223,7 +223,6 @@ class ApplicationController < ActionController::Base end def authentication_check_only(auth_param) - #logger.debug 'authentication_check' #logger.debug params.inspect #logger.debug session.inspect @@ -233,38 +232,16 @@ class ApplicationController < ActionController::Base if session.id && session[:user_id] logger.debug 'session based auth check' user = User.lookup(id: session[:user_id]) - - # check scopes / permission check - # auth_param[:permission] - #if auth_param[:permission] && !user.permission?(auth_param[:permission]) - # return { - # auth: false, - # message: 'No permission!', - # } - #end - - current_user_set(user) - logger.debug "session based auth for '#{user.login}'" - return { - auth: true - } + return authentication_check_prerequesits(user, 'session', auth_param) if user end - error_message = 'authentication failed' - # check sso based authentication sso_user = User.sso(params) if sso_user - if check_maintenance_only(sso_user) - return { - auth: false, - message: 'Maintenance mode enabled!', - } + if authentication_check_prerequesits(sso_user, 'session', auth_param) + session[:persistent] = true + return sso_user end - session[:persistent] = true - return { - auth: true - } end # check http basic based authentication @@ -272,50 +249,10 @@ class ApplicationController < ActionController::Base request.session_options[:skip] = true # do not send a session cookie logger.debug "http basic auth check '#{username}'" if Setting.get('api_password_access') == false - return { - auth: false, - message: 'API password access disabled!', - } + raise Exceptions::NotAuthorized, 'API password access disabled!' end user = User.authenticate(username, password) - next if !user - if check_maintenance_only(user) - return { - auth: false, - message: 'Maintenance mode enabled!', - } - end - current_user_set(user) - user_device_log(user, 'basic_auth') - logger.debug "http basic auth for '#{user.login}'" - return { - auth: true - } - end - - # check http token action based authentication - if auth_param[:token_action] - authenticate_with_http_token do |token, _options| - request.session_options[:skip] = true # do not send a session cookie - logger.debug "http token action auth check '#{token}'" - user = Token.check( - action: auth_param[:token_action], - name: token, - ) - next if !user - if check_maintenance_only(user) - return { - auth: false, - message: 'Maintenance mode enabled!', - } - end - current_user_set(user) - user_device_log(user, 'token_auth') - logger.debug "http token action auth for '#{user.login}'" - return { - auth: true - } - end + return authentication_check_prerequesits(user, 'basic_auth', auth_param) if user end # check http token based authentication @@ -323,31 +260,16 @@ class ApplicationController < ActionController::Base logger.debug "http token auth check '#{token}'" request.session_options[:skip] = true # do not send a session cookie if Setting.get('api_token_access') == false - return { - auth: false, - message: 'API token access disabled!', - } + raise Exceptions::NotAuthorized, 'API token access disabled!' end user = Token.check( action: 'api', name: token, + permission: auth_param[:permission], + inactive_user: true, ) - next if !user - if check_maintenance_only(user) - return { - auth: false, - message: 'Maintenance mode enabled!', - } - end - - # permission check - # auth_param[:permission] - current_user_set(user) - user_device_log(user, 'token_auth') - logger.debug "http token auth for '#{user.login}'" - return { - auth: true - } + @_token_auth = token # remember for permission_check + return authentication_check_prerequesits(user, 'token_auth', auth_param) if user end =begin @@ -360,73 +282,57 @@ class ApplicationController < ActionController::Base # check expire if access_token.expires_in && (access_token.created_at + access_token.expires_in) < Time.zone.now - return { - auth: false, - message: 'OAuth2 token is expired!', - } + raise Exceptions::NotAuthorized, 'OAuth2 token is expired!' + end + + if access_token.scopes.empty? + raise Exceptions::NotAuthorized, 'OAuth2 scope missing for token!' end user = User.find(access_token.resource_owner_id) - if !user || user.active == false - return { - auth: false, - message: 'OAuth2 resource owner inactive!', - } - end - - if check_maintenance_only(user) - return { - auth: false, - message: 'Maintenance mode enabled!', - } - end - - # check scopes / permission check - # auth_param[:permission] - if access_token.scopes.empty? - return { - auth: false, - message: 'OAuth2 scope missing for token!', - } - end - - current_user_set(user) - user_device_log(user, 'token_auth') - logger.debug "oauth token auth for '#{user.login}'" - return { - auth: true - } + return authentication_check_prerequesits(user, 'token_auth', auth_param) if user end =end - logger.debug error_message - { - auth: false, - message: error_message, - } + false + end + + def authentication_check_prerequesits(user, auth_type, auth_param) + if check_maintenance_only(user) + raise Exceptions::NotAuthorized, 'Maintenance mode enabled!' + end + + if user.active == false + raise Exceptions::NotAuthorized, 'User is inactive!' + end + + # check scopes / permission check + if auth_param[:permission] && !user.permissions?(auth_param[:permission]) + raise Exceptions::NotAuthorized, 'No permission!' + end + + current_user_set(user) + user_device_log(user, auth_type) + logger.debug "#{auth_type} for '#{user.login}'" + true end def authentication_check(auth_param = {}) - result = authentication_check_only(auth_param) + user = authentication_check_only(auth_param) # check if basic_auth fallback is possible - if auth_param[:basic_auth_promt] && result[:auth] == false + if auth_param[:basic_auth_promt] && !user return request_http_basic_authentication end # return auth not ok - if result[:auth] == false - raise Exceptions::NotAuthorized, result[:message] + if !user + raise Exceptions::NotAuthorized, 'authentication failed' end # return auth ok true end - def role?(role_name) - return false if !current_user - current_user.role?(role_name) - end - def ticket_permission(ticket) return true if ticket.permission(current_user: current_user) raise Exceptions::NotAuthorized @@ -438,9 +344,19 @@ class ApplicationController < ActionController::Base raise Exceptions::NotAuthorized end - def deny_if_not_role(role_name) - return false if role?(role_name) - raise Exceptions::NotAuthorized + def permission_check(key) + if @_token_auth + user = Token.check( + action: 'api', + name: @_token_auth, + permission: key, + ) + return false if user + raise Exceptions::NotAuthorized, 'No permission!' + end + + return false if current_user && current_user.permissions?(key) + raise Exceptions::NotAuthorized, 'No permission!' end def valid_session_with_user @@ -683,7 +599,7 @@ class ApplicationController < ActionController::Base # check maintenance mode def check_maintenance_only(user) return false if Setting.get('maintenance_mode') != true - return false if user.role?('Admin') + return false if user.permissions?('admin.maintenance') Rails.logger.info "Maintenance mode enabled, denied login for user #{user.login}, it's no admin user." true end diff --git a/app/controllers/calendars_controller.rb b/app/controllers/calendars_controller.rb index 3591c1f47..6192412b3 100644 --- a/app/controllers/calendars_controller.rb +++ b/app/controllers/calendars_controller.rb @@ -1,10 +1,9 @@ # Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/ class CalendarsController < ApplicationController - before_action :authentication_check + before_action { authentication_check(permission: 'admin.calendar') } def index - deny_if_not_role(Z_ROLENAME_ADMIN) # calendars assets = {} @@ -25,22 +24,19 @@ class CalendarsController < ApplicationController end def show - deny_if_not_role(Z_ROLENAME_ADMIN) model_show_render(Calendar, params) end def create - deny_if_not_role(Z_ROLENAME_ADMIN) model_create_render(Calendar, params) end def update - deny_if_not_role(Z_ROLENAME_ADMIN) model_update_render(Calendar, params) end def destroy - deny_if_not_role(Z_ROLENAME_ADMIN) model_destory_render(Calendar, params) end + end diff --git a/app/controllers/channels_controller.rb b/app/controllers/channels_controller.rb index a88bb62d1..50a3b332f 100644 --- a/app/controllers/channels_controller.rb +++ b/app/controllers/channels_controller.rb @@ -17,7 +17,7 @@ curl http://localhost/api/v1/group/channels.json -v -u #{login}:#{password} -H " =end def group_update - deny_if_not_role(Z_ROLENAME_ADMIN) + permission_check('admin') check_access channel = Channel.find(params[:id]) @@ -40,12 +40,13 @@ curl http://localhost/api/v1/channels.json -v -u #{login}:#{password} -H "Conten =end def destroy - deny_if_not_role(Z_ROLENAME_ADMIN) + permission_check('admin') check_access model_destory_render(Channel, params) end def twitter_index + permission_check('admin.channel_twitter') assets = {} ExternalCredential.where(name: 'twitter').each { |external_credential| assets = external_credential.assets(assets) @@ -64,11 +65,12 @@ curl http://localhost/api/v1/channels.json -v -u #{login}:#{password} -H "Conten end def twitter_verify - deny_if_not_role(Z_ROLENAME_ADMIN) + permission_check('admin.channel_twitter') model_update_render(Channel, params) end def facebook_index + permission_check('admin.channel_facebook') assets = {} ExternalCredential.where(name: 'facebook').each { |external_credential| assets = external_credential.assets(assets) @@ -87,12 +89,12 @@ curl http://localhost/api/v1/channels.json -v -u #{login}:#{password} -H "Conten end def facebook_verify - deny_if_not_role(Z_ROLENAME_ADMIN) + permission_check('admin.channel_facebook') model_update_render(Channel, params) end def email_index - deny_if_not_role(Z_ROLENAME_ADMIN) + permission_check('admin.channel_email') system_online_service = Setting.get('system_online_service') account_channel_ids = [] notification_channel_ids = [] @@ -143,7 +145,7 @@ curl http://localhost/api/v1/channels.json -v -u #{login}:#{password} -H "Conten def email_probe # check admin permissions - deny_if_not_role(Z_ROLENAME_ADMIN) + permission_check('admin.channel_email') # probe settings based on email and password result = EmailHelper::Probe.full( @@ -163,7 +165,7 @@ curl http://localhost/api/v1/channels.json -v -u #{login}:#{password} -H "Conten def email_outbound # check admin permissions - deny_if_not_role(Z_ROLENAME_ADMIN) + permission_check('admin.channel_email') # verify access return if params[:channel_id] && !check_access(params[:channel_id]) @@ -175,7 +177,7 @@ curl http://localhost/api/v1/channels.json -v -u #{login}:#{password} -H "Conten def email_inbound # check admin permissions - deny_if_not_role(Z_ROLENAME_ADMIN) + permission_check('admin.channel_email') # verify access return if params[:channel_id] && !check_access(params[:channel_id]) @@ -192,7 +194,7 @@ curl http://localhost/api/v1/channels.json -v -u #{login}:#{password} -H "Conten def email_verify # check admin permissions - deny_if_not_role(Z_ROLENAME_ADMIN) + permission_check('admin.channel_email') email = params[:email] || params[:meta][:email] email = email.downcase @@ -287,7 +289,7 @@ curl http://localhost/api/v1/channels.json -v -u #{login}:#{password} -H "Conten check_online_service # check admin permissions - deny_if_not_role(Z_ROLENAME_ADMIN) + permission_check('admin.channel_email') adapter = params[:adapter].downcase diff --git a/app/controllers/chats_controller.rb b/app/controllers/chats_controller.rb index 8e0bfb0cc..9e12d73d8 100644 --- a/app/controllers/chats_controller.rb +++ b/app/controllers/chats_controller.rb @@ -1,10 +1,9 @@ # Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/ class ChatsController < ApplicationController - before_action :authentication_check + before_action { authentication_check(permission: 'admin.chat') } def index - deny_if_not_role(Z_ROLENAME_ADMIN) chat_ids = [] assets = {} Chat.order(:id).each { |chat| @@ -20,22 +19,19 @@ class ChatsController < ApplicationController end def show - deny_if_not_role(Z_ROLENAME_ADMIN) model_show_render(Chat, params) end def create - deny_if_not_role(Z_ROLENAME_ADMIN) model_create_render(Chat, params) end def update - deny_if_not_role(Z_ROLENAME_ADMIN) model_update_render(Chat, params) end def destroy - deny_if_not_role(Z_ROLENAME_ADMIN) model_destory_render(Chat, params) end + end diff --git a/app/controllers/cti_controller.rb b/app/controllers/cti_controller.rb index 5f7c3582a..09527c322 100644 --- a/app/controllers/cti_controller.rb +++ b/app/controllers/cti_controller.rb @@ -1,12 +1,10 @@ # Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/ class CtiController < ApplicationController - before_action :authentication_check + before_action { authentication_check(permission: 'cti.agent') } # list current caller log def index - deny_if_not_role('CTI') - backends = [ { name: 'sipgate.io', @@ -22,7 +20,6 @@ class CtiController < ApplicationController # set caller log to done def done - deny_if_not_role('CTI') log = Cti::Log.find(params['id']) log.done = params['done'] log.save diff --git a/app/controllers/email_addresses_controller.rb b/app/controllers/email_addresses_controller.rb index 040e47bfc..17be35d72 100644 --- a/app/controllers/email_addresses_controller.rb +++ b/app/controllers/email_addresses_controller.rb @@ -46,6 +46,7 @@ curl http://localhost/api/v1/email_addresses.json -v -u #{login}:#{password} =end def index + permission_check(['admin.channel_email', 'ticket.agent']) model_index_render(EmailAddress, params) end @@ -67,6 +68,7 @@ curl http://localhost/api/v1/email_addresses/#{id}.json -v -u #{login}:#{passwor =end def show + permission_check(['admin.channel_email', 'ticket.agent']) model_show_render(EmailAddress, params) end @@ -97,7 +99,7 @@ curl http://localhost/api/v1/email_addresses.json -v -u #{login}:#{password} -H =end def create - deny_if_not_role(Z_ROLENAME_ADMIN) + permission_check('admin.channel_email') model_create_render(EmailAddress, params) end @@ -128,7 +130,7 @@ curl http://localhost/api/v1/email_addresses/#{id}.json -v -u #{login}:#{passwor =end def update - deny_if_not_role(Z_ROLENAME_ADMIN) + permission_check('admin.channel_email') model_update_render(EmailAddress, params) end @@ -146,7 +148,7 @@ curl http://localhost/api/v1/email_addresses/#{id}.json -v -u #{login}:#{passwor =end def destroy - deny_if_not_role(Z_ROLENAME_ADMIN) + permission_check('admin.channel_email') model_destory_render(EmailAddress, params) end end diff --git a/app/controllers/external_credentials_controller.rb b/app/controllers/external_credentials_controller.rb index d764d279d..052c728d0 100644 --- a/app/controllers/external_credentials_controller.rb +++ b/app/controllers/external_credentials_controller.rb @@ -1,30 +1,25 @@ # Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/ class ExternalCredentialsController < ApplicationController - before_action :authentication_check + before_action { authentication_check(permission: ['admin.channel_twitter', 'admin.channel_facebook']) } def index - deny_if_not_role(Z_ROLENAME_ADMIN) model_index_render(ExternalCredential, params) end def show - deny_if_not_role(Z_ROLENAME_ADMIN) model_show_render(ExternalCredential, params) end def create - deny_if_not_role(Z_ROLENAME_ADMIN) model_create_render(ExternalCredential, params) end def update - deny_if_not_role(Z_ROLENAME_ADMIN) model_update_render(ExternalCredential, params) end def destroy - deny_if_not_role(Z_ROLENAME_ADMIN) model_destory_render(ExternalCredential, params) end @@ -37,7 +32,6 @@ class ExternalCredentialsController < ApplicationController end def link_account - deny_if_not_role(Z_ROLENAME_ADMIN) provider = params[:provider].downcase attributes = ExternalCredential.request_account_to_link(provider) session[:request_token] = attributes[:request_token] @@ -45,7 +39,6 @@ class ExternalCredentialsController < ApplicationController end def callback - deny_if_not_role(Z_ROLENAME_ADMIN) provider = params[:provider].downcase channel = ExternalCredential.link_account(provider, session[:request_token], params) session[:request_token] = nil diff --git a/app/controllers/first_steps_controller.rb b/app/controllers/first_steps_controller.rb index ed81a24a3..a2de9211d 100644 --- a/app/controllers/first_steps_controller.rb +++ b/app/controllers/first_steps_controller.rb @@ -44,7 +44,7 @@ class FirstStepsController < ApplicationController macro_active = true end - if current_user.role?('Admin') + if current_user.permissions?('admin') result = [ { @@ -225,7 +225,7 @@ class FirstStepsController < ApplicationController end def access? - return true if current_user.role?(%w(Agent Admin)) + return true if current_user.permissions?(['admin', 'ticket.agent']) render json: [] false end diff --git a/app/controllers/form_controller.rb b/app/controllers/form_controller.rb index a2eac78a8..e13ccb237 100644 --- a/app/controllers/form_controller.rb +++ b/app/controllers/form_controller.rb @@ -74,14 +74,14 @@ class FormController < ApplicationController customer = User.find_by(email: email) if !customer - roles = Role.where(name: 'Customer') + role_ids = Role.signup_role_ids customer = User.create( firstname: name, lastname: '', email: email, password: '', active: true, - roles: roles, + role_ids: role_ids, updated_by_id: 1, created_by_id: 1, ) diff --git a/app/controllers/getting_started_controller.rb b/app/controllers/getting_started_controller.rb index ee26be95e..5118507b2 100644 --- a/app/controllers/getting_started_controller.rb +++ b/app/controllers/getting_started_controller.rb @@ -110,7 +110,7 @@ curl http://localhost/api/v1/getting_started -v -u #{login}:#{password} def base # check admin permissions - deny_if_not_role(Z_ROLENAME_ADMIN) + permission_check('admin.wizard') # validate url messages = {} diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb index 728cbb8ed..8983557c2 100644 --- a/app/controllers/groups_controller.rb +++ b/app/controllers/groups_controller.rb @@ -1,7 +1,7 @@ # Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/ class GroupsController < ApplicationController - before_action :authentication_check + before_action { authentication_check(permission: 'admin.group') } =begin @@ -101,7 +101,6 @@ curl http://localhost/api/v1/groups -v -u #{login}:#{password} -H "Content-Type: =end def create - deny_if_not_role(Z_ROLENAME_ADMIN) model_create_render(Group, params) end @@ -133,7 +132,6 @@ curl http://localhost/api/v1/groups -v -u #{login}:#{password} -H "Content-Type: =end def update - deny_if_not_role(Z_ROLENAME_ADMIN) model_update_render(Group, params) end @@ -151,7 +149,6 @@ curl http://localhost/api/v1/groups/{id} -v -u #{login}:#{password} -H "Content- =end def destroy - deny_if_not_role(Z_ROLENAME_ADMIN) model_destory_render(Group, params) end end diff --git a/app/controllers/http_logs_controller.rb b/app/controllers/http_logs_controller.rb index b257905a7..d363d79b4 100644 --- a/app/controllers/http_logs_controller.rb +++ b/app/controllers/http_logs_controller.rb @@ -5,7 +5,7 @@ class HttpLogsController < ApplicationController # GET /http_logs/:facility def index - deny_if_not_role(Z_ROLENAME_ADMIN) + permission_check('admin.*') list = if params[:facility] HttpLog.where(facility: params[:facility]).order('created_at DESC').limit(params[:limit] || 50) else @@ -16,7 +16,7 @@ class HttpLogsController < ApplicationController # POST /http_logs def create - deny_if_not_role(Z_ROLENAME_ADMIN) + permission_check('admin.*') model_create_render(HttpLog, params) end diff --git a/app/controllers/jobs_controller.rb b/app/controllers/jobs_controller.rb index 6a9d25948..68b5754f0 100644 --- a/app/controllers/jobs_controller.rb +++ b/app/controllers/jobs_controller.rb @@ -1,30 +1,26 @@ # Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/ class JobsController < ApplicationController - before_action :authentication_check + before_action { authentication_check(permission: 'admin.scheduler') } def index - deny_if_not_role(Z_ROLENAME_ADMIN) model_index_render(Job, params) end def show - deny_if_not_role(Z_ROLENAME_ADMIN) model_show_render(Job, params) end def create - deny_if_not_role(Z_ROLENAME_ADMIN) model_create_render(Job, params) end def update - deny_if_not_role(Z_ROLENAME_ADMIN) model_update_render(Job, params) end def destroy - deny_if_not_role(Z_ROLENAME_ADMIN) model_destory_render(Job, params) end + end diff --git a/app/controllers/object_manager_attributes_controller.rb b/app/controllers/object_manager_attributes_controller.rb index 262165352..16d53e0ae 100644 --- a/app/controllers/object_manager_attributes_controller.rb +++ b/app/controllers/object_manager_attributes_controller.rb @@ -1,11 +1,10 @@ # Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/ class ObjectManagerAttributesController < ApplicationController - before_action :authentication_check + before_action { authentication_check(permission: 'admin.object') } # GET /object_manager_attributes_list def list - deny_if_not_role(Z_ROLENAME_ADMIN) render json: { objects: ObjectManager.list_frontend_objects, } @@ -13,19 +12,16 @@ class ObjectManagerAttributesController < ApplicationController # GET /object_manager_attributes def index - deny_if_not_role(Z_ROLENAME_ADMIN) render json: ObjectManager::Attribute.list_full end # GET /object_manager_attributes/1 def show - deny_if_not_role(Z_ROLENAME_ADMIN) model_show_render(ObjectManager::Attribute, params) end # POST /object_manager_attributes def create - deny_if_not_role(Z_ROLENAME_ADMIN) check_params # check if attribute already exists @@ -55,7 +51,6 @@ class ObjectManagerAttributesController < ApplicationController # PUT /object_manager_attributes/1 def update - deny_if_not_role(Z_ROLENAME_ADMIN) check_params begin object_manager_attribute = ObjectManager::Attribute.add( @@ -77,7 +72,6 @@ class ObjectManagerAttributesController < ApplicationController # DELETE /object_manager_attributes/1 def destroy - deny_if_not_role(Z_ROLENAME_ADMIN) object_manager_attribute = ObjectManager::Attribute.find(params[:id]) ObjectManager::Attribute.remove( object_lookup_id: object_manager_attribute.object_lookup_id, @@ -88,14 +82,12 @@ class ObjectManagerAttributesController < ApplicationController # POST /object_manager_attributes_discard_changes def discard_changes - deny_if_not_role(Z_ROLENAME_ADMIN) ObjectManager::Attribute.discard_changes render json: {}, status: :ok end # POST /object_manager_attributes_execute_migrations def execute_migrations - deny_if_not_role(Z_ROLENAME_ADMIN) ObjectManager::Attribute.migration_execute render json: {}, status: :ok end diff --git a/app/controllers/organizations_controller.rb b/app/controllers/organizations_controller.rb index 46649c67e..4628807d5 100644 --- a/app/controllers/organizations_controller.rb +++ b/app/controllers/organizations_controller.rb @@ -57,7 +57,7 @@ curl http://localhost/api/v1/organizations -v -u #{login}:#{password} # only allow customer to fetch his own organization organizations = [] - if role?(Z_ROLENAME_CUSTOMER) && !role?(Z_ROLENAME_ADMIN) && !role?(Z_ROLENAME_AGENT) + if !current_user.permissions?('admin.organization') && !current_user.permissions?('ticket.agent') if current_user.organization_id organizations = Organization.where(id: current_user.organization_id).offset(offset).limit(per_page) end @@ -111,7 +111,7 @@ curl http://localhost/api/v1/organizations/#{id} -v -u #{login}:#{password} def show # only allow customer to fetch his own organization - if role?(Z_ROLENAME_CUSTOMER) && !role?(Z_ROLENAME_ADMIN) && !role?(Z_ROLENAME_AGENT) + if !current_user.permissions?('admin.organization') && !current_user.permissions?('ticket.agent') if !current_user.organization_id render json: {} return @@ -160,7 +160,8 @@ curl http://localhost/api/v1/organizations -v -u #{login}:#{password} -H "Conten =end def create - deny_if_not_role(Z_ROLENAME_AGENT) + permission_check('ticket.agent') + #permission_check('admin.organization') model_create_render(Organization, params) end @@ -191,7 +192,7 @@ curl http://localhost/api/v1/organizations -v -u #{login}:#{password} -H "Conten =end def update - deny_if_not_role(Z_ROLENAME_AGENT) + permission_check('ticket.agent') model_update_render(Organization, params) end @@ -209,7 +210,7 @@ curl http://localhost/api/v1/organization/{id} -v -u #{login}:#{password} -H "Co =end def destroy - deny_if_not_role(Z_ROLENAME_AGENT) + permission_check('ticket.agent') model_references_check(Organization, params) model_destory_render(Organization, params) end @@ -217,7 +218,7 @@ curl http://localhost/api/v1/organization/{id} -v -u #{login}:#{password} -H "Co # GET /api/v1/organizations/search def search - if role?(Z_ROLENAME_CUSTOMER) && !role?(Z_ROLENAME_ADMIN) && !role?(Z_ROLENAME_AGENT) + if !current_user.permissions?('admin.organization') && !current_user.permissions?('ticket.agent') raise Exceptions::NotAuthorized end @@ -284,7 +285,7 @@ curl http://localhost/api/v1/organization/{id} -v -u #{login}:#{password} -H "Co def history # permission check - if !role?(Z_ROLENAME_ADMIN) && !role?(Z_ROLENAME_AGENT) + if !current_user.permissions?('admin.organization') && !current_user.permissions?('ticket.agent') raise Exceptions::NotAuthorized end diff --git a/app/controllers/overviews_controller.rb b/app/controllers/overviews_controller.rb index e570a3bdb..69b1c2069 100644 --- a/app/controllers/overviews_controller.rb +++ b/app/controllers/overviews_controller.rb @@ -1,7 +1,7 @@ # Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/ class OverviewsController < ApplicationController - before_action :authentication_check + before_action { authentication_check(permission: 'admin.overview') } =begin @@ -52,7 +52,6 @@ curl http://localhost/api/v1/overviews.json -v -u #{login}:#{password} =end def index - deny_if_not_role(Z_ROLENAME_ADMIN) model_index_render(Overview, params) end @@ -74,7 +73,6 @@ curl http://localhost/api/v1/overviews/#{id}.json -v -u #{login}:#{password} =end def show - deny_if_not_role(Z_ROLENAME_ADMIN) model_show_render(Overview, params) end @@ -108,7 +106,6 @@ curl http://localhost/api/v1/overviews.json -v -u #{login}:#{password} -H "Conte =end def create - deny_if_not_role(Z_ROLENAME_ADMIN) model_create_render(Overview, params) end @@ -142,7 +139,6 @@ curl http://localhost/api/v1/overviews.json -v -u #{login}:#{password} -H "Conte =end def update - deny_if_not_role(Z_ROLENAME_ADMIN) model_update_render(Overview, params) end @@ -160,7 +156,6 @@ curl http://localhost/api/v1/overviews/#{id}.json -v -u #{login}:#{password} -H =end def destroy - deny_if_not_role(Z_ROLENAME_ADMIN) model_destory_render(Overview, params) end end diff --git a/app/controllers/packages_controller.rb b/app/controllers/packages_controller.rb index a39a87c28..d3626377f 100644 --- a/app/controllers/packages_controller.rb +++ b/app/controllers/packages_controller.rb @@ -1,11 +1,10 @@ # Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/ class PackagesController < ApplicationController - before_action :authentication_check + before_action { authentication_check(permission: 'admin.package') } # GET /api/v1/packages def index - deny_if_not_role(Z_ROLENAME_ADMIN) packages = Package.all().order('name') render json: { packages: packages @@ -14,21 +13,14 @@ class PackagesController < ApplicationController # POST /api/v1/packages def install - deny_if_not_role(Z_ROLENAME_ADMIN) - Package.install(string: params[:file_upload].read) - redirect_to '/#system/package' end # DELETE /api/v1/packages def uninstall - deny_if_not_role(Z_ROLENAME_ADMIN) - package = Package.find(params[:id]) - Package.uninstall(name: package.name, version: package.version) - render json: { success: true } diff --git a/app/controllers/postmaster_filters_controller.rb b/app/controllers/postmaster_filters_controller.rb index 9a7164c2d..b4c5df52c 100644 --- a/app/controllers/postmaster_filters_controller.rb +++ b/app/controllers/postmaster_filters_controller.rb @@ -1,7 +1,7 @@ # Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/ class PostmasterFiltersController < ApplicationController - before_action :authentication_check + before_action { authentication_check(permission: 'admin.channel_email') } =begin @@ -54,7 +54,6 @@ curl http://localhost/api/v1/postmaster_filters.json -v -u #{login}:#{password} =end def index - deny_if_not_role(Z_ROLENAME_ADMIN) model_index_render(PostmasterFilter, params) end @@ -76,7 +75,6 @@ curl http://localhost/api/v1/postmaster_filters/#{id}.json -v -u #{login}:#{pass =end def show - deny_if_not_role(Z_ROLENAME_ADMIN) model_show_render(PostmasterFilter, params) end @@ -121,7 +119,6 @@ curl http://localhost/api/v1/postmaster_filters.json -v -u #{login}:#{password} =end def create - deny_if_not_role(Z_ROLENAME_ADMIN) model_create_render(PostmasterFilter, params) end @@ -164,7 +161,6 @@ curl http://localhost/api/v1/postmaster_filters.json -v -u #{login}:#{password} =end def update - deny_if_not_role(Z_ROLENAME_ADMIN) model_update_render(PostmasterFilter, params) end @@ -179,7 +175,6 @@ Test: =end def destroy - deny_if_not_role(Z_ROLENAME_ADMIN) model_destory_render(PostmasterFilter, params) end end diff --git a/app/controllers/report_profiles_controller.rb b/app/controllers/report_profiles_controller.rb index 58f574e18..f88933fd2 100644 --- a/app/controllers/report_profiles_controller.rb +++ b/app/controllers/report_profiles_controller.rb @@ -1,5 +1,5 @@ class ReportProfilesController < ApplicationController - before_action :authentication_check + before_action { authentication_check(permission: 'admin.report_profile') } =begin @@ -138,4 +138,5 @@ curl http://localhost/api/report_profiles.json -v -u #{login}:#{password} -H "Co def destroy model_destory_render(Report::Profile, params) end + end diff --git a/app/controllers/reports_controller.rb b/app/controllers/reports_controller.rb index 741ff14b2..122abd177 100644 --- a/app/controllers/reports_controller.rb +++ b/app/controllers/reports_controller.rb @@ -3,11 +3,10 @@ require 'tempfile' class ReportsController < ApplicationController - before_action :authentication_check + before_action { authentication_check(permission: 'report') } # GET /api/reports/config def reporting_config - deny_if_not_role('Report') render json: { config: Report.config, profiles: Report::Profile.list, @@ -16,8 +15,6 @@ class ReportsController < ApplicationController # GET /api/reports/generate def generate - deny_if_not_role('Report') - get_params = params_all return if !get_params @@ -61,8 +58,6 @@ class ReportsController < ApplicationController # GET /api/reports/sets def sets - deny_if_not_role('Report') - get_params = params_all return if !get_params diff --git a/app/controllers/roles_controller.rb b/app/controllers/roles_controller.rb index 4dd7b7f39..19317a51a 100644 --- a/app/controllers/roles_controller.rb +++ b/app/controllers/roles_controller.rb @@ -95,7 +95,7 @@ curl http://localhost/api/v1/roles.json -v -u #{login}:#{password} -H "Content-T =end def create - deny_if_not_role(Z_ROLENAME_ADMIN) + permission_check('admin.role') model_create_render(Role, params) end @@ -124,7 +124,7 @@ curl http://localhost/api/v1/roles.json -v -u #{login}:#{password} -H "Content-T =end def update - deny_if_not_role(Z_ROLENAME_ADMIN) + permission_check('admin.role') model_update_render(Role, params) end @@ -139,7 +139,7 @@ Test: =end def destroy - deny_if_not_role(Z_ROLENAME_ADMIN) + permission_check('admin.role') model_destory_render(Role, params) end end diff --git a/app/controllers/sessions/collection_base.rb b/app/controllers/sessions/collection_base.rb index bde5a8f5f..52c57ec77 100644 --- a/app/controllers/sessions/collection_base.rb +++ b/app/controllers/sessions/collection_base.rb @@ -17,6 +17,11 @@ module ExtraCollection collections[ RecentView.to_app_model ] = RecentView.list(user, 10) assets = RecentView.assets_of_object_list(collections[ RecentView.to_app_model ], assets) + collections[ Permission.to_app_model ] = [] + Permission.all.each { |item| + assets = item.assets(assets) + } + collections[ Role.to_app_model ] = [] Role.all.each { |item| assets = item.assets(assets) diff --git a/app/controllers/sessions/collection_ticket.rb b/app/controllers/sessions/collection_ticket.rb index 87fcb39f9..b54225619 100644 --- a/app/controllers/sessions/collection_ticket.rb +++ b/app/controllers/sessions/collection_ticket.rb @@ -28,7 +28,7 @@ module ExtraCollection Ticket::Article::Sender.all.each { |item| assets = item.assets(assets) } - if !user.role?(Z_ROLENAME_CUSTOMER) + if user.permissions?(['ticket.agent', 'admin.channel_email']) # all signatures collections[ Signature.to_app_model ] = [] diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index c5f21c937..79acae694 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -12,7 +12,7 @@ class SessionsController < ApplicationController user = User.authenticate(params[:username], params[:password]) # check maintenance mode - return if check_maintenance(user) + check_maintenance(user) # auth failed raise Exceptions::NotAuthorized, 'Wrong Username and Password combination.' if !user @@ -195,7 +195,8 @@ class SessionsController < ApplicationController # "switch" to user def switch_to_user - deny_if_not_role(Z_ROLENAME_ADMIN) + authentication_check + permission_check('admin.session') # check user if !params[:id] @@ -277,7 +278,8 @@ class SessionsController < ApplicationController end def list - deny_if_not_role(Z_ROLENAME_ADMIN) + authentication_check + permission_check('admin.session') assets = {} sessions_clean = [] SessionHelper.list.each { |session| @@ -295,7 +297,8 @@ class SessionsController < ApplicationController end def delete - deny_if_not_role(Z_ROLENAME_ADMIN) + authentication_check + permission_check('admin.session') SessionHelper.destroy(params[:id]) render json: {} end diff --git a/app/controllers/settings_controller.rb b/app/controllers/settings_controller.rb index dd4e2a51f..8e29fcf22 100644 --- a/app/controllers/settings_controller.rb +++ b/app/controllers/settings_controller.rb @@ -1,36 +1,31 @@ # Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/ class SettingsController < ApplicationController - before_action :authentication_check + before_action { authentication_check(permission: 'admin.*') } # GET /settings def index - deny_if_not_role(Z_ROLENAME_ADMIN) model_index_render(Setting, params) end # GET /settings/1 def show - deny_if_not_role(Z_ROLENAME_ADMIN) model_show_render(Setting, params) end # POST /settings def create - deny_if_not_role(Z_ROLENAME_ADMIN) model_create_render(Setting, params) end # PUT /settings/1 def update - deny_if_not_role(Z_ROLENAME_ADMIN) check_access model_update_render(Setting, params) end # PUT /settings/image/:id def update_image - deny_if_not_role(Z_ROLENAME_ADMIN) if !params[:logo] render json: { @@ -82,7 +77,6 @@ class SettingsController < ApplicationController # DELETE /settings/1 def destroy - deny_if_not_role(Z_ROLENAME_ADMIN) check_access model_destory_render(Setting, params) end diff --git a/app/controllers/signatures_controller.rb b/app/controllers/signatures_controller.rb index af4a14d26..f4b21ef1e 100644 --- a/app/controllers/signatures_controller.rb +++ b/app/controllers/signatures_controller.rb @@ -47,6 +47,7 @@ curl http://localhost/api/v1/signatures.json -v -u #{login}:#{password} =end def index + permission_check(['admin.channel_email', 'ticket.agent']) model_index_render(Signature, params) end @@ -68,6 +69,7 @@ curl http://localhost/api/v1/signatures/#{id}.json -v -u #{login}:#{password} =end def show + permission_check(['admin.channel_email', 'ticket.agent']) model_show_render(Signature, params) end @@ -96,7 +98,7 @@ curl http://localhost/api/v1/signatures.json -v -u #{login}:#{password} -H "Cont =end def create - deny_if_not_role(Z_ROLENAME_ADMIN) + permission_check(['admin.channel_email']) model_create_render(Signature, params) end @@ -125,7 +127,7 @@ curl http://localhost/api/v1/signatures.json -v -u #{login}:#{password} -H "Cont =end def update - deny_if_not_role(Z_ROLENAME_ADMIN) + permission_check(['admin.channel_email']) model_update_render(Signature, params) end @@ -140,7 +142,7 @@ Test: =end def destroy - deny_if_not_role(Z_ROLENAME_ADMIN) + permission_check(['admin.channel_email']) model_destory_render(Signature, params) end end diff --git a/app/controllers/slas_controller.rb b/app/controllers/slas_controller.rb index 61a420759..c18703ce5 100644 --- a/app/controllers/slas_controller.rb +++ b/app/controllers/slas_controller.rb @@ -1,7 +1,7 @@ # Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/ class SlasController < ApplicationController - before_action :authentication_check + before_action { authentication_check(permission: 'admin.sla') } =begin @@ -47,7 +47,6 @@ curl http://localhost/api/v1/slas.json -v -u #{login}:#{password} =end def index - deny_if_not_role(Z_ROLENAME_ADMIN) if params[:full] @@ -92,7 +91,6 @@ curl http://localhost/api/v1/slas/#{id}.json -v -u #{login}:#{password} =end def show - deny_if_not_role(Z_ROLENAME_ADMIN) model_show_render(Sla, params) end @@ -121,7 +119,6 @@ curl http://localhost/api/v1/slas.json -v -u #{login}:#{password} -H "Content-Ty =end def create - deny_if_not_role(Z_ROLENAME_ADMIN) model_create_render(Sla, params) end @@ -150,7 +147,6 @@ curl http://localhost/api/v1/slas.json -v -u #{login}:#{password} -H "Content-Ty =end def update - deny_if_not_role(Z_ROLENAME_ADMIN) model_update_render(Sla, params) end @@ -168,7 +164,7 @@ curl http://localhost/api/v1/slas.json -v -u #{login}:#{password} -H "Content-Ty =end def destroy - deny_if_not_role(Z_ROLENAME_ADMIN) model_destory_render(Sla, params) end + end diff --git a/app/controllers/tags_controller.rb b/app/controllers/tags_controller.rb index 35f809efa..50c51d9ee 100644 --- a/app/controllers/tags_controller.rb +++ b/app/controllers/tags_controller.rb @@ -60,6 +60,7 @@ class TagsController < ApplicationController # GET /api/v1/tag_list def admin_list + permission_check('admin.tag') list = Tag::Item.order('name ASC').limit(params[:limit] || 1000) results = [] list.each { |item| @@ -75,14 +76,14 @@ class TagsController < ApplicationController # POST /api/v1/tag_list def admin_create - deny_if_not_role('Admin') + permission_check('admin.tag') Tag::Item.lookup_by_name_and_create(params[:name]) render json: {} end # PUT /api/v1/tag_list/:id def admin_rename - deny_if_not_role('Admin') + permission_check('admin.tag') Tag::Item.rename( id: params[:id], name: params[:name], @@ -92,7 +93,7 @@ class TagsController < ApplicationController # DELETE /api/v1/tag_list/:id def admin_delete - deny_if_not_role('Admin') + permission_check('admin.tag') Tag::Item.remove(params[:id]) render json: {} end diff --git a/app/controllers/templates_controller.rb b/app/controllers/templates_controller.rb index 96ee542b3..b2e142c14 100644 --- a/app/controllers/templates_controller.rb +++ b/app/controllers/templates_controller.rb @@ -47,7 +47,7 @@ curl http://localhost/api/v1/templates.json -v -u #{login}:#{password} =end def index - deny_if_not_role('Agent') + permission_check(['admin.template', 'ticket.agent']) model_index_render(Template, params) end @@ -69,7 +69,7 @@ curl http://localhost/api/v1/templates/#{id}.json -v -u #{login}:#{password} =end def show - deny_if_not_role('Agent') + permission_check(['admin.template', 'ticket.agent']) model_show_render(Template, params) end @@ -97,7 +97,7 @@ curl http://localhost/api/v1/templates.json -v -u #{login}:#{password} -H "Conte =end def create - deny_if_not_role('Agent') + permission_check(['admin.template', 'ticket.agent']) model_create_render(Template, params) end @@ -125,7 +125,7 @@ curl http://localhost/api/v1/templates.json -v -u #{login}:#{password} -H "Conte =end def update - deny_if_not_role('Agent') + permission_check(['admin.template', 'ticket.agent']) model_update_render(Template, params) end @@ -143,7 +143,7 @@ curl http://localhost/api/v1/templates.json -v -u #{login}:#{password} -H "Conte =end def destroy - deny_if_not_role('Agent') + permission_check(['admin.template', 'ticket.agent']) model_destory_render(Template, params) end end diff --git a/app/controllers/text_modules_controller.rb b/app/controllers/text_modules_controller.rb index b1f6f256a..a4c729836 100644 --- a/app/controllers/text_modules_controller.rb +++ b/app/controllers/text_modules_controller.rb @@ -49,6 +49,7 @@ curl http://localhost/api/v1/text_modules.json -v -u #{login}:#{password} =end def index + permission_check('ticket.agent') model_index_render(TextModule, params) end @@ -70,6 +71,7 @@ curl http://localhost/api/v1/text_modules/#{id}.json -v -u #{login}:#{password} =end def show + permission_check('ticket.agent') model_show_render(TextModule, params) end @@ -99,7 +101,7 @@ curl http://localhost/api/v1/text_modules.json -v -u #{login}:#{password} -H "Co =end def create - deny_if_not_role(Z_ROLENAME_ADMIN) + permission_check('admin.text_module') model_create_render(TextModule, params) end @@ -129,7 +131,7 @@ curl http://localhost/api/v1/text_modules.json -v -u #{login}:#{password} -H "Co =end def update - deny_if_not_role(Z_ROLENAME_ADMIN) + permission_check('admin.text_module') model_update_render(TextModule, params) end @@ -147,7 +149,7 @@ curl http://localhost/api/v1/text_modules.json -v -u #{login}:#{password} -H "Co =end def destroy - deny_if_not_role(Z_ROLENAME_ADMIN) + permission_check('admin.text_module') model_destory_render(TextModule, params) end end diff --git a/app/controllers/ticket_articles_controller.rb b/app/controllers/ticket_articles_controller.rb index 626e8720a..2bbc204ae 100644 --- a/app/controllers/ticket_articles_controller.rb +++ b/app/controllers/ticket_articles_controller.rb @@ -5,7 +5,7 @@ class TicketArticlesController < ApplicationController # GET /articles def index - deny_if_not_role(Z_ROLENAME_ADMIN) + permission_check('admin') model_index_render(Ticket::Article, params) end @@ -48,7 +48,7 @@ class TicketArticlesController < ApplicationController ticket.articles.each { |article| # ignore internal article if customer is requesting - next if article.internal == true && role?(Z_ROLENAME_CUSTOMER) + next if article.internal == true && current_user.permissions?('ticket.customer') result = article.attributes_with_relation_names @@ -67,7 +67,7 @@ class TicketArticlesController < ApplicationController ticket.articles.each { |article| # ignore internal article if customer is requesting - next if article.internal == true && role?(Z_ROLENAME_CUSTOMER) + next if article.internal == true && current_user.permissions?('ticket.customer') record_ids.push article.id assets = article.assets({}) @@ -82,7 +82,7 @@ class TicketArticlesController < ApplicationController ticket.articles.each { |article| # ignore internal article if customer is requesting - next if article.internal == true && role?(Z_ROLENAME_CUSTOMER) + next if article.internal == true && current_user.permissions?('ticket.customer') articles.push article.attributes_with_relation_names } diff --git a/app/controllers/ticket_priorities_controller.rb b/app/controllers/ticket_priorities_controller.rb index 7d538c506..367f00b5a 100644 --- a/app/controllers/ticket_priorities_controller.rb +++ b/app/controllers/ticket_priorities_controller.rb @@ -5,29 +5,31 @@ class TicketPrioritiesController < ApplicationController # GET /ticket_priorities def index + permission_check(['admin.object', 'ticket.agent', 'ticket.customer']) model_index_render(Ticket::Priority, params) end # GET /ticket_priorities/1 def show + permission_check(['admin.object', 'ticket.agent', 'ticket.customer']) model_show_render(Ticket::Priority, params) end # POST /ticket_priorities def create - deny_if_not_role(Z_ROLENAME_ADMIN) + permission_check('admin.object') model_create_render(Ticket::Priority, params) end # PUT /ticket_priorities/1 def update - deny_if_not_role(Z_ROLENAME_ADMIN) + permission_check('admin.object') model_update_render(Ticket::Priority, params) end # DELETE /ticket_priorities/1 def destroy - deny_if_not_role(Z_ROLENAME_ADMIN) + permission_check('admin.object') model_references_check(Ticket::Priority, params) model_destory_render(Ticket::Priority, params) end diff --git a/app/controllers/ticket_states_controller.rb b/app/controllers/ticket_states_controller.rb index a03c31c80..335adcea7 100644 --- a/app/controllers/ticket_states_controller.rb +++ b/app/controllers/ticket_states_controller.rb @@ -5,29 +5,31 @@ class TicketStatesController < ApplicationController # GET /ticket_states def index + permission_check(['admin.object', 'ticket.agent', 'ticket.customer']) model_index_render(Ticket::State, params) end # GET /ticket_states/1 def show + permission_check(['admin.object', 'ticket.agent', 'ticket.customer']) model_show_render(Ticket::State, params) end # POST /ticket_states def create - deny_if_not_role(Z_ROLENAME_ADMIN) + permission_check('admin.object') model_create_render(Ticket::State, params) end # PUT /ticket_states/1 def update - deny_if_not_role(Z_ROLENAME_ADMIN) + permission_check('admin.object') model_update_render(Ticket::State, params) end # DELETE /ticket_states/1 def destroy - deny_if_not_role(Z_ROLENAME_ADMIN) + permission_check('admin.object') return if model_references_check(Ticket::State, params) model_destory_render(Ticket::State, params) end diff --git a/app/controllers/tickets_controller.rb b/app/controllers/tickets_controller.rb index 240eaf703..0f0d71ad4 100644 --- a/app/controllers/tickets_controller.rb +++ b/app/controllers/tickets_controller.rb @@ -356,7 +356,7 @@ class TicketsController < ApplicationController # GET /api/v1/tickets/selector def selector - deny_if_not_role(Z_ROLENAME_ADMIN) + permission_check('admin.*') ticket_count, tickets = Ticket.selectors(params[:condition], 6) @@ -627,7 +627,7 @@ class TicketsController < ApplicationController articles.each { |article| # ignore internal article if customer is requesting - next if article.internal == true && role?(Z_ROLENAME_CUSTOMER) + next if article.internal == true && current_user.permissions?('ticket.customer') # load article ids article_ids.push article.id diff --git a/app/controllers/translations_controller.rb b/app/controllers/translations_controller.rb index 14532f9c5..49bde6b60 100644 --- a/app/controllers/translations_controller.rb +++ b/app/controllers/translations_controller.rb @@ -10,62 +10,62 @@ class TranslationsController < ApplicationController # PUT /translations/push def push - deny_if_not_role(Z_ROLENAME_ADMIN) + permission_check('admin.translation') start = Time.zone.now Translation.push(params[:locale]) - if start > Time.zone.now - 5.seconds - sleep 4 + if start > Time.zone.now - 4.seconds + sleep 3 end render json: { message: 'ok' }, status: :ok end # POST /translations/sync/:locale def sync - deny_if_not_role(Z_ROLENAME_ADMIN) + permission_check('admin.translation') Translation.load(params[:locale]) render json: { message: 'ok' }, status: :ok end # POST /translations/reset def reset - deny_if_not_role(Z_ROLENAME_ADMIN) + permission_check('admin.translation') Translation.reset(params[:locale]) render json: { message: 'ok' }, status: :ok end # GET /translations/admin/lang/:locale def admin - deny_if_not_role(Z_ROLENAME_ADMIN) + permission_check('admin.translation') render json: Translation.lang(params[:locale], true) end # GET /translations def index - deny_if_not_role(Z_ROLENAME_ADMIN) + permission_check('admin.translation') model_index_render(Translation, params) end # GET /translations/1 def show - deny_if_not_role(Z_ROLENAME_ADMIN) + permission_check('admin.translation') model_show_render(Translation, params) end # POST /translations def create - deny_if_not_role(Z_ROLENAME_ADMIN) + permission_check('admin.translation') model_create_render(Translation, params) end # PUT /translations/1 def update - deny_if_not_role(Z_ROLENAME_ADMIN) + permission_check('admin.translation') model_update_render(Translation, params) end # DELETE /translations/1 def destroy - deny_if_not_role(Z_ROLENAME_ADMIN) + permission_check('admin.translation') model_destory_render(Translation, params) end end diff --git a/app/controllers/triggers_controller.rb b/app/controllers/triggers_controller.rb index 827d8de25..ad70ffdd5 100644 --- a/app/controllers/triggers_controller.rb +++ b/app/controllers/triggers_controller.rb @@ -1,30 +1,26 @@ # Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/ class TriggersController < ApplicationController - before_action :authentication_check + before_action { authentication_check(permission: 'admin.trigger') } def index - deny_if_not_role(Z_ROLENAME_ADMIN) model_index_render(Trigger, params) end def show - deny_if_not_role(Z_ROLENAME_ADMIN) model_show_render(Trigger, params) end def create - deny_if_not_role(Z_ROLENAME_ADMIN) model_create_render(Trigger, params) end def update - deny_if_not_role(Z_ROLENAME_ADMIN) model_update_render(Trigger, params) end def destroy - deny_if_not_role(Z_ROLENAME_ADMIN) model_destory_render(Trigger, params) end + end diff --git a/app/controllers/user_access_token_controller.rb b/app/controllers/user_access_token_controller.rb index c1dab3f3e..c6f759ad4 100644 --- a/app/controllers/user_access_token_controller.rb +++ b/app/controllers/user_access_token_controller.rb @@ -23,10 +23,13 @@ class UserAccessTokenController < ApplicationController raise Exceptions::UnprocessableEntity, 'Need label!' end token = Token.create( - action: 'api', - label: params[:label], - persistent: true, - user_id: current_user.id, + action: 'api', + label: params[:label], + persistent: true, + user_id: current_user.id, + preferences: { + permission: params[:permission] + } ) render json: { name: token.name, diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 32bcda482..9ee81a255 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -21,7 +21,7 @@ class UsersController < ApplicationController end # only allow customer to fetch him self - users = if role?(Z_ROLENAME_CUSTOMER) && !role?(Z_ROLENAME_ADMIN) && !role?('Agent') + users = if !current_user.permissions?('admin.user') && !current_user.permissions?('ticket.agent') User.where(id: current_user.id).offset(offset).limit(per_page) else User.all.offset(offset).limit(per_page) @@ -72,7 +72,7 @@ class UsersController < ApplicationController def show # access deny - return if !permission_check + permission_check_local if params[:expand] user = User.find(params[:id]).attributes_with_relation_names @@ -110,7 +110,7 @@ class UsersController < ApplicationController user = User.new(clean_params) user.param_set_associations(params) - # check if it's first user, tje admin user + # check if it's first user, the admin user # inital admin account count = User.all.count() admin_account_exists = true @@ -137,7 +137,7 @@ class UsersController < ApplicationController group_ids = [] role_ids = [] if count <= 2 - Role.where(name: [ Z_ROLENAME_ADMIN, 'Agent', 'Chat']).each { |role| + Role.where(name: %w(Admin Agent)).each { |role| role_ids.push role.id } Group.all().each { |group| @@ -146,7 +146,7 @@ class UsersController < ApplicationController # everybody else will go as customer per default else - role_ids.push Role.where(name: Z_ROLENAME_CUSTOMER).first.id + role_ids.push Role.signup_role_ids end user.role_ids = role_ids user.group_ids = group_ids @@ -160,8 +160,8 @@ class UsersController < ApplicationController # else do assignment as defined else - # permission check by role - permission_check_by_role(params) + # permission check + permission_check_by_permission(params) if params[:role_ids] user.role_ids = params[:role_ids] @@ -246,30 +246,30 @@ class UsersController < ApplicationController def update # access deny - return if !permission_check + permission_check_local user = User.find(params[:id]) clean_params = User.param_association_lookup(params) clean_params = User.param_cleanup(clean_params, true) - # permission check by role - permission_check_by_role(params) + # permission check + permission_check_by_permission(params) user.update_attributes(clean_params) - # only allow Admin's and Agent's - if role?(Z_ROLENAME_ADMIN) && role?('Agent') && (params[:role_ids] || params[:roles]) + # only allow Admin's + if current_user.permissions?('admin.user') && (params[:role_ids] || params[:roles]) user.role_ids = params[:role_ids] user.param_set_associations({ role_ids: params[:role_ids], roles: params[:roles] }) end # only allow Admin's - if role?(Z_ROLENAME_ADMIN) && (params[:group_ids] || params[:groups]) + if current_user.permissions?('admin.user') && (params[:group_ids] || params[:groups]) user.group_ids = params[:group_ids] user.param_set_associations({ group_ids: params[:group_ids], groups: params[:groups] }) end # only allow Admin's and Agent's - if role?(Z_ROLENAME_ADMIN) && role?('Agent') && (params[:organization_ids] || params[:organizations]) + if current_user.permissions?(['admin.user', 'ticket.agent']) && (params[:organization_ids] || params[:organizations]) user.param_set_associations({ organization_ids: params[:organization_ids], organizations: params[:organizations] }) end @@ -295,7 +295,7 @@ class UsersController < ApplicationController # @response_message 200 User successfully deleted. # @response_message 401 Invalid session. def destroy - deny_if_not_role(Z_ROLENAME_ADMIN) + permission_check('admin.user') model_references_check(User, params) model_destory_render(User, params) end @@ -321,7 +321,7 @@ class UsersController < ApplicationController # @response_message 401 Invalid session. def search - if role?(Z_ROLENAME_CUSTOMER) && !role?(Z_ROLENAME_ADMIN) && !role?(Z_ROLENAME_AGENT) + if !current_user.permissions('ticket.agent') && !current_user.permissions('admin.user') response_access_deny return end @@ -407,7 +407,7 @@ class UsersController < ApplicationController # @response_message 401 Invalid session. def recent - if role?(Z_ROLENAME_CUSTOMER) && !role?(Z_ROLENAME_ADMIN) + if !current_user.permissions?('admin.user') response_access_deny return end @@ -466,7 +466,7 @@ class UsersController < ApplicationController def history # permission check - if !role?(Z_ROLENAME_ADMIN) && !role?('Agent') + if !current_user.permissions?('admin.user') && !current_user.permissions?('ticket.agent') response_access_deny return end @@ -957,10 +957,10 @@ curl http://localhost/api/v1/users/avatar -v -u #{login}:#{password} -H "Content true end - def permission_check_by_role(params) - return true if role?(Z_ROLENAME_ADMIN) + def permission_check_by_permission(params) + return true if current_user.permissions?('admin.user') - if !role?('Admin') && params[:role_ids] + if !current_user.permissions?('admin.user') && params[:role_ids] if params[:role_ids].class != Array params[:role_ids] = [params[:role_ids]] end @@ -971,13 +971,14 @@ curl http://localhost/api/v1/users/avatar -v -u #{login}:#{password} -H "Content raise Exceptions::NotAuthorized, 'Invalid role_ids!' end role_name = role_local.name + # TODO: check role permissions next if role_name != 'Admin' && role_name != 'Agent' logger.info "This role assignment is only allowed by admin! current_user_id: #{current_user.id} assigned to #{role_name}" raise Exceptions::NotAuthorized, 'This role assignment is only allowed by admin!' } end - if role?('Agent') && params[:group_ids] + if !current_user.permissions?('admin.user') && params[:group_ids] if params[:group_ids].class != Array params[:group_ids] = [params[:group_ids]] end @@ -987,21 +988,21 @@ curl http://localhost/api/v1/users/avatar -v -u #{login}:#{password} -H "Content end end - return true if role?('Agent') + return true if current_user.permissions?('ticket.agent') response_access_deny false end - def permission_check - return true if role?(Z_ROLENAME_ADMIN) - return true if role?('Agent') + def permission_check_local + return true if current_user.permissions?('admin.user') + return true if current_user.permissions?('ticket.agent') - # allow to update customer by him self - return true if role?(Z_ROLENAME_CUSTOMER) && params[:id].to_i == current_user.id + # allow to update any by him self + # TODO check certain attributes like roles_ids and group_ids + return true if params[:id].to_i == current_user.id - response_access_deny - false + raise Exceptions::NotAuthorized end end diff --git a/app/models/activity_stream.rb b/app/models/activity_stream.rb index 74fddc122..bc31d2c56 100644 --- a/app/models/activity_stream.rb +++ b/app/models/activity_stream.rb @@ -12,7 +12,7 @@ add a new activity entry for an object ActivityStream.add( type: 'update', object: 'Ticket', - role: 'Admin', + permission: 'admin.user', o_id: ticket.id, created_by_id: 1, created_at: '2013-06-04 10:00:00', @@ -30,20 +30,20 @@ add a new activity entry for an object object_id = ObjectLookup.by_name(data[:object]) end - role_id = nil - if data[:role] - role = Role.lookup(name: data[:role]) - if !role - raise "No such Role #{data[:role]}" + permission_id = nil + if data[:permission] + permission = Permission.lookup(name: data[:permission]) + if !permission + raise "No such Permission #{data[:permission]}" end - role_id = role.id + permission_id = permission.id end # check newest entry - is needed result = ActivityStream.where( o_id: data[:o_id], #:activity_stream_type_id => type_id, - role_id: role_id, + permission_id: permission_id, activity_stream_object_id: object_id, created_by_id: data[:created_by_id] ).order('created_at DESC, id DESC').first @@ -63,7 +63,7 @@ add a new activity entry for an object o_id: data[:o_id], activity_stream_type_id: type_id, activity_stream_object_id: object_id, - role_id: role_id, + permission_id: permission_id, group_id: data[:group_id], created_at: data[:created_at], created_by_id: data[:created_by_id] @@ -92,26 +92,28 @@ remove whole activity entries of an object return all activity entries of an user - activity_stream = ActivityStream.list(user) + activity_stream = ActivityStream.list(user, limit) =end def self.list(user, limit) - role_ids = user.role_ids + # do not return an activity stream for custoers + return [] if !user.permissions?('ticket.agent') && !user.permissions?('admin') + + permission_ids = [] + user.roles.each { |role| + permission_ids = permission_ids.concat(role.permission_ids) + } group_ids = user.group_ids - # do not return an activity stream for custoers - customer_role = Role.lookup(name: 'Customer') - - return [] if role_ids.include?(customer_role.id) stream = if group_ids.empty? - ActivityStream.where('(role_id IN (?) AND group_id is NULL)', role_ids ) - .order( 'created_at DESC, id DESC' ) - .limit( limit ) + ActivityStream.where('(permission_id IN (?) AND group_id is NULL)', permission_ids) + .order('created_at DESC, id DESC') + .limit(limit) else - ActivityStream.where('(role_id IN (?) AND group_id is NULL) OR ( role_id IN (?) AND group_id IN (?) ) OR ( role_id is NULL AND group_id IN (?) )', role_ids, role_ids, group_ids, group_ids ) - .order( 'created_at DESC, id DESC' ) - .limit( limit ) + ActivityStream.where('(permission_id IN (?) AND group_id is NULL) OR (permission_id IN (?) AND group_id IN (?)) OR (permission_id is NULL AND group_id IN (?))', permission_ids, permission_ids, group_ids, group_ids) + .order('created_at DESC, id DESC') + .limit(limit) end list = [] stream.each do |item| diff --git a/app/models/application_model.rb b/app/models/application_model.rb index a6951d4f6..55e7ce7b6 100644 --- a/app/models/application_model.rb +++ b/app/models/application_model.rb @@ -1093,7 +1093,7 @@ reload search index with full data serve methode to configure and enable activity stream support for this model class Model < ApplicationModel - activity_stream_support role: 'Admin' + activity_stream_support permission: 'admin.user' end =end diff --git a/app/models/application_model/activity_stream_base.rb b/app/models/application_model/activity_stream_base.rb index 85173eaf9..bb9c01fc7 100644 --- a/app/models/application_model/activity_stream_base.rb +++ b/app/models/application_model/activity_stream_base.rb @@ -25,7 +25,7 @@ returns # return if we run on init mode return if !Setting.get('system_init_done') - role = self.class.activity_stream_support_config[:role] + permission = self.class.activity_stream_support_config[:permission] updated_at = self.updated_at if force updated_at = Time.zone.now @@ -35,7 +35,7 @@ returns type: type, object: self.class.name, group_id: self['group_id'], - role: role, + permission: permission, created_at: updated_at, created_by_id: user_id, ) diff --git a/app/models/channel/assets.rb b/app/models/channel/assets.rb index 6d7fe2220..951770e70 100644 --- a/app/models/channel/assets.rb +++ b/app/models/channel/assets.rb @@ -33,7 +33,7 @@ returns access = false if UserInfo.current_user_id user = User.lookup(id: UserInfo.current_user_id) - if user.role?('Admin') + if user.permissions?('admin.channel') access = true end end diff --git a/app/models/channel/filter/identify_sender.rb b/app/models/channel/filter/identify_sender.rb index 369a5c495..6ed30cc05 100644 --- a/app/models/channel/filter/identify_sender.rb +++ b/app/models/channel/filter/identify_sender.rb @@ -88,7 +88,7 @@ module Channel::Filter::IdentifySender return user if user # create new user - roles = Role.where(name: 'Customer') + role_ids = Role.signup_role_ids # fillup %w(firstname lastname).each { |item| @@ -98,7 +98,7 @@ module Channel::Filter::IdentifySender } data[:password] = '' data[:active] = true - data[:roles] = roles + data[:role_ids] = role_ids data[:updated_by_id] = 1 data[:created_by_id] = 1 diff --git a/app/models/cti/log.rb b/app/models/cti/log.rb index 5b8ddfc1f..fc6046ae9 100644 --- a/app/models/cti/log.rb +++ b/app/models/cti/log.rb @@ -255,7 +255,7 @@ returns end def push_event - users = User.of_role('CTI') + users = User.with_permissions('cti.agent') users.each { |user| # send notify about event @@ -272,7 +272,7 @@ returns def push_caller_list list = Cti::Log.log - users = User.of_role('CTI') + users = User.with_permissions('cti.agent') users.each { |user| # send notify on create/update/delete diff --git a/app/models/group.rb b/app/models/group.rb index d35c29613..4b3f4407d 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -6,7 +6,7 @@ class Group < ApplicationModel belongs_to :signature validates :name, presence: true - activity_stream_support role: Z_ROLENAME_ADMIN + activity_stream_support permission: 'admin.group' history_support notify_clients_support latest_change_support diff --git a/app/models/online_notification.rb b/app/models/online_notification.rb index af4841a90..4ab8365b0 100644 --- a/app/models/online_notification.rb +++ b/app/models/online_notification.rb @@ -281,7 +281,7 @@ with dedicated times } # notify all agents - User.of_role('Agent').each { |user| + User.with_permissions('ticket.agent').each { |user| Sessions.send_to( user.id, { diff --git a/app/models/organization.rb b/app/models/organization.rb index 7975d404b..4a73c3c3f 100644 --- a/app/models/organization.rb +++ b/app/models/organization.rb @@ -1,6 +1,7 @@ # Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/ class Organization < ApplicationModel + load 'organization/permission.rb' include Organization::Permission load 'organization/assets.rb' include Organization::Assets @@ -12,7 +13,7 @@ class Organization < ApplicationModel has_many :members, class_name: 'User' validates :name, presence: true - activity_stream_support role: Z_ROLENAME_ADMIN + activity_stream_support permission: 'admin.role' history_support search_index_support notify_clients_support diff --git a/app/models/organization/permission.rb b/app/models/organization/permission.rb index 05e27590e..661134576 100644 --- a/app/models/organization/permission.rb +++ b/app/models/organization/permission.rb @@ -19,7 +19,7 @@ returns def permission (data) # check customer - if data[:current_user].role?('Customer') + if data[:current_user].permissions?('ticket.customer') # access ok if its own organization return false if data[:type] != 'ro' @@ -31,8 +31,8 @@ returns end # check agent - return true if data[:current_user].role?(Z_ROLENAME_ADMIN) - return true if data[:current_user].role?('Agent') + return true if data[:current_user].permissions?('admin') + return true if data[:current_user].permissions?('ticket.agent') false end end diff --git a/app/models/organization/search.rb b/app/models/organization/search.rb index bc640606b..6a609f865 100644 --- a/app/models/organization/search.rb +++ b/app/models/organization/search.rb @@ -23,7 +23,7 @@ returns if user has no permissions to search =end def search_preferences(current_user) - return false if !current_user.role?('Agent') && !current_user.role?(Z_ROLENAME_ADMIN) + return false if !current_user.permissions?('ticket.agent') && !current_user.permissions?('admin.organization') { prio: 1000, direct_search_index: true, diff --git a/app/models/permission.rb b/app/models/permission.rb new file mode 100644 index 000000000..4514d314e --- /dev/null +++ b/app/models/permission.rb @@ -0,0 +1,33 @@ +# Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/ + +class Permission < ApplicationModel + has_and_belongs_to_many :roles + validates :name, presence: true + store :preferences + notify_clients_support + latest_change_support + +=begin + + permissions = Permission.with_parents('some_key.sub_key') + +returnes + + ['some_key.sub_key', 'some_key'] + +=end + + def self.with_parents(key) + names = [] + part = '' + key.split('.').each { |local_part| + if part != '' + part += '.' + end + part += local_part + names.push part + } + names + end + +end diff --git a/app/models/role.rb b/app/models/role.rb index d081689ab..42395f628 100644 --- a/app/models/role.rb +++ b/app/models/role.rb @@ -1,10 +1,134 @@ # Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/ class Role < ApplicationModel + has_and_belongs_to_many :users, after_add: :cache_update, after_remove: :cache_update + has_and_belongs_to_many :permissions, after_add: :cache_update, after_remove: :cache_update + validates :name, presence: true + store :preferences - has_and_belongs_to_many :users, after_add: :cache_update, after_remove: :cache_update - validates :name, presence: true - activity_stream_support role: Z_ROLENAME_ADMIN + before_create :validate_permissions + before_update :validate_permissions + + activity_stream_support permission: 'admin.role' notify_clients_support latest_change_support + +=begin + +grand permission to role + + role.permission_grand('permission.key') + +=end + + def permission_grand(key) + permission = Permission.lookup(name: key) + raise "Invalid permission #{key}" if !permission + return true if permission_ids.include?(permission.id) + self.permission_ids = permission_ids.push permission.id + true + end + +=begin + +revoke permission of role + + role.permission_revoke('permission.key') + +=end + + def permission_revoke(key) + permission = Permission.lookup(name: key) + raise "Invalid permission #{key}" if !permission + return true if !permission_ids.include?(permission.id) + self.permission_ids = self.permission_ids -= [permission.id] + true + end + +=begin + +get signup roles + + Role.signup_roles + +returnes + + [role1, role2, ...] + +=end + + def self.signup_roles + Role.where(active: true, default_at_signup: true) + end + +=begin + +get signup role ids + + Role.signup_role_ids + +returnes + + [role1, role2, ...] + +=end + + def self.signup_role_ids + Role.where(active: true, default_at_signup: true).map(&:id) + end + +=begin + +get all roles with permission + + roles = Role.with_permissions('admin.session') + +get all roles with permission "admin.session" or "ticket.agent" + + roles = Role.with_permissions(['admin.session', 'ticket.agent']) + +returns + + [user1, user2, ...] + +=end + + def self.with_permissions(keys) + if keys.class != Array + keys = [keys] + end + roles = [] + permission_ids = [] + keys.each { |key| + Object.const_get('Permission').with_parents(key).each { |local_key| + permission = Object.const_get('Permission').lookup(name: local_key) + next if !permission + permission_ids.push permission.id + } + next if permission_ids.empty? + Role.joins(:roles_permissions).where('permissions_roles.permission_id IN (?) AND roles.active = ?', permission_ids, true).uniq().each { |role| + roles.push role + } + } + return [] if roles.empty? + roles + end + + private + + def validate_permissions + return if !self.permission_ids + permission_ids.each { |permission_id| + permission = Permission.lookup(id: permission_id) + raise "Unable to find permission for id #{permission_id}" if !permission + raise "Permission #{permission.name} is disabled" if permission.preferences[:disabled] == true + next unless permission.preferences[:not] + permission.preferences[:not].each { |local_permission_name| + local_permission = Permission.lookup(name: local_permission_name) + next if !local_permission + raise "Permission #{permission.name} conflicts with #{local_permission.name}" if permission_ids.include?(local_permission.id) + } + } + end + end diff --git a/app/models/text_module.rb b/app/models/text_module.rb index bf5bf4734..713481a9a 100644 --- a/app/models/text_module.rb +++ b/app/models/text_module.rb @@ -14,6 +14,8 @@ load text modules from online =end def self.load(locale, overwrite_existing_item = false) + raise 'Got no locale' if locale.empty? + locale = locale.split(',').first.downcase # in case of accept_language header is given url = "https://i18n.zammad.com/api/v1/text_modules/#{locale}" result = UserAgent.get( diff --git a/app/models/ticket.rb b/app/models/ticket.rb index bbcd6447d..b544d68b3 100644 --- a/app/models/ticket.rb +++ b/app/models/ticket.rb @@ -3,6 +3,7 @@ class Ticket < ApplicationModel include Ticket::Escalation include Ticket::Subject + load 'ticket/permission.rb' include Ticket::Permission load 'ticket/assets.rb' include Ticket::Assets @@ -23,35 +24,40 @@ class Ticket < ApplicationModel latest_change_support - activity_stream_support ignore_attributes: { - organization_id: true, # organization_id will channge automatically on user update - create_article_type_id: true, - create_article_sender_id: true, - article_count: true, - first_response: true, - first_response_escal_date: true, - first_response_sla_time: true, - first_response_in_min: true, - first_response_diff_in_min: true, - close_time: true, - close_time_escal_date: true, - close_time_sla_time: true, - close_time_in_min: true, - close_time_diff_in_min: true, - update_time_escal_date: true, - update_time_sla_time: true, - update_time_in_min: true, - update_time_diff_in_min: true, - last_contact: true, - last_contact_agent: true, - last_contact_customer: true, - } + activity_stream_support( + permission: 'ticket.agent', + ignore_attributes: { + organization_id: true, # organization_id will channge automatically on user update + create_article_type_id: true, + create_article_sender_id: true, + article_count: true, + first_response: true, + first_response_escal_date: true, + first_response_sla_time: true, + first_response_in_min: true, + first_response_diff_in_min: true, + close_time: true, + close_time_escal_date: true, + close_time_sla_time: true, + close_time_in_min: true, + close_time_diff_in_min: true, + update_time_escal_date: true, + update_time_sla_time: true, + update_time_in_min: true, + update_time_diff_in_min: true, + last_contact: true, + last_contact_agent: true, + last_contact_customer: true, + } + ) - history_support ignore_attributes: { - create_article_type_id: true, - create_article_sender_id: true, - article_count: true, - } + history_support( + ignore_attributes: { + create_article_type_id: true, + create_article_sender_id: true, + article_count: true, + } + ) search_index_support @@ -85,10 +91,12 @@ returns =end def agent_of_group + roles = Role.with_permissions('ticket.agent') + role_ids = roles.map(&:id) Group.find(group_id) .users.where(active: true) .joins(:roles) - .where('roles.name' => Z_ROLENAME_AGENT, 'roles.active' => true) + .where('roles.id' => role_ids, 'roles.active' => true) .order('users.login') .uniq() end @@ -107,7 +115,7 @@ returns def self.access_condition(user) access_condition = [] - if user.role?(Z_ROLENAME_AGENT) + if user.permissions?('ticket.agent') group_ids = Group.select('groups.id').joins(:users) .where('groups_users.user_id = ?', user.id) .where('groups.active = ?', true) @@ -291,7 +299,7 @@ returns Ticket::Article.create( ticket_id: id, type_id: Ticket::Article::Type.lookup(name: 'note').id, - sender_id: Ticket::Article::Sender.lookup(name: Z_ROLENAME_AGENT).id, + sender_id: Ticket::Article::Sender.lookup(name: 'Agent').id, body: 'merged', internal: false, created_by_id: data[:user_id], diff --git a/app/models/ticket/activity_stream_log.rb b/app/models/ticket/activity_stream_log.rb index 14f0f4897..a20c58b62 100644 --- a/app/models/ticket/activity_stream_log.rb +++ b/app/models/ticket/activity_stream_log.rb @@ -14,7 +14,7 @@ returns =end - def activity_stream_log (type, user_id) + def activity_stream_log(type, user_id) # return if we run import mode return if Setting.get('import_mode') @@ -23,13 +23,13 @@ returns return if !Setting.get('system_init_done') return if !self.class.activity_stream_support_config - role = self.class.activity_stream_support_config[:role] + permission = self.class.activity_stream_support_config[:permission] ActivityStream.add( o_id: self['id'], type: type, object: self.class.name, group_id: self['group_id'], - role: role, + permission: permission, created_at: updated_at, created_by_id: user_id, ) diff --git a/app/models/ticket/article.rb b/app/models/ticket/article.rb index 84b91e1f4..b4c08605c 100644 --- a/app/models/ticket/article.rb +++ b/app/models/ticket/article.rb @@ -18,21 +18,26 @@ class Ticket::Article < ApplicationModel notify_clients_support - activity_stream_support ignore_attributes: { - type_id: true, - sender_id: true, - preferences: true, - } + activity_stream_support( + permission: 'ticket.agent', + ignore_attributes: { + type_id: true, + sender_id: true, + preferences: true, + } + ) - history_support ignore_attributes: { - type_id: true, - sender_id: true, - preferences: true, - message_id: true, - from: true, - to: true, - cc: true, - } + history_support( + ignore_attributes: { + type_id: true, + sender_id: true, + preferences: true, + message_id: true, + from: true, + to: true, + cc: true, + } + ) # fillup md5 of message id to search easier on very long message ids def check_message_id_md5 diff --git a/app/models/ticket/article/activity_stream_log.rb b/app/models/ticket/article/activity_stream_log.rb index 18d723c8f..843cbd022 100644 --- a/app/models/ticket/article/activity_stream_log.rb +++ b/app/models/ticket/article/activity_stream_log.rb @@ -23,14 +23,14 @@ returns return if !Setting.get('system_init_done') return if !self.class.activity_stream_support_config - role = self.class.activity_stream_support_config[:role] + permission = self.class.activity_stream_support_config[:permission] ticket = Ticket.lookup(id: ticket_id) ActivityStream.add( o_id: self['id'], type: type, object: self.class.name, group_id: ticket.group_id, - role: role, + permission: permission, created_at: updated_at, created_by_id: user_id, ) diff --git a/app/models/ticket/permission.rb b/app/models/ticket/permission.rb index f123f9144..06f192066 100644 --- a/app/models/ticket/permission.rb +++ b/app/models/ticket/permission.rb @@ -6,7 +6,7 @@ module Ticket::Permission check if user has access to ticket ticket = Ticket.find(123) - result = ticket.permission( :current_user => User.find(123) ) + result = ticket.permission(current_user: User.find(123)) returns @@ -17,7 +17,7 @@ returns def permission (data) # check customer - if data[:current_user].role?('Customer') + if data[:current_user].permissions?('ticket.customer') # access ok if its own ticket return true if customer_id == data[:current_user].id diff --git a/app/models/ticket/screen_options.rb b/app/models/ticket/screen_options.rb index 1d85eeea8..0fb91865b 100644 --- a/app/models/ticket/screen_options.rb +++ b/app/models/ticket/screen_options.rb @@ -80,7 +80,7 @@ returns # get group / user relations agents = {} - User.of_role('Agent').each { |user| + User.with_permissions('ticket.agent').each { |user| agents[ user.id ] = 1 } diff --git a/app/models/ticket/search.rb b/app/models/ticket/search.rb index bfe211b52..65b842ffb 100644 --- a/app/models/ticket/search.rb +++ b/app/models/ticket/search.rb @@ -102,7 +102,7 @@ returns query_extention['bool'] = {} query_extention['bool']['must'] = [] - if current_user.role?('Agent') + if current_user.permissions?('ticket.agent') groups = Group.joins(:users) .where('groups_users.user_id = ?', current_user.id) .where('groups.active = ?', true) diff --git a/app/models/token.rb b/app/models/token.rb index 4bce3ed3e..4e84b96db 100644 --- a/app/models/token.rb +++ b/app/models/token.rb @@ -3,6 +3,7 @@ class Token < ActiveRecord::Base before_create :generate_token belongs_to :user + store :preferences =begin @@ -17,9 +18,14 @@ returns create new persistent token token = Token.create( - action: 'CalendarSubscriptions', + action: 'api', persistent: true, user_id: user.id, + preferences: { + permission: { + 'user_preferences.calendar' => true, + } + } ) in case if you use it via an controller, e. g. you can verify via "curl -H "Authorization: Token token=33562a00d7eda2a7c2fb639b91c6bcb8422067b6" http://... @@ -36,6 +42,10 @@ check token user = Token.check(action: 'PasswordReset', name: 'TheTokenItSelf') +check api token with permissions + + user = Token.check(action: 'api', name: 'TheTokenItSelf', permission: 'admin.session') + returns user for who this token was created @@ -61,7 +71,16 @@ returns user = token.user # persistent token not valid if user is inative - return if token.persistent && user.active == false + if !data[:inactive_user] + return if token.persistent && user.active == false + end + + # add permission check + if data[:permission] + return if !user.permissions?(data[:permission]) + return if !token.preferences[:permission] + return if token.preferences[:permission][data[:permission]] != true + end # return token user user diff --git a/app/models/transaction/clearbit_enrichment.rb b/app/models/transaction/clearbit_enrichment.rb index 1ddb7a5e9..8e8ea859a 100644 --- a/app/models/transaction/clearbit_enrichment.rb +++ b/app/models/transaction/clearbit_enrichment.rb @@ -50,7 +50,7 @@ sync all users against clearbit =end def self.sync - users = User.of_role('Customer') + users = User.of_role(Role.signup_roles) users.each { |user| sync_user(user) } diff --git a/app/models/user.rb b/app/models/user.rb index 59c49425a..30f32c482 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -24,6 +24,7 @@ require 'digest/md5' # @property active [Boolean] The flag that shows the active state of the User. # @property note [String] The note or comment stored to the User. class User < ApplicationModel + load 'user/permission.rb' include User::Permission load 'user/assets.rb' include User::Assets @@ -31,8 +32,8 @@ class User < ApplicationModel load 'user/search_index.rb' include User::SearchIndex - before_create :check_name, :check_email, :check_login, :check_password, :check_preferences_default - before_update :check_password, :check_email, :check_login, :check_preferences_default + before_create :check_name, :check_email, :check_login, :check_password, :check_preferences_default, :validate_roles + before_update :check_password, :check_email, :check_login, :check_preferences_default, :validate_roles after_create :avatar_for_email_check after_update :avatar_for_email_check after_destroy :avatar_destroy @@ -41,6 +42,7 @@ class User < ApplicationModel has_and_belongs_to_many :groups, after_add: :cache_update, after_remove: :cache_update, class_name: 'Group' has_and_belongs_to_many :roles, after_add: [:cache_update, :check_notifications], after_remove: :cache_update, class_name: 'Role' has_and_belongs_to_many :organizations, after_add: :cache_update, after_remove: :cache_update, class_name: 'Organization' + #has_many :permissions, class_name: 'Permission', through: :roles, class_name: 'Role' has_many :tokens, after_add: :cache_update, after_remove: :cache_update has_many :authorizations, after_add: :cache_update, after_remove: :cache_update belongs_to :organization, class_name: 'Organization' @@ -48,7 +50,7 @@ class User < ApplicationModel store :preferences activity_stream_support( - role: Z_ROLENAME_ADMIN, + permission: 'admin.user', ignore_attributes: { last_login: true, login_failed: true, @@ -289,7 +291,7 @@ returns def self.create_from_hash!(hash) - roles = Role.where(name: 'Customer') + role_ids = Role.signup_role_ids url = '' if hash['info']['urls'] hash['info']['urls'].each { |_name, local_url| @@ -307,7 +309,7 @@ returns address: hash['info']['location'], note: hash['info']['description'], source: hash['provider'], - roles: roles, + role_ids: role_ids, updated_by_id: 1, created_by_id: 1, ) @@ -315,6 +317,109 @@ returns =begin +get all permissions of user + + user = User.find(123) + user.permissions + +returns + + { + 'permission.key' => true, + # ... + } + +=end + + def permissions + list = {} + Object.const_get('Permission').joins(:roles).where('roles.id IN (?)', role_ids).each { |permission| + next if permission.preferences[:selectable] == false + list[permission.name] = true + } + list + end + +=begin + +true or false for permission + + user = User.find(123) + user.permissions?('permission.key') # access to certain permission.key + user.permissions?(['permission.key1', 'permission.key2']) # access to permission.key1 or permission.key2 + + user.permissions?('permission') # access to all sub keys + +returns + + true|false + +=end + + def permissions?(key) + keys = key + names = [] + if key.class == String + keys = [key] + end + keys.each { |local_key| + permissions = Object.const_get('Permission').with_parents(local_key) + Object.const_get('Permission').joins(:roles).where('roles.id IN (?) AND permissions.name IN (?)', role_ids, permissions).each { |permission| + next if permission.preferences[:selectable] == false + return true + } + } + false + end + +=begin + +get all users with permission + + users = User.with_permissions('admin.session') + +get all users with permission "admin.session" or "ticket.agent" + + users = User.with_permissions(['admin.session', 'ticket.agent']) + +returns + + [user1, user2, ...] + +=end + + def self.with_permissions(keys) + if keys.class != Array + keys = [keys] + end + total_role_ids = [] + permission_ids = [] + keys.each { |key| + role_ids = [] + Object.const_get('Permission').with_parents(key).each { |local_key| + permission = Object.const_get('Permission').lookup(name: local_key) + next if !permission + permission_ids.push permission.id + } + next if permission_ids.empty? + Role.select('id').joins(:roles_permissions).where('permissions_roles.permission_id IN (?) AND roles.active = ?', permission_ids, true).uniq().each { |role| + role_ids.push role.id + } + total_role_ids.push role_ids + } + return [] if total_role_ids.empty? + condition = '' + total_role_ids.each { |_role_ids| + if condition != '' + condition += ' OR ' + end + condition += 'roles_users.role_id IN (?)' + } + User.joins(:users_roles).where("(#{condition}) AND users.active = ?", *total_role_ids, true).order(:id) + end + +=begin + generate new token for reset password result = User.password_reset_new_token(username) @@ -510,6 +615,8 @@ list of active users in role result = User.of_role('Agent', group_ids) + result = User.of_role(['Agent', 'Admin']) + returns result = [user1, user2] @@ -663,6 +770,20 @@ returns end end + def validate_roles + return if !role_ids + role_ids.each { |role_id| + role = Role.lookup(id: role_id) + raise "Unable to find role for id #{role_id}" if !role + next unless role.preferences[:not] + role.preferences[:not].each { |local_role_name| + local_role = Role.lookup(name: local_role_name) + next if !local_role + raise "Role #{role.name} conflicts with #{local_role.name}" if role_ids.include?(local_role.id) + } + } + end + def avatar_for_email_check return if !email diff --git a/app/models/user/permission.rb b/app/models/user/permission.rb index 9fcc70df3..4729ea5cf 100644 --- a/app/models/user/permission.rb +++ b/app/models/user/permission.rb @@ -19,7 +19,7 @@ returns def permission (data) # check customer - if data[:current_user].role?(Z_ROLENAME_CUSTOMER) + if data[:current_user].permissions?('ticket.customer') # access ok if its own user return true if id == data[:current_user].id @@ -29,8 +29,8 @@ returns end # check agent - return true if data[:current_user].role?(Z_ROLENAME_ADMIN) - return true if data[:current_user].role?('Agent') + return true if data[:current_user].permissions?('admin.user') + return true if data[:current_user].permissions?('ticket.agent') false end end diff --git a/app/models/user/search.rb b/app/models/user/search.rb index ac328087b..1bbce1552 100644 --- a/app/models/user/search.rb +++ b/app/models/user/search.rb @@ -23,7 +23,7 @@ returns if user has no permissions to search =end def search_preferences(current_user) - return false if !current_user.role?('Agent') && !current_user.role?(Z_ROLENAME_ADMIN) + return false if !current_user.permissions?('ticket.agent') && !current_user.permissions?('admin.user') { prio: 2000, direct_search_index: true, @@ -35,7 +35,7 @@ returns if user has no permissions to search search user result = User.search( - query: 'some search term' + query: 'some search term', limit: 15, current_user: user_model, ) diff --git a/config/initializers/core_zammad_constants.rb b/config/initializers/core_zammad_constants.rb deleted file mode 100644 index be6355374..000000000 --- a/config/initializers/core_zammad_constants.rb +++ /dev/null @@ -1,8 +0,0 @@ -# Copyright (C) 2014 Zammad Foundation, http://zammad-foundation.org/ - -# Prefix all zammad constants w/ Z_ - -# Prefix all rolenames with Z_ROLENAME -Z_ROLENAME_ADMIN = 'Admin'.freeze -Z_ROLENAME_AGENT = 'Agent'.freeze -Z_ROLENAME_CUSTOMER = 'Customer'.freeze diff --git a/db/migrate/20120101000001_create_base.rb b/db/migrate/20120101000001_create_base.rb index cfef0994a..83e476ab9 100644 --- a/db/migrate/20120101000001_create_base.rb +++ b/db/migrate/20120101000001_create_base.rb @@ -95,6 +95,8 @@ class CreateBase < ActiveRecord::Migration create_table :roles do |t| t.string :name, limit: 100, null: false + t.string :preferences, limit: 500.kilobytes + 1, null: true + t.boolean :default_at_signup, null: true, default: false t.boolean :active, null: false, default: true t.string :note, limit: 250, null: true t.integer :updated_by_id, null: false @@ -103,6 +105,19 @@ class CreateBase < ActiveRecord::Migration end add_index :roles, [:name], unique: true + create_table :permissions do |t| + t.string :name, limit: 255, null: false + t.string :note, limit: 500, null: true + t.string :preferences, limit: 10_000, null: true + t.timestamps + end + add_index :permissions, [:name], unique: true + + create_table :permissions_roles, id: false do |t| + t.belongs_to :role, index: true + t.belongs_to :permission, index: true + end + create_table :organizations do |t| t.string :name, limit: 100, null: false t.boolean :shared, null: false, default: true @@ -189,6 +204,7 @@ class CreateBase < ActiveRecord::Migration t.string :name, limit: 100, null: false t.string :action, limit: 40, null: false t.string :label, limit: 255, null: true + t.string :preferences, limit: 500.kilobytes + 1, null: true t.timestamps null: false end add_index :tokens, :user_id @@ -264,7 +280,7 @@ class CreateBase < ActiveRecord::Migration create_table :activity_streams do |t| t.references :activity_stream_type, null: false t.references :activity_stream_object, null: false - t.references :role, null: true + t.references :permission, null: true t.references :group, null: true t.integer :o_id, null: false t.integer :created_by_id, null: false @@ -272,7 +288,7 @@ class CreateBase < ActiveRecord::Migration end add_index :activity_streams, [:o_id] add_index :activity_streams, [:created_by_id] - add_index :activity_streams, [:role_id] + add_index :activity_streams, [:permission_id] add_index :activity_streams, [:group_id] add_index :activity_streams, [:created_at] add_index :activity_streams, [:activity_stream_object_id] diff --git a/db/migrate/20160805000001_add_permission.rb b/db/migrate/20160805000001_add_permission.rb new file mode 100644 index 000000000..d97ebb0ab --- /dev/null +++ b/db/migrate/20160805000001_add_permission.rb @@ -0,0 +1,376 @@ +class AddPermission < ActiveRecord::Migration + def change + + # return if it's a new setup + return if !Setting.find_by(name: 'system_init_done') + + create_table :permissions do |t| + t.string :name, limit: 255, null: false + t.string :note, limit: 500, null: true + t.string :preferences, limit: 10_000, null: true + t.timestamps + end + add_index :permissions, [:name], unique: true + + create_table :permissions_roles, id: false do |t| + t.belongs_to :role, index: true + t.belongs_to :permission, index: true + end + + Permission.create_or_update( + name: 'admin', + note: 'Admin Interface', + preferences: {}, + ) + Permission.create_or_update( + name: 'admin.user', + note: 'Manage %s', + preferences: { + translations: ['Users'] + }, + ) + Permission.create_or_update( + name: 'admin.group', + note: 'Manage %s', + preferences: { + translations: ['Groups'] + }, + ) + Permission.create_or_update( + name: 'admin.role', + note: 'Manage %s', + preferences: { + translations: ['Roles'] + }, + ) + Permission.create_or_update( + name: 'admin.organization', + note: 'Manage %s', + preferences: { + translations: ['Organizations'] + }, + ) + Permission.create_or_update( + name: 'admin.overview', + note: 'Manage %s', + preferences: { + translations: ['Overviews'] + }, + ) + Permission.create_or_update( + name: 'admin.text_module', + note: 'Manage %s', + preferences: { + translations: ['Text Modules'] + }, + ) + Permission.create_or_update( + name: 'admin.macro', + note: 'Manage %s', + preferences: { + translations: ['Macros'] + }, + ) + Permission.create_or_update( + name: 'admin.tag', + note: 'Manage %s', + preferences: { + translations: ['Tags'] + }, + ) + Permission.create_or_update( + name: 'admin.calendar', + note: 'Manage %s', + preferences: { + translations: ['Calendar'] + }, + ) + Permission.create_or_update( + name: 'admin.sla', + note: 'Manage %s', + preferences: { + translations: ['SLA'] + }, + ) + Permission.create_or_update( + name: 'admin.scheduler', + note: 'Manage %s', + preferences: { + translations: ['Scheduler'] + }, + ) + Permission.create_or_update( + name: 'admin.report_profile', + note: 'Manage %s', + preferences: { + translations: ['Report Profiles'] + }, + ) + Permission.create_or_update( + name: 'admin.channel_web', + note: 'Manage %s', + preferences: { + translations: ['Channel - Web'] + }, + ) + Permission.create_or_update( + name: 'admin.channel_formular', + note: 'Manage %s', + preferences: { + translations: ['Channel - Formular'] + }, + ) + Permission.create_or_update( + name: 'admin.channel_web', + note: 'Manage %s', + preferences: { + translations: ['Channel - Web'] + }, + ) + Permission.create_or_update( + name: 'admin.channel_email', + note: 'Manage %s', + preferences: { + translations: ['Channel - Email'] + }, + ) + Permission.create_or_update( + name: 'admin.channel_twitter', + note: 'Manage %s', + preferences: { + translations: ['Channel - Twitter'] + }, + ) + Permission.create_or_update( + name: 'admin.channel_facebook', + note: 'Manage %s', + preferences: { + translations: ['Channel - Facebook'] + }, + ) + Permission.create_or_update( + name: 'admin.channel_chat', + note: 'Manage %s', + preferences: { + translations: ['Channel - Chat'] + }, + ) + Permission.create_or_update( + name: 'admin.branding', + note: 'Manage %s', + preferences: { + translations: ['Branding'] + }, + ) + Permission.create_or_update( + name: 'admin.setting_system', + note: 'Manage %s Settings', + preferences: { + translations: ['System'] + }, + ) + Permission.create_or_update( + name: 'admin.security', + note: 'Manage %s Settings', + preferences: { + translations: ['Security'] + }, + ) + Permission.create_or_update( + name: 'admin.ticket', + note: 'Manage %s Settings', + preferences: { + translations: ['Ticket'] + }, + ) + Permission.create_or_update( + name: 'admin.package', + note: 'Manage %s', + preferences: { + translations: ['Packages'] + }, + ) + Permission.create_or_update( + name: 'admin.integration', + note: 'Manage %s', + preferences: { + translations: ['Integrations'] + }, + ) + Permission.create_or_update( + name: 'admin.api', + note: 'Manage %s', + preferences: { + translations: ['API'] + }, + ) + Permission.create_or_update( + name: 'admin.object', + note: 'Manage %s', + preferences: { + translations: ['Objects'] + }, + ) + Permission.create_or_update( + name: 'admin.translation', + note: 'Manage %s', + preferences: { + translations: ['Translations'] + }, + ) + Permission.create_or_update( + name: 'admin.maintenance', + note: 'Manage %s', + preferences: { + translations: ['Maintenance'] + }, + ) + Permission.create_or_update( + name: 'admin.session', + note: 'Manage %s', + preferences: { + translations: ['Sessions'] + }, + ) + Permission.create_or_update( + name: 'user_preferences', + note: 'User Preferences', + preferences: {}, + ) + Permission.create_or_update( + name: 'user_preferences.password', + note: 'Change %s', + preferences: { + translations: ['Password'] + }, + ) + Permission.create_or_update( + name: 'user_preferences.notifications', + note: 'Manage %s', + preferences: { + translations: ['Notifications'], + required: ['ticket.agent'], + }, + ) + Permission.create_or_update( + name: 'user_preferences.access_token', + note: 'Manage %s', + preferences: { + translations: ['Token Access'] + }, + ) + Permission.create_or_update( + name: 'user_preferences.language', + note: 'Change %s', + preferences: { + translations: ['Language'] + }, + ) + Permission.create_or_update( + name: 'user_preferences.linked_accounts', + note: 'Manage %s', + preferences: { + translations: ['Linked Accounts'] + }, + ) + Permission.create_or_update( + name: 'user_preferences.device', + note: 'Manage %s', + preferences: { + translations: ['Devices'] + }, + ) + Permission.create_or_update( + name: 'user_preferences.avatar', + note: 'Manage %s', + preferences: { + translations: ['Avatar'] + }, + ) + Permission.create_or_update( + name: 'user_preferences.calendar', + note: 'Access to %s', + preferences: { + translations: ['Calendars'], + required: ['ticket.agent'], + }, + ) + + Permission.create_or_update( + name: 'report', + note: 'Report Interface', + preferences: {}, + ) + Permission.create_or_update( + name: 'ticket', + note: 'Ticket Interface', + preferences: { + disabled: true + }, + ) + Permission.create_or_update( + name: 'ticket.agent', + note: 'Access to Agent Tickets based on Group Access', + preferences: { + not: ['ticket.customer'], + plugin: ['groups'] + }, + ) + Permission.create_or_update( + name: 'ticket.customer', + note: 'Access to Customer Tickets based on current_user and current_user.organization', + preferences: { + not: ['ticket.agent'], + }, + ) + Permission.create_or_update( + name: 'chat', + note: 'Access to %s', + preferences: { + translations: ['Chat'] + }, + ) + Permission.create_or_update( + name: 'chat.agent', + note: 'Access to %s', + preferences: { + translations: ['Chat'], + not: ['chat.customer'], + }, + ) + Permission.create_or_update( + name: 'cti', + note: 'CTI', + preferences: { + disabled: true + }, + ) + Permission.create_or_update( + name: 'cti.agent', + note: 'Access to %s', + preferences: { + translations: ['CTI'], + not: ['cti.customer'], + }, + ) + + admin = Role.find_by(name: 'Admin') + admin.permission_grand('user_preferences') + admin.permission_grand('admin') + admin.permission_grand('report') + + agent = Role.find_by(name: 'Agent') + agent.permission_grand('user_preferences') + agent.permission_grand('ticket.agent') + agent.permission_grand('chat.agent') + agent.permission_grand('cti.agent') + + customer = Role.find_by(name: 'Customer') + customer.permission_grand('user_preferences.password') + customer.permission_grand('user_preferences.language') + customer.permission_grand('user_preferences.linked_accounts') + customer.permission_grand('user_preferences.avatar') + customer.permission_grand('ticket.customer') + + end +end diff --git a/db/migrate/20160810000002_update_token.rb b/db/migrate/20160810000002_update_token.rb new file mode 100644 index 000000000..9ba3d2993 --- /dev/null +++ b/db/migrate/20160810000002_update_token.rb @@ -0,0 +1,9 @@ + +class UpdateToken < ActiveRecord::Migration + def up + # return if it's a new setup + return if !Setting.find_by(name: 'system_init_done') + + add_column :tokens, :preferences, :text, limit: 500.kilobytes + 1, null: true + end +end diff --git a/db/migrate/20160810000003_update_activity_stream.rb b/db/migrate/20160810000003_update_activity_stream.rb new file mode 100644 index 000000000..11a2a4e82 --- /dev/null +++ b/db/migrate/20160810000003_update_activity_stream.rb @@ -0,0 +1,34 @@ + +class UpdateActivityStream < ActiveRecord::Migration + def up + # return if it's a new setup + return if !Setting.find_by(name: 'system_init_done') + ActivityStream.destroy_all + add_column :activity_streams, :permission_id, :integer, null: true + remove_column :activity_streams, :role_id + + Setting.create_or_update( + title: 'sipgate.io integration', + name: 'sipgate_integration', + area: 'Integration::Switch', + description: 'Define if sipgate.io (http://www.sipgate.io) is enabled or not.', + options: { + form: [ + { + display: '', + null: true, + name: 'sipgate_integration', + tag: 'boolean', + options: { + true => 'yes', + false => 'no', + }, + }, + ], + }, + state: false, + preferences: { prio: 1, trigger: ['menu:render', 'cti:reload'] }, + frontend: false + ) + end +end diff --git a/db/migrate/20160811000001_update_role.rb b/db/migrate/20160811000001_update_role.rb new file mode 100644 index 000000000..690244212 --- /dev/null +++ b/db/migrate/20160811000001_update_role.rb @@ -0,0 +1,131 @@ + +class UpdateRole < ActiveRecord::Migration + def up + # return if it's a new setup + return if !Setting.find_by(name: 'system_init_done') + + add_column :roles, :preferences, :text, limit: 500.kilobytes + 1, null: true + add_column :roles, :default_at_signup, :boolean, null: true, default: false + + Role.create_or_update( + id: 1, + name: 'Admin', + note: 'To configure your system.', + preferences: { + not: ['Customer'], + }, + default_at_signup: false, + updated_by_id: 1, + created_by_id: 1 + ) + Role.create_or_update( + id: 2, + name: 'Agent', + note: 'To work on Tickets.', + default_at_signup: false, + preferences: { + not: ['Customer'], + }, + updated_by_id: 1, + created_by_id: 1 + ) + Role.create_or_update( + id: 3, + name: 'Customer', + note: 'People who create Tickets ask for help.', + preferences: { + not: %w(Agent Admin), + }, + default_at_signup: true, + updated_by_id: 1, + created_by_id: 1 + ) + Role.create_or_update( + id: 4, + name: 'Report', + note: 'Access the report area.', + preferences: { + not: ['Customer'], + }, + default_at_signup: false, + created_by_id: 1, + updated_by_id: 1, + ) + + ObjectManager::Attribute.add( + force: true, + object: 'Organization', + name: 'shared', + display: 'Shared organization', + data_type: 'boolean', + data_option: { + null: true, + default: true, + note: 'Customers in the organization can view each other items.', + item_class: 'formGroup--halfSize', + translate: true, + options: { + true: 'yes', + false: 'no', + } + }, + editable: false, + active: true, + screens: { + edit: { + Admin: { + null: false, + }, + }, + view: { + '-all-' => { + shown: true, + }, + }, + }, + to_create: false, + to_migrate: false, + to_delete: false, + position: 1400, + ) + + ObjectManager::Attribute.add( + force: true, + object: 'User', + name: 'role_ids', + display: 'Permissions', + data_type: 'user_permission', + data_option: { + null: false, + item_class: 'checkbox', + }, + editable: false, + active: true, + screens: { + signup: {}, + invite_agent: { + '-all-' => { + null: false, + default: [Role.lookup(name: 'Agent').id], + }, + }, + invite_customer: {}, + edit: { + Admin: { + null: true, + }, + }, + view: { + '-all-' => { + shown: false, + }, + }, + }, + to_create: false, + to_migrate: false, + to_delete: false, + position: 1600, + ) + + end +end diff --git a/db/seeds.rb b/db/seeds.rb index 2d1fbd20c..2efe9d784 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -1959,7 +1959,7 @@ Setting.create_if_not_exists( ], }, state: false, - preferences: { prio: 1, trigger: 'cti:reload' }, + preferences: { prio: 1, trigger: ['menu:render', 'cti:reload'] }, frontend: false ) Setting.create_if_not_exists( @@ -2126,20 +2126,358 @@ Role.create_if_not_exists( created_by_id: 1, updated_by_id: 1, ) -Role.create_if_not_exists( - id: 5, - name: 'Chat', - note: 'Access to chat feature.', - updated_by_id: 1, - created_by_id: 1 + +Permission.create_if_not_exists( + name: 'admin', + note: 'Admin Interface', + preferences: {}, ) -Role.create_if_not_exists( - id: 6, - name: 'CTI', - note: 'Access to CTI feature.', - updated_by_id: 1, - created_by_id: 1 +Permission.create_if_not_exists( + name: 'admin.user', + note: 'Manage %s', + preferences: { + translations: ['Users'] + }, ) +Permission.create_if_not_exists( + name: 'admin.group', + note: 'Manage %s', + preferences: { + translations: ['Groups'] + }, +) +Permission.create_if_not_exists( + name: 'admin.role', + note: 'Manage %s', + preferences: { + translations: ['Roles'] + }, +) +Permission.create_if_not_exists( + name: 'admin.organization', + note: 'Manage %s', + preferences: { + translations: ['Organizations'] + }, +) +Permission.create_if_not_exists( + name: 'admin.overview', + note: 'Manage %s', + preferences: { + translations: ['Overviews'] + }, +) +Permission.create_if_not_exists( + name: 'admin.text_module', + note: 'Manage %s', + preferences: { + translations: ['Text Modules'] + }, +) +Permission.create_if_not_exists( + name: 'admin.macro', + note: 'Manage %s', + preferences: { + translations: ['Macros'] + }, +) +Permission.create_if_not_exists( + name: 'admin.tag', + note: 'Manage %s', + preferences: { + translations: ['Tags'] + }, +) +Permission.create_if_not_exists( + name: 'admin.calendar', + note: 'Manage %s', + preferences: { + translations: ['Calendar'] + }, +) +Permission.create_if_not_exists( + name: 'admin.sla', + note: 'Manage %s', + preferences: { + translations: ['SLA'] + }, +) +Permission.create_if_not_exists( + name: 'admin.scheduler', + note: 'Manage %s', + preferences: { + translations: ['Scheduler'] + }, +) +Permission.create_if_not_exists( + name: 'admin.report_profile', + note: 'Manage %s', + preferences: { + translations: ['Report Profiles'] + }, +) +Permission.create_if_not_exists( + name: 'admin.channel_web', + note: 'Manage %s', + preferences: { + translations: ['Channel - Web'] + }, +) +Permission.create_if_not_exists( + name: 'admin.channel_formular', + note: 'Manage %s', + preferences: { + translations: ['Channel - Formular'] + }, +) +Permission.create_if_not_exists( + name: 'admin.channel_web', + note: 'Manage %s', + preferences: { + translations: ['Channel - Web'] + }, +) +Permission.create_if_not_exists( + name: 'admin.channel_email', + note: 'Manage %s', + preferences: { + translations: ['Channel - Email'] + }, +) +Permission.create_if_not_exists( + name: 'admin.channel_twitter', + note: 'Manage %s', + preferences: { + translations: ['Channel - Twitter'] + }, +) +Permission.create_if_not_exists( + name: 'admin.channel_facebook', + note: 'Manage %s', + preferences: { + translations: ['Channel - Facebook'] + }, +) +Permission.create_if_not_exists( + name: 'admin.channel_chat', + note: 'Manage %s', + preferences: { + translations: ['Channel - Chat'] + }, +) +Permission.create_if_not_exists( + name: 'admin.branding', + note: 'Manage %s', + preferences: { + translations: ['Branding'] + }, +) +Permission.create_if_not_exists( + name: 'admin.setting_system', + note: 'Manage %s Settings', + preferences: { + translations: ['System'] + }, +) +Permission.create_if_not_exists( + name: 'admin.security', + note: 'Manage %s Settings', + preferences: { + translations: ['Security'] + }, +) +Permission.create_if_not_exists( + name: 'admin.ticket', + note: 'Manage %s Settings', + preferences: { + translations: ['Ticket'] + }, +) +Permission.create_if_not_exists( + name: 'admin.package', + note: 'Manage %s', + preferences: { + translations: ['Packages'] + }, +) +Permission.create_if_not_exists( + name: 'admin.integration', + note: 'Manage %s', + preferences: { + translations: ['Integrations'] + }, +) +Permission.create_if_not_exists( + name: 'admin.api', + note: 'Manage %s', + preferences: { + translations: ['API'] + }, +) +Permission.create_if_not_exists( + name: 'admin.object', + note: 'Manage %s', + preferences: { + translations: ['Objects'] + }, +) +Permission.create_if_not_exists( + name: 'admin.translation', + note: 'Manage %s', + preferences: { + translations: ['Translations'] + }, +) +Permission.create_if_not_exists( + name: 'admin.maintenance', + note: 'Manage %s', + preferences: { + translations: ['Maintenance'] + }, +) +Permission.create_if_not_exists( + name: 'admin.session', + note: 'Manage %s', + preferences: { + translations: ['Sessions'] + }, +) +Permission.create_if_not_exists( + name: 'user_preferences', + note: 'User Preferences', + preferences: {}, +) +Permission.create_if_not_exists( + name: 'user_preferences.password', + note: 'Change %s', + preferences: { + translations: ['Password'] + }, +) +Permission.create_if_not_exists( + name: 'user_preferences.notifications', + note: 'Manage %s', + preferences: { + translations: ['Notifications'], + required: ['ticket.agent'], + }, +) +Permission.create_if_not_exists( + name: 'user_preferences.access_token', + note: 'Manage %s', + preferences: { + translations: ['Token Access'] + }, +) +Permission.create_if_not_exists( + name: 'user_preferences.language', + note: 'Change %s', + preferences: { + translations: ['Language'] + }, +) +Permission.create_if_not_exists( + name: 'user_preferences.linked_accounts', + note: 'Manage %s', + preferences: { + translations: ['Linked Accounts'] + }, +) +Permission.create_if_not_exists( + name: 'user_preferences.device', + note: 'Manage %s', + preferences: { + translations: ['Devices'] + }, +) +Permission.create_if_not_exists( + name: 'user_preferences.avatar', + note: 'Manage %s', + preferences: { + translations: ['Avatar'] + }, +) +Permission.create_if_not_exists( + name: 'user_preferences.calendar', + note: 'Access to %s', + preferences: { + translations: ['Calendars'], + required: ['ticket.agent'], + }, +) + +Permission.create_if_not_exists( + name: 'report', + note: 'Report Interface', + preferences: {}, +) +Permission.create_if_not_exists( + name: 'ticket', + note: 'Ticket Interface', + preferences: { + disabled: true + }, +) +Permission.create_if_not_exists( + name: 'ticket.agent', + note: 'Access to Agent Tickets based on Group Access', + preferences: { + not: ['ticket.customer'], + plugin: ['groups'] + }, +) +Permission.create_if_not_exists( + name: 'ticket.customer', + note: 'Access to Customer Tickets based on current_user.id and current_user.organization_id', + preferences: { + not: ['ticket.agent'], + }, +) +Permission.create_if_not_exists( + name: 'chat', + note: 'Access to %s', + preferences: { + translations: ['Chat'] + }, +) +Permission.create_if_not_exists( + name: 'chat.agent', + note: 'Access to %s', + preferences: { + translations: ['Chat'], + not: ['chat.customer'], + }, +) +Permission.create_if_not_exists( + name: 'cti', + note: 'CTI', + preferences: { + disabled: true + }, +) +Permission.create_if_not_exists( + name: 'cti.agent', + note: 'Access to %s', + preferences: { + translations: ['CTI'], + not: ['cti.customer'], + }, +) + +admin = Role.find_by(name: 'Admin') +admin.permission_grand('user_preferences') +admin.permission_grand('admin') +admin.permission_grand('report') + +agent = Role.find_by(name: 'Agent') +agent.permission_grand('user_preferences') +agent.permission_grand('ticket.agent') +agent.permission_grand('chat.agent') +agent.permission_grand('cti.agent') + +customer = Role.find_by(name: 'Customer') +customer.permission_grand('user_preferences') +customer.permission_grand('ticket.customer') Group.create_if_not_exists( id: 1, @@ -3765,10 +4103,7 @@ ObjectManager::Attribute.add( invite_agent: { '-all-' => { null: false, - hideMode: { - rolesSelected: ['Agent'], - rolesNot: ['Customer'], - } + default: [Role.lookup(name: 'Agent').id], }, }, invite_customer: {}, @@ -3866,9 +4201,10 @@ ObjectManager::Attribute.add( note: 'Customers in the organization can view each other items.', item_class: 'formGroup--halfSize', options: { - true: 'Yes', - false: 'No', - } + true: 'yes', + false: 'no', + }, + translate: true, }, editable: false, active: true, diff --git a/lib/auto_wizard.rb b/lib/auto_wizard.rb index a15c6eabb..509409a04 100644 --- a/lib/auto_wizard.rb +++ b/lib/auto_wizard.rb @@ -108,7 +108,7 @@ returns if admin_user.id == 1 if !user_data[:roles] && !user_data[:role_ids] - user_data[:roles] = Role.where(name: %w(Agent Admin Chat)) + user_data[:roles] = Role.where(name: %w(Agent Admin)) end if !user_data[:groups] && !user_data[:group_ids] user_data[:groups] = Group.all diff --git a/lib/facebook.rb b/lib/facebook.rb index ff77cdd14..3fcda92df 100644 --- a/lib/facebook.rb +++ b/lib/facebook.rb @@ -156,8 +156,8 @@ result else user_data[:firstname] = item_user['name'] end - user_data[:active] = true - user_data[:roles] = Role.where(name: 'Customer') + user_data[:active] = true + user_data[:role_ids] = Role.signup_role_ids user = User.create(user_data) end diff --git a/lib/sessions/backend/collections/base.rb b/lib/sessions/backend/collections/base.rb index eca18facc..6cd72f122 100644 --- a/lib/sessions/backend/collections/base.rb +++ b/lib/sessions/backend/collections/base.rb @@ -1,5 +1,5 @@ class Sessions::Backend::Collections::Base < Sessions::Backend::Base - class << self; attr_accessor :model, :roles, :not_roles end + class << self; attr_accessor :model, :permissions end def initialize(user, asset_lookup, client, client_id, ttl) @user = user @@ -22,24 +22,9 @@ class Sessions::Backend::Collections::Base < Sessions::Backend::Base def push - # check role based access - if self.class.roles - access = false - self.class.roles.each { |role| - next if !@user.role?(role) - access = true - break - } - return if !access - end - if self.class.not_roles - access = false - self.class.not_roles.each { |role| - next if @user.role?(role) - access = true - break - } - return if !access + # check permission based access + if self.class.permissions + return if !@user.permissions?(self.class.permissions) end # check timeout @@ -98,18 +83,11 @@ class Sessions::Backend::Collections::Base < Sessions::Backend::Base @model = model end - def self.add_if_role(role) - if !@roles - @roles = [] + def self.add_if_permission(key) + if !@permissions + @permissions = [] end - @roles.push role - end - - def self.add_if_not_role(role) - if !@not_roles - @not_roles = [] - end - @not_roles.push role + @permissions.push key end end diff --git a/lib/sessions/backend/collections/email_address.rb b/lib/sessions/backend/collections/email_address.rb index 092919e14..e7aacae66 100644 --- a/lib/sessions/backend/collections/email_address.rb +++ b/lib/sessions/backend/collections/email_address.rb @@ -1,4 +1,4 @@ class Sessions::Backend::Collections::EmailAddress < Sessions::Backend::Collections::Base model_set 'EmailAddress' - add_if_not_role 'Customer' + add_if_permission 'ticket.agent' end diff --git a/lib/sessions/backend/collections/macro.rb b/lib/sessions/backend/collections/macro.rb index 18c1af84b..a85f3fa60 100644 --- a/lib/sessions/backend/collections/macro.rb +++ b/lib/sessions/backend/collections/macro.rb @@ -1,4 +1,4 @@ class Sessions::Backend::Collections::Macro < Sessions::Backend::Collections::Base model_set 'Macro' - add_if_not_role 'Customer' + add_if_permission 'ticket.agent' end diff --git a/lib/sessions/backend/collections/permission.rb b/lib/sessions/backend/collections/permission.rb new file mode 100644 index 000000000..ec186485d --- /dev/null +++ b/lib/sessions/backend/collections/permission.rb @@ -0,0 +1,3 @@ +class Sessions::Backend::Collections::Permission < Sessions::Backend::Collections::Base + model_set 'Permission' +end diff --git a/lib/sessions/backend/collections/signature.rb b/lib/sessions/backend/collections/signature.rb index e244c6a55..7645b1de9 100644 --- a/lib/sessions/backend/collections/signature.rb +++ b/lib/sessions/backend/collections/signature.rb @@ -1,4 +1,4 @@ class Sessions::Backend::Collections::Signature < Sessions::Backend::Collections::Base model_set 'Signature' - add_if_not_role 'Customer' + add_if_permission 'ticket.agent' end diff --git a/lib/sessions/event/base.rb b/lib/sessions/event/base.rb index eba0821ec..c985bc9ff 100644 --- a/lib/sessions/event/base.rb +++ b/lib/sessions/event/base.rb @@ -49,7 +49,7 @@ class Sessions::Event::Base true end - def role_permission_check(role, event) + def permission_check(key, event) if !@session error = { event: "#{event}_error", @@ -81,7 +81,7 @@ class Sessions::Event::Base Sessions.send(@client_id, error) return end - if !user.role?(role) + if !user.permissions?(key) error = { event: "#{event}_error", data: { diff --git a/lib/sessions/event/chat_agent_state.rb b/lib/sessions/event/chat_agent_state.rb index a2661c4c4..90250fe8b 100644 --- a/lib/sessions/event/chat_agent_state.rb +++ b/lib/sessions/event/chat_agent_state.rb @@ -4,7 +4,7 @@ class Sessions::Event::ChatAgentState < Sessions::Event::ChatBase return super if super # check if user has permissions - return if !role_permission_check('Agent', 'chat') + return if !permission_check('chat.agent', 'chat') Chat::Agent.state(@session['id'], @payload['data']['active']) diff --git a/lib/sessions/event/chat_session_start.rb b/lib/sessions/event/chat_session_start.rb index 0b7188507..6d291668c 100644 --- a/lib/sessions/event/chat_session_start.rb +++ b/lib/sessions/event/chat_session_start.rb @@ -2,7 +2,7 @@ class Sessions::Event::ChatSessionStart < Sessions::Event::ChatBase def run return super if super - return if !role_permission_check('Agent', 'chat') + return if !permission_check('chat.agent', 'chat') # find first in waiting list chat_session = Chat::Session.where(state: 'waiting').order('created_at ASC').first diff --git a/lib/sessions/event/chat_status_agent.rb b/lib/sessions/event/chat_status_agent.rb index 3266af4e2..f78f47b83 100644 --- a/lib/sessions/event/chat_status_agent.rb +++ b/lib/sessions/event/chat_status_agent.rb @@ -4,7 +4,7 @@ class Sessions::Event::ChatStatusAgent < Sessions::Event::ChatBase return super if super # check if user has permissions - return if !role_permission_check('Agent', 'chat') + return if !permission_check('chat.agent', 'chat') # renew timestamps state = Chat::Agent.state(@session['id']) diff --git a/lib/sessions/event/maintenance.rb b/lib/sessions/event/maintenance.rb index fe8ba33d9..732346b1d 100644 --- a/lib/sessions/event/maintenance.rb +++ b/lib/sessions/event/maintenance.rb @@ -14,7 +14,7 @@ class Sessions::Event::Maintenance < Sessions::Event::Base def run # check if sender is admin - return if !role_permission_check('Admin', 'maintenance') + return if !permission_check('admin.maintenance', 'maintenance') Sessions.broadcast(@payload, 'public', @session['id']) false end diff --git a/lib/stats.rb b/lib/stats.rb index eb019cf29..580fdeeb8 100644 --- a/lib/stats.rb +++ b/lib/stats.rb @@ -27,7 +27,7 @@ returns ] # generate stats per agent - users = User.of_role('Agent') + users = User.with_permissions('ticket.agent') agent_count = 0 user_result = {} users.each { |user| diff --git a/lib/tweet_base.rb b/lib/tweet_base.rb index 10f4157f0..4a02eaedb 100644 --- a/lib/tweet_base.rb +++ b/lib/tweet_base.rb @@ -60,7 +60,7 @@ class TweetBase user_data[:note] = tweet_user.description user_data[:address] = tweet_user.location user_data[:active] = true - user_data[:roles] = Role.where(name: 'Customer') + user_data[:role_ids] = Role.signup_role_ids user = User.create(user_data) end diff --git a/test/controllers/api_auth_controller_test.rb b/test/controllers/api_auth_controller_test.rb index f24222dda..ee8d34c07 100644 --- a/test/controllers/api_auth_controller_test.rb +++ b/test/controllers/api_auth_controller_test.rb @@ -55,16 +55,18 @@ class ApiAuthControllerTest < ActionDispatch::IntegrationTest admin_credentials = ActionController::HttpAuthentication::Basic.encode_credentials('api-admin@example.com', 'adminpw') Setting.set('api_password_access', false) - get '/api/v1/settings', {}, @headers.merge('Authorization' => admin_credentials) + get '/api/v1/sessions', {}, @headers.merge('Authorization' => admin_credentials) assert_response(401) + result = JSON.parse(@response.body) + assert_equal(Hash, result.class) + assert_equal('API password access disabled!', result['error']) Setting.set('api_password_access', true) - get '/api/v1/settings', {}, @headers.merge('Authorization' => admin_credentials) + get '/api/v1/sessions', {}, @headers.merge('Authorization' => admin_credentials) assert_response(200) result = JSON.parse(@response.body) - assert_equal(Array, result.class) + assert_equal(Hash, result.class) assert(result) - end test 'basic auth - agent' do @@ -74,6 +76,9 @@ class ApiAuthControllerTest < ActionDispatch::IntegrationTest Setting.set('api_password_access', false) get '/api/v1/tickets', {}, @headers.merge('Authorization' => agent_credentials) assert_response(401) + result = JSON.parse(@response.body) + assert_equal(Hash, result.class) + assert_equal('API password access disabled!', result['error']) Setting.set('api_password_access', true) get '/api/v1/tickets', {}, @headers.merge('Authorization' => agent_credentials) @@ -81,7 +86,6 @@ class ApiAuthControllerTest < ActionDispatch::IntegrationTest result = JSON.parse(@response.body) assert_equal(Array, result.class) assert(result) - end test 'basic auth - customer' do @@ -91,6 +95,9 @@ class ApiAuthControllerTest < ActionDispatch::IntegrationTest Setting.set('api_password_access', false) get '/api/v1/tickets', {}, @headers.merge('Authorization' => customer_credentials) assert_response(401) + result = JSON.parse(@response.body) + assert_equal(Hash, result.class) + assert_equal('API password access disabled!', result['error']) Setting.set('api_password_access', true) get '/api/v1/tickets', {}, @headers.merge('Authorization' => customer_credentials) @@ -98,29 +105,80 @@ class ApiAuthControllerTest < ActionDispatch::IntegrationTest result = JSON.parse(@response.body) assert_equal(Array, result.class) assert(result) - end test 'token auth - admin' do admin_token = Token.create( - action: 'api', - persistent: true, - user_id: @admin.id, + action: 'api', + persistent: true, + user_id: @admin.id, + preferences: { + permission: { + 'admin.session' => true, + } + }, ) admin_credentials = "Token token=#{admin_token.name}" Setting.set('api_token_access', false) - get '/api/v1/settings', {}, @headers.merge('Authorization' => admin_credentials) + get '/api/v1/sessions', {}, @headers.merge('Authorization' => admin_credentials) assert_response(401) + result = JSON.parse(@response.body) + assert_equal(Hash, result.class) + assert_equal('API token access disabled!', result['error']) Setting.set('api_token_access', true) - get '/api/v1/settings', {}, @headers.merge('Authorization' => admin_credentials) + get '/api/v1/sessions', {}, @headers.merge('Authorization' => admin_credentials) assert_response(200) result = JSON.parse(@response.body) - assert_equal(Array, result.class) + assert_equal(Hash, result.class) assert(result) + admin_token.preferences[:permission]['admin.session'] = false + admin_token.save! + + get '/api/v1/sessions', {}, @headers.merge('Authorization' => admin_credentials) + assert_response(401) + result = JSON.parse(@response.body) + assert_equal(Hash, result.class) + assert_equal('No permission!', result['error']) + + admin_token.preferences[:permission] = {} + admin_token.save! + + get '/api/v1/sessions', {}, @headers.merge('Authorization' => admin_credentials) + assert_response(401) + result = JSON.parse(@response.body) + assert_equal(Hash, result.class) + assert_equal('No permission!', result['error']) + + @admin.active = false + @admin.save! + + get '/api/v1/sessions', {}, @headers.merge('Authorization' => admin_credentials) + assert_response(401) + result = JSON.parse(@response.body) + assert_equal(Hash, result.class) + assert_equal('User is inactive!', result['error']) + + admin_token.preferences[:permission]['admin.session'] = true + admin_token.save! + + get '/api/v1/sessions', {}, @headers.merge('Authorization' => admin_credentials) + assert_response(401) + result = JSON.parse(@response.body) + assert_equal(Hash, result.class) + assert_equal('User is inactive!', result['error']) + + @admin.active = true + @admin.save! + + get '/api/v1/sessions', {}, @headers.merge('Authorization' => admin_credentials) + assert_response(200) + result = JSON.parse(@response.body) + assert_equal(Hash, result.class) + assert(result) end test 'token auth - agent' do @@ -135,6 +193,9 @@ class ApiAuthControllerTest < ActionDispatch::IntegrationTest Setting.set('api_token_access', false) get '/api/v1/tickets', {}, @headers.merge('Authorization' => agent_credentials) assert_response(401) + result = JSON.parse(@response.body) + assert_equal(Hash, result.class) + assert_equal('API token access disabled!', result['error']) Setting.set('api_token_access', true) get '/api/v1/tickets', {}, @headers.merge('Authorization' => agent_credentials) @@ -142,7 +203,6 @@ class ApiAuthControllerTest < ActionDispatch::IntegrationTest result = JSON.parse(@response.body) assert_equal(Array, result.class) assert(result) - end test 'token auth - customer' do @@ -157,6 +217,9 @@ class ApiAuthControllerTest < ActionDispatch::IntegrationTest Setting.set('api_token_access', false) get '/api/v1/tickets', {}, @headers.merge('Authorization' => customer_credentials) assert_response(401) + result = JSON.parse(@response.body) + assert_equal(Hash, result.class) + assert_equal('API token access disabled!', result['error']) Setting.set('api_token_access', true) get '/api/v1/tickets', {}, @headers.merge('Authorization' => customer_credentials) @@ -164,7 +227,6 @@ class ApiAuthControllerTest < ActionDispatch::IntegrationTest result = JSON.parse(@response.body) assert_equal(Array, result.class) assert(result) - end test 'token auth - invalid user - admin' do @@ -180,13 +242,18 @@ class ApiAuthControllerTest < ActionDispatch::IntegrationTest @admin.save! Setting.set('api_token_access', false) - get '/api/v1/settings', {}, @headers.merge('Authorization' => admin_credentials) + get '/api/v1/sessions', {}, @headers.merge('Authorization' => admin_credentials) assert_response(401) + result = JSON.parse(@response.body) + assert_equal(Hash, result.class) + assert_equal('API token access disabled!', result['error']) Setting.set('api_token_access', true) - get '/api/v1/settings', {}, @headers.merge('Authorization' => admin_credentials) + get '/api/v1/sessions', {}, @headers.merge('Authorization' => admin_credentials) assert_response(401) - + result = JSON.parse(@response.body) + assert_equal(Hash, result.class) + assert_equal('User is inactive!', result['error']) end end diff --git a/test/controllers/packages_controller_test.rb b/test/controllers/packages_controller_test.rb index 84fd39122..7b31d8ee2 100644 --- a/test/controllers/packages_controller_test.rb +++ b/test/controllers/packages_controller_test.rb @@ -50,18 +50,19 @@ class PackagesControllerTest < ActionDispatch::IntegrationTest end - test 'packages index with nobody' do + test '01 packages index with nobody' do # index get '/api/v1/packages', {}, @headers assert_response(401) - result = JSON.parse(@response.body) - assert_equal(result.class, Hash) - assert_not(result['packages']) + result = JSON.parse(@response.body) + assert_equal(Hash, result.class) + assert_not(result['packages']) + assert_equal('authentication failed', result['error']) end - test 'packages index with admin' do + test '02 packages index with admin' do credentials = ActionController::HttpAuthentication::Basic.encode_credentials('packages-admin@example.com', 'adminpw') @@ -69,35 +70,62 @@ class PackagesControllerTest < ActionDispatch::IntegrationTest get '/api/v1/packages', {}, @headers.merge('Authorization' => credentials) assert_response(200) result = JSON.parse(@response.body) - assert_equal(result.class, Hash) + assert_equal(Hash, result.class) assert(result['packages']) - end - test 'packages index with agent' do + test '03 packages index with admin and wrong pw' do - credentials = ActionController::HttpAuthentication::Basic.encode_credentials('packages-agent@example.com', 'adminpw') + credentials = ActionController::HttpAuthentication::Basic.encode_credentials('packages-admin@example.com', 'wrongadminpw') # index get '/api/v1/packages', {}, @headers.merge('Authorization' => credentials) assert_response(401) result = JSON.parse(@response.body) - assert_equal(result.class, Hash) - assert_not(result['packages']) - + assert_equal(Hash, result.class) + assert_equal('authentication failed', result['error']) end - test 'packages index with customer' do + test '04 packages index with inactive admin' do + @admin.active = false + @admin.save! + + credentials = ActionController::HttpAuthentication::Basic.encode_credentials('packages-admin@example.com', 'adminpw') + + # index + get '/api/v1/packages', {}, @headers.merge('Authorization' => credentials) + assert_response(401) + result = JSON.parse(@response.body) + assert_equal(Hash, result.class) + assert_equal('authentication failed', result['error']) + end + + test '05 packages index with agent' do + + credentials = ActionController::HttpAuthentication::Basic.encode_credentials('packages-agent@example.com', 'agentpw') + + # index + get '/api/v1/packages', {}, @headers.merge('Authorization' => credentials) + + assert_response(401) + result = JSON.parse(@response.body) + assert_equal(Hash, result.class) + assert_not(result['packages']) + assert_equal('No permission!', result['error']) + end + + test '06 packages index with customer' do credentials = ActionController::HttpAuthentication::Basic.encode_credentials('packages-customer1@example.com', 'customer1pw') # index get '/api/v1/packages', {}, @headers.merge('Authorization' => credentials) + assert_response(401) result = JSON.parse(@response.body) - assert_equal(result.class, Hash) + assert_equal(Hash, result.class) assert_not(result['packages']) - + assert_equal('No permission!', result['error']) end end diff --git a/test/controllers/search_controller_test.rb b/test/controllers/search_controller_test.rb index ea0da700b..e4431b61a 100644 --- a/test/controllers/search_controller_test.rb +++ b/test/controllers/search_controller_test.rb @@ -201,20 +201,23 @@ class SearchControllerTest < ActionDispatch::IntegrationTest post '/api/v1/search/ticket', params.to_json, @headers assert_response(401) result = JSON.parse(@response.body) - assert_equal(result.class, Hash) + assert_equal(Hash, result.class) assert_not(result.empty?) + assert_equal('authentication failed', result['error']) post '/api/v1/search/user', params.to_json, @headers assert_response(401) result = JSON.parse(@response.body) - assert_equal(result.class, Hash) + assert_equal(Hash, result.class) assert_not(result.empty?) + assert_equal('authentication failed', result['error']) post '/api/v1/search', params.to_json, @headers assert_response(401) result = JSON.parse(@response.body) - assert_equal(result.class, Hash) + assert_equal(Hash, result.class) assert_not(result.empty?) + assert_equal('authentication failed', result['error']) end diff --git a/test/controllers/settings_controller_test.rb b/test/controllers/settings_controller_test.rb index 8cfbfb393..b276bacbc 100644 --- a/test/controllers/settings_controller_test.rb +++ b/test/controllers/settings_controller_test.rb @@ -56,9 +56,8 @@ class SettingsControllerTest < ActionDispatch::IntegrationTest get '/api/v1/settings', {}, @headers assert_response(401) result = JSON.parse(@response.body) - assert_equal(result.class, Hash) + assert_equal(Hash, result.class) assert_not(result['settings']) - end test 'settings index with admin' do @@ -71,7 +70,6 @@ class SettingsControllerTest < ActionDispatch::IntegrationTest result = JSON.parse(@response.body) assert_equal(Array, result.class) assert(result) - end test 'settings index with agent' do @@ -82,9 +80,9 @@ class SettingsControllerTest < ActionDispatch::IntegrationTest get '/api/v1/settings', {}, @headers.merge('Authorization' => credentials) assert_response(401) result = JSON.parse(@response.body) - assert_equal(result.class, Hash) + assert_equal(Hash, result.class) assert_not(result['settings']) - + assert_equal('No permission!', result['error']) end test 'settings index with customer' do @@ -95,9 +93,9 @@ class SettingsControllerTest < ActionDispatch::IntegrationTest get '/api/v1/settings', {}, @headers.merge('Authorization' => credentials) assert_response(401) result = JSON.parse(@response.body) - assert_equal(result.class, Hash) + assert_equal(Hash, result.class) assert_not(result['settings']) - + assert_equal('No permission!', result['error']) end end diff --git a/test/integration/auto_wizard_test.rb b/test/integration/auto_wizard_test.rb index 1c64d49d9..b47d62701 100644 --- a/test/integration/auto_wizard_test.rb +++ b/test/integration/auto_wizard_test.rb @@ -46,7 +46,7 @@ class AutoWizardTest < ActiveSupport::TestCase assert_equal(false, AutoWizard.enabled?) # check first user roles - auto_wizard_data[:Users][0][:roles] = %w(Agent Admin Chat) + auto_wizard_data[:Users][0][:roles] = %w(Agent Admin) auto_wizard_data[:Users].each { |local_user| user = User.find_by(login: local_user[:login]) diff --git a/test/integration/sipgate_controller_test.rb b/test/integration/sipgate_controller_test.rb index eae662591..c79d90d45 100644 --- a/test/integration/sipgate_controller_test.rb +++ b/test/integration/sipgate_controller_test.rb @@ -68,7 +68,7 @@ class SipgateControllerTest < ActionDispatch::IntegrationTest ) groups = Group.where(name: 'Users') - roles = Role.where(name: %w(Agent CTI)) + roles = Role.where(name: %w(Agent)) agent = User.create_or_update( login: 'cti-agent@example.com', firstname: 'E', diff --git a/test/unit/chat_test.rb b/test/unit/chat_test.rb index 162b07031..faab5a402 100644 --- a/test/unit/chat_test.rb +++ b/test/unit/chat_test.rb @@ -8,7 +8,7 @@ class ChatTest < ActiveSupport::TestCase # create base groups = Group.all - roles = Role.where( name: %w(Agent Chat) ) + roles = Role.where( name: %w(Agent) ) agent1 = User.create_or_update( login: 'ticket-chat-agent1@example.com', firstname: 'Notification', diff --git a/test/unit/permission_test.rb b/test/unit/permission_test.rb new file mode 100644 index 000000000..fc9fc340c --- /dev/null +++ b/test/unit/permission_test.rb @@ -0,0 +1,13 @@ +# encoding: utf-8 +require 'test_helper' + +class PermissionTest < ActiveSupport::TestCase + + test 'permission' do + permissions = Permission.with_parents('some_key.sub_key') + assert_equal('some_key', permissions[0]) + assert_equal('some_key.sub_key', permissions[1]) + assert_equal(2, permissions.count) + end + +end diff --git a/test/unit/role_test.rb b/test/unit/role_test.rb new file mode 100644 index 000000000..27494690f --- /dev/null +++ b/test/unit/role_test.rb @@ -0,0 +1,119 @@ +# encoding: utf-8 +require 'test_helper' + +class RoleTest < ActiveSupport::TestCase + test 'permission' do + + permission_test = Permission.create_or_update( + name: 'test', + note: 'parent test permission', + preferences: { + disabled: true + }, + ) + permission_test_agent = Permission.create_or_update( + name: 'test.agent', + note: 'agent test permission', + preferences: { + not: ['test.customer'], + }, + ) + permission_test_customer = Permission.create_or_update( + name: 'test.customer', + note: 'customer test permission', + preferences: { + not: ['test.agent'], + }, + ) + permission_test_normal = Permission.create_or_update( + name: 'test.normal', + note: 'normal test permission', + preferences: {}, + ) + + assert_raises(RuntimeError) { + Role.create( + name: 'Test1', + note: 'Test1 Role.', + permissions: [permission_test], + updated_by_id: 1, + created_by_id: 1 + ) + } + assert_raises(RuntimeError) { + Role.create( + name: 'Test1', + note: 'Test1 Role.', + permissions: [permission_test_agent, permission_test_customer], + updated_by_id: 1, + created_by_id: 1 + ) + } + assert_raises(RuntimeError) { + Role.create( + name: 'Test1', + note: 'Test1 Role.', + permissions: [permission_test_normal, permission_test_agent, permission_test_customer], + updated_by_id: 1, + created_by_id: 1 + ) + } + role11 = Role.create( + name: 'Test1.1', + note: 'Test1.1 Role.', + permissions: [permission_test_agent], + updated_by_id: 1, + created_by_id: 1 + ) + role12 = Role.create( + name: 'Test1.2', + note: 'Test1.2 Role.', + permissions: [permission_test_customer], + updated_by_id: 1, + created_by_id: 1 + ) + role13 = Role.create( + name: 'Test1.3', + note: 'Test1.3 Role.', + permissions: [permission_test_normal], + updated_by_id: 1, + created_by_id: 1 + ) + role14 = Role.create( + name: 'Test1.4', + note: 'Test1.4 Role.', + permissions: [permission_test_normal, permission_test_customer], + updated_by_id: 1, + created_by_id: 1 + ) + + end + + test 'permission default' do + roles = Role.with_permissions('not_existing') + assert(roles.empty?) + + roles = Role.with_permissions('admin') + assert_equal('Admin', roles.first.name) + + roles = Role.with_permissions('admin.session') + assert_equal('Admin', roles.first.name) + + roles = Role.with_permissions(['admin.session', 'not_existing']) + assert_equal('Admin', roles.first.name) + + roles = Role.with_permissions('ticket.agent') + assert_equal('Agent', roles.first.name) + + roles = Role.with_permissions(['ticket.agent', 'not_existing']) + assert_equal('Agent', roles.first.name) + + roles = Role.with_permissions('ticket.customer') + assert_equal('Customer', roles.first.name) + + roles = Role.with_permissions(['ticket.customer', 'not_existing']) + assert_equal('Customer', roles.first.name) + + end + +end diff --git a/test/unit/ticket_trigger_test.rb b/test/unit/ticket_trigger_test.rb index 6a08086d3..4a7f06970 100644 --- a/test/unit/ticket_trigger_test.rb +++ b/test/unit/ticket_trigger_test.rb @@ -704,7 +704,7 @@ class TicketTriggerTest < ActiveSupport::TestCase assert_equal('2 normal', ticket_p.priority.name, 'ticket_p.priority verify') assert_equal(2, ticket_p.articles.count, 'ticket_p.articles verify') - p ticket_p.articles.last.inspect + #p ticket_p.articles.last.inspect article_p = ticket_p.articles.last assert_match('Owner has changed', article_p.subject) assert_match('Zammad ', article_p.from) @@ -783,7 +783,7 @@ class TicketTriggerTest < ActiveSupport::TestCase assert_equal('3 high', ticket_p.priority.name, 'ticket_p.priority verify') assert_equal(2, ticket_p.articles.count, 'ticket_p.articles verify') - p ticket_p.articles.last.inspect + #p ticket_p.articles.last.inspect article_p = ticket_p.articles.last assert_match('Owner has changed', article_p.subject) assert_match('Zammad ', article_p.from) @@ -867,7 +867,7 @@ class TicketTriggerTest < ActiveSupport::TestCase assert_equal('3 high', ticket_p.priority.name, 'ticket_p.priority verify') assert_equal(2, ticket_p.articles.count, 'ticket_p.articles verify') - p ticket_p.articles.last.inspect + #p ticket_p.articles.last.inspect article_p = ticket_p.articles.last assert_match('Owner has changed', article_p.subject) assert_match('Zammad ', article_p.from) diff --git a/test/unit/token_test.rb b/test/unit/token_test.rb index 9e5504d0c..e13b4a2bb 100644 --- a/test/unit/token_test.rb +++ b/test/unit/token_test.rb @@ -1,110 +1,122 @@ # encoding: utf-8 -# rubocop:disable Next require 'test_helper' class TokenTest < ActiveSupport::TestCase test 'token' do - tests = [ + groups = Group.all + roles = Role.where(name: 'Agent') + agent1 = User.create_or_update( + login: 'token-agent1@example.com', + firstname: 'Token', + lastname: 'Agent1', + email: 'token-agent1@example.com', + password: 'agentpw', + active: true, + roles: roles, + groups: groups, + updated_by_id: 1, + created_by_id: 1, + ) - # test 1 - { - test_name: 'invalid token', - action: 'PasswordReset', - name: '1NV4L1D', - result: nil, - }, + # invalid token + user = Token.check( + action: 'PasswordReset', + name: '1NV4L1D', + ) + assert_not(user) - # test 2 - { - test_name: 'fresh token', - create: { - user_id: 2, - action: 'PasswordReset', - }, - action: 'PasswordReset', - result: true, - verify: { - firstname: 'Nicole', - lastname: 'Braun', - email: 'nicole.braun@zammad.org', + # generate fresh token + token = Token.create( + action: 'PasswordReset', + user_id: agent1.id, + ) + assert(token) + assert_equal(nil, token.persistent) + user = Token.check( + action: 'PasswordReset_NotExisting', + name: token.name, + ) + assert_not(user) + user = Token.check( + action: 'PasswordReset', + name: token.name, + ) + assert(user) + assert_equal('Token', user.firstname) + assert_equal('Agent1', user.lastname) + assert_equal('token-agent1@example.com', user.email) + + # two days but not persistent + token = Token.create( + action: 'PasswordReset', + user_id: agent1.id, + created_at: 2.days.ago, + persistent: false, + ) + user = Token.check( + action: 'PasswordReset', + name: token.name, + ) + assert_not(user) + + # two days but persistent + token = Token.create( + action: 'iCal', + user_id: agent1.id, + created_at: 2.days.ago, + persistent: true, + ) + user = Token.check( + action: 'iCal', + name: token.name, + ) + assert(user) + assert_equal('Token', user.firstname) + assert_equal('Agent1', user.lastname) + assert_equal('token-agent1@example.com', user.email) + + # api token with permissions + token = Token.create( + action: 'api', + label: 'some label', + persistent: true, + user_id: agent1.id, + preferences: { + permission: { + 'admin' => true, # agent has no access to admin.* + 'ticket.agent' => true, } - }, + } + ) + user = Token.check( + action: 'api', + name: token.name, + permission: 'admin.session', + ) + assert_not(user) + user = Token.check( + action: 'api', + name: token.name, + permission: 'admin', + ) + assert_not(user) + user = Token.check( + action: 'api', + name: token.name, + permission: 'ticket', + ) + assert_not(user) + user = Token.check( + action: 'api', + name: token.name, + permission: 'ticket.agent', + ) + assert(user) + assert_equal('Token', user.firstname) + assert_equal('Agent1', user.lastname) + assert_equal('token-agent1@example.com', user.email) - # test 3 - { - test_name: 'two days but not persistent', - create: { - user_id: 2, - action: 'PasswordReset', - created_at: 2.days.ago, - }, - action: 'PasswordReset', - result: nil, - }, - - { - test_name: 'two days but persistent', - create: { - user_id: 2, - action: 'iCal', - created_at: 2.days.ago, - persistent: true, - }, - action: 'iCal', - result: true, - verify: { - firstname: 'Nicole', - lastname: 'Braun', - email: 'nicole.braun@zammad.org', - } - }, - ] - - tests.each { |test| - - if test[:create] - - #puts test[:test_name] + ': creating token '+ test[:create].inspect - - token = Token.create( - action: test[:create][:action], - user_id: test[:create][:user_id], - created_at: test[:create][:created_at].to_s, - persistent: test[:create][:persistent] - ) - - #puts test[:test_name] + ': created token ' + token.inspect - - test[:name] = token.name - end - - user = Token.check( - action: test[:action], - name: test[:name] - ) - - if test[:result] == true - if !user - assert(false, test[:test_name] + ': token verification failed') - else - test[:verify].each { |key, value| - assert_equal(user[key], value, 'verify') - } - end - else - assert_equal(test[:result], user, test[:test_name] + ': failed or not existing') - end - - if test[:name] - #puts test[:test_name] + ': deleting token '+ test[:name] - - token = Token.find_by(name: test[:name]) - - if token - token.destroy - end - end - } end + end diff --git a/test/unit/user_device_test.rb b/test/unit/user_device_test.rb index c1e941a95..cd734e971 100644 --- a/test/unit/user_device_test.rb +++ b/test/unit/user_device_test.rb @@ -3,12 +3,10 @@ require 'test_helper' class UserDeviceTest < ActiveSupport::TestCase setup do - # create agent - groups = Group.all - roles = Role.where(name: 'Agent') - UserInfo.current_user_id = 1 + groups = Group.all + roles = Role.where(name: 'Agent') @agent = User.create_or_update( login: 'user-device-agent@example.com', firstname: 'UserDevice', @@ -19,6 +17,17 @@ class UserDeviceTest < ActiveSupport::TestCase roles: roles, groups: groups, ) + + roles = Role.where(name: 'Customer') + @customer = User.create_or_update( + login: 'user-device-customer@example.com', + firstname: 'UserDevice', + lastname: 'Customer', + email: 'user-device-customer@example.com', + password: 'customerpw', + active: true, + roles: roles, + ) end test 'aaa - session test' do diff --git a/test/unit/user_test.rb b/test/unit/user_test.rb index 1c23ee0b8..b15dbd160 100644 --- a/test/unit/user_test.rb +++ b/test/unit/user_test.rb @@ -345,4 +345,196 @@ class UserTest < ActiveSupport::TestCase end + test 'permission' do + test_role_1 = Role.create_or_update( + name: 'Test1', + note: 'To configure your system.', + preferences: { + not: ['Test3'], + }, + updated_by_id: 1, + created_by_id: 1 + ) + test_role_2 = Role.create_or_update( + name: 'Test2', + note: 'To work on Tickets.', + preferences: { + not: ['Test3'], + }, + updated_by_id: 1, + created_by_id: 1 + ) + test_role_3 = Role.create_or_update( + name: 'Test3', + note: 'People who create Tickets ask for help.', + preferences: { + not: %w(Test1 Test2), + }, + updated_by_id: 1, + created_by_id: 1 + ) + test_role_4 = Role.create_or_update( + name: 'Test4', + note: 'Access the report area.', + preferences: {}, + created_by_id: 1, + updated_by_id: 1, + ) + assert_raises(RuntimeError) { + User.create_or_update( + login: 'customer-role1@example.com', + firstname: 'Role', + lastname: 'Customer1', + email: 'customer-role1@example.com', + password: 'customerpw', + active: true, + roles: [test_role_1, test_role_3], + updated_by_id: 1, + created_by_id: 1, + ) + } + assert_raises(RuntimeError) { + User.create_or_update( + login: 'customer-role1@example.com', + firstname: 'Role', + lastname: 'Customer1', + email: 'customer-role1@example.com', + password: 'customerpw', + active: true, + roles: [test_role_2, test_role_3], + updated_by_id: 1, + created_by_id: 1, + ) + } + user1 = User.create_or_update( + login: 'customer-role1@example.com', + firstname: 'Role', + lastname: 'Customer1', + email: 'customer-role1@example.com', + password: 'customerpw', + active: true, + roles: [test_role_1, test_role_2], + updated_by_id: 1, + created_by_id: 1, + ) + assert(user1.role_ids.include?(test_role_1.id)) + assert(user1.role_ids.include?(test_role_2.id)) + assert_not(user1.role_ids.include?(test_role_3.id)) + assert_not(user1.role_ids.include?(test_role_4.id)) + user1 = User.create_or_update( + login: 'customer-role1@example.com', + firstname: 'Role', + lastname: 'Customer1', + email: 'customer-role1@example.com', + password: 'customerpw', + active: true, + roles: [test_role_1, test_role_4], + updated_by_id: 1, + created_by_id: 1, + ) + assert(user1.role_ids.include?(test_role_1.id)) + assert_not(user1.role_ids.include?(test_role_2.id)) + assert_not(user1.role_ids.include?(test_role_3.id)) + assert(user1.role_ids.include?(test_role_4.id)) + assert_raises(RuntimeError) { + User.create_or_update( + login: 'customer-role1@example.com', + firstname: 'Role', + lastname: 'Customer1', + email: 'customer-role1@example.com', + password: 'customerpw', + active: true, + roles: [test_role_1, test_role_3], + updated_by_id: 1, + created_by_id: 1, + ) + } + assert_raises(RuntimeError) { + User.create_or_update( + login: 'customer-role1@example.com', + firstname: 'Role', + lastname: 'Customer1', + email: 'customer-role1@example.com', + password: 'customerpw', + active: true, + roles: [test_role_2, test_role_3], + updated_by_id: 1, + created_by_id: 1, + ) + } + assert(user1.role_ids.include?(test_role_1.id)) + assert_not(user1.role_ids.include?(test_role_2.id)) + assert_not(user1.role_ids.include?(test_role_3.id)) + assert(user1.role_ids.include?(test_role_4.id)) + + end + + test 'permission default' do + admin_count = User.of_role('Admin').count + admin = User.create_or_update( + login: 'admin-role1@example.com', + firstname: 'Role', + lastname: 'Admin1', + email: 'admin-role1@example.com', + password: 'adminpw', + active: true, + roles: Role.where(name: %w(Admin Agent)), + updated_by_id: 1, + created_by_id: 1, + ) + agent_count = User.of_role('Agent').count + agent = User.create_or_update( + login: 'agent-role1@example.com', + firstname: 'Role', + lastname: 'Agent1', + email: 'agent-role1@example.com', + password: 'agentpw', + active: true, + roles: Role.where(name: 'Agent'), + updated_by_id: 1, + created_by_id: 1, + ) + customer_count = User.of_role('Customer').count + customer = User.create_or_update( + login: 'customer-role1@example.com', + firstname: 'Role', + lastname: 'Customer1', + email: 'customer-role1@example.com', + password: 'customerpw', + active: true, + roles: Role.where(name: 'Customer'), + updated_by_id: 1, + created_by_id: 1, + ) + users = User.with_permissions('not_existing') + assert(users.empty?) + + users = User.with_permissions('admin') + assert_equal(admin_count + 1, users.count) + assert_equal(admin.login, users.last.login) + + users = User.with_permissions('admin.session') + assert_equal(admin_count + 1, users.count) + assert_equal(admin.login, users.last.login) + + users = User.with_permissions(['admin.session', 'not_existing']) + assert_equal(admin_count + 1, users.count) + assert_equal(admin.login, users.last.login) + + users = User.with_permissions('ticket.agent') + assert_equal(agent_count + 1, users.count) + assert_equal(agent.login, users.last.login) + users = User.with_permissions(['ticket.agent', 'not_existing']) + assert_equal(agent_count + 1, users.count) + assert_equal(agent.login, users.last.login) + + users = User.with_permissions('ticket.customer') + assert_equal(customer_count + 1, users.count) + assert_equal(customer.login, users.last.login) + users = User.with_permissions(['ticket.customer', 'not_existing']) + assert_equal(customer_count + 1, users.count) + assert_equal(customer.login, users.last.login) + + end + end