vjt-zendesk 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +127 -0
- data/Rakefile +48 -0
- data/lib/zendesk.rb +72 -0
- data/lib/zendesk/controller.rb +53 -0
- data/lib/zendesk/helpers.rb +32 -0
- data/lib/zendesk/railtie.rb +20 -0
- data/lib/zendesk/routing.rb +24 -0
- data/lib/zendesk/version.rb +3 -0
- metadata +88 -0
data/README.md
ADDED
@@ -0,0 +1,127 @@
|
|
1
|
+
Zendesk on Rails - Dropbox and Remote Authentication
|
2
|
+
====================================================
|
3
|
+
|
4
|
+
Purpose
|
5
|
+
-------
|
6
|
+
|
7
|
+
The plugin implements the HTML generation code for the
|
8
|
+
[Zendesk dropbox](http://www.zendesk.com/blog/instant-support-access-with-drop-box)
|
9
|
+
and the necessary controller and routing code to implement
|
10
|
+
[Zendesk's remote authentication](http://www.zendesk.com/api/remote-authentication)
|
11
|
+
|
12
|
+
|
13
|
+
Installation
|
14
|
+
------------
|
15
|
+
|
16
|
+
In Gemfile
|
17
|
+
|
18
|
+
gem 'vjt-zendesk', :require => 'zendesk'
|
19
|
+
|
20
|
+
Configuration
|
21
|
+
-------------
|
22
|
+
|
23
|
+
In your `config/routes.rb`:
|
24
|
+
|
25
|
+
zendesk :on => '/support', :controller => 'root'
|
26
|
+
|
27
|
+
The `/support` path will then respond to the methods that generate the query
|
28
|
+
string parameters required for Remote Authentication, while the `/support/exit`
|
29
|
+
path will simply set a notice in the flash and redirect the user to the app
|
30
|
+
`root_url`. You can override this behaviour by implementing a `zendesk_logout`
|
31
|
+
method in the controller.
|
32
|
+
|
33
|
+
Finally, in your config/application.rb:
|
34
|
+
|
35
|
+
config.zendesk = {
|
36
|
+
:token => 'Your Zendesk token',
|
37
|
+
:hostname => 'example.zendesk.com',
|
38
|
+
:login => proc { [current_user.name, current_user.email] },
|
39
|
+
:login_url => :login_url,
|
40
|
+
:dropbox => {
|
41
|
+
:title => 'Dropbox title',
|
42
|
+
:email => proc { current_user.email rescue nil }
|
43
|
+
}
|
44
|
+
}
|
45
|
+
|
46
|
+
The required options are:
|
47
|
+
|
48
|
+
* `:token` -- your zendesk [shared secret](http://www.zendesk.com/api/remote-authentication)
|
49
|
+
* `:hostname` -- your zendesk account host name
|
50
|
+
* `:login` -- a `Proc` object evaluated in the controller instance context,
|
51
|
+
that must return an `Array` whose first element is the current user name and the second its email.
|
52
|
+
This `Proc` is evaluated iff the `logged_in?` instance method of your controller returns true.
|
53
|
+
* `:login_url` -- The name of the named route helper that generates the full URL of your login page.
|
54
|
+
We use `:ssl_login_url` thanks to our [SSL Helper](http://github.com/vjt/ssl_helper) plugin.
|
55
|
+
|
56
|
+
The `:dropbox` option is for the [Zendesk dropbox](http://www.zendesk.com/blog/instant-support-access-with-drop-box)
|
57
|
+
configuration, it should be an hash with symbolized keys and it is converted to
|
58
|
+
`JSON` and bound to the `zendesk_params` Javascript variable.
|
59
|
+
|
60
|
+
To facilitate the Dropbox usage, the `:email` option can be a `Proc` object that
|
61
|
+
is then evaluated in the controller instance context and should return the current
|
62
|
+
user e-mail or nil if the user is not logged in. If the `:email` option is unset
|
63
|
+
no e-mail appears precompiled in the Dropbox for, or you could even set a static
|
64
|
+
email for every feedback request (dunno why should you do that, though :-).
|
65
|
+
|
66
|
+
|
67
|
+
Usage
|
68
|
+
-----
|
69
|
+
|
70
|
+
To embed the Dropbox tags, use the `zendesk_dropbox_tags` helper
|
71
|
+
in your layout:
|
72
|
+
|
73
|
+
<%= zendesk_dropbox_tags %>
|
74
|
+
|
75
|
+
To display a link that displays the dropbox when clicked use the
|
76
|
+
`zendesk_dropbox_link_to` helper in your views:
|
77
|
+
|
78
|
+
<%= zendesk_dropbox_link_to 'Send feedback' %>
|
79
|
+
|
80
|
+
To display a link that starts the Remote Authentication process
|
81
|
+
use the `zendesk_link_to` helper in your views:
|
82
|
+
|
83
|
+
<%= zendesk_link_to 'Support' %>
|
84
|
+
|
85
|
+
The second parameter of said helper is passed to Rails' `link_to`
|
86
|
+
one to customize the link tag attributes.
|
87
|
+
|
88
|
+
|
89
|
+
Caching
|
90
|
+
-------
|
91
|
+
|
92
|
+
If you implement asset minifization and concatenation, you'll surely
|
93
|
+
want to reduce HTTP requests to external services. While it's not the
|
94
|
+
best practice in the world to cache said services assets, to speed up
|
95
|
+
your application you may be forced to do it.
|
96
|
+
|
97
|
+
[Panmind](http://panmind.com), where this project originated, is doing
|
98
|
+
this, both to reduce the number of HTTP requests and because the lag with
|
99
|
+
`assets0.zendesk.com` from Europe is quite high.
|
100
|
+
|
101
|
+
To make a long story short, if you're including the Zendesk assets in
|
102
|
+
your minified blobs, you can use just the `zendesk_dropbox_config` view
|
103
|
+
helper to generate the dropbox configuration, placing it before the
|
104
|
+
inclusion of your JS blobs: this way the `zenbox_params` variable will
|
105
|
+
be already defined when the JS is evaluated.
|
106
|
+
|
107
|
+
|
108
|
+
Compatibility
|
109
|
+
-------------
|
110
|
+
|
111
|
+
Tested with Rails 3.0.x running under Ruby 1.9.2.
|
112
|
+
|
113
|
+
|
114
|
+
TODO
|
115
|
+
----
|
116
|
+
|
117
|
+
* Your login action must implement a `redirect_to params[:return_to] || some_other_url`
|
118
|
+
or redirects to Zendesk won't work: remove relying on this assumption. Cleanly.
|
119
|
+
* Clean up configuration by requiring less variables: *convention over configuration*!
|
120
|
+
* Configuration of the `logged_in?` method name
|
121
|
+
* Allow options passing to the `zendesk_dropbox_link_to` helper
|
122
|
+
* Code documentation
|
123
|
+
* Tests (yuck!)
|
124
|
+
|
125
|
+
Please fork the project and send us a pull request if you check off any of these items
|
126
|
+
from the to-do list, or for any other improvement. Thanks! :-)
|
127
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/rdoctask'
|
3
|
+
|
4
|
+
require 'lib/zendesk/version'
|
5
|
+
|
6
|
+
begin
|
7
|
+
require 'jeweler'
|
8
|
+
Jeweler::Tasks.new do |gemspec|
|
9
|
+
gemspec.name = 'vjt-zendesk'
|
10
|
+
|
11
|
+
gemspec.summary = 'Zendesk on Rails - Dropbox and Remote Authentication'
|
12
|
+
gemspec.description = 'The plugin implements the HTML generation code for the ' \
|
13
|
+
'Zendesk dropbox and the necessary controller and routing ' \
|
14
|
+
'code to implement remote authentication'
|
15
|
+
|
16
|
+
gemspec.authors = ['Marcello Barnaba']
|
17
|
+
gemspec.email = 'vjt@openssl.it'
|
18
|
+
gemspec.homepage = 'http://github.com/vjt/zendesk'
|
19
|
+
|
20
|
+
gemspec.files = %w( README.md Rakefile rails/init.rb ) + Dir['lib/**/*']
|
21
|
+
gemspec.extra_rdoc_files = %w( README.md )
|
22
|
+
gemspec.has_rdoc = true
|
23
|
+
|
24
|
+
gemspec.version = Zendesk::Version
|
25
|
+
gemspec.date = '2010-11-23'
|
26
|
+
|
27
|
+
gemspec.require_path = 'lib'
|
28
|
+
|
29
|
+
gemspec.add_dependency('rails', '~> 3.0')
|
30
|
+
end
|
31
|
+
rescue LoadError
|
32
|
+
puts 'Jeweler not available. Install it with: gem install jeweler'
|
33
|
+
end
|
34
|
+
|
35
|
+
desc 'Generate the rdoc'
|
36
|
+
Rake::RDocTask.new do |rdoc|
|
37
|
+
rdoc.rdoc_files.add %w( README.md lib/**/*.rb )
|
38
|
+
|
39
|
+
rdoc.main = 'README.md'
|
40
|
+
rdoc.title = 'Zendesk on Rails - Dropbox and Remote Authentication'
|
41
|
+
end
|
42
|
+
|
43
|
+
desc 'Will someone help write tests?'
|
44
|
+
task :default do
|
45
|
+
puts
|
46
|
+
puts 'Can you help in writing tests? Please do :-)'
|
47
|
+
puts
|
48
|
+
end
|
data/lib/zendesk.rb
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'zendesk/controller'
|
2
|
+
require 'zendesk/helpers'
|
3
|
+
require 'zendesk/routing'
|
4
|
+
require 'zendesk/version'
|
5
|
+
require 'zendesk/railtie'
|
6
|
+
|
7
|
+
# Zendesk remote authentication helper for Rails. Implements JS generation,
|
8
|
+
# controller actions and route helpers. Have a look at the code, because it
|
9
|
+
# is more explanatory than a thousand words :-)
|
10
|
+
#
|
11
|
+
# Kudos to the Zendesk staff for such a simple and effective interface.
|
12
|
+
#
|
13
|
+
# (C) 2010 Panmind, Released under the terms of the Ruby License.
|
14
|
+
# (C) 2011 vjt@openssl.it
|
15
|
+
#
|
16
|
+
# - vjt Wed May 18 23:01:09 CEST 2011
|
17
|
+
#
|
18
|
+
module Zendesk
|
19
|
+
class ConfigurationError < StandardError; end
|
20
|
+
|
21
|
+
class << self
|
22
|
+
attr_reader :token, :hostname
|
23
|
+
|
24
|
+
def auth_url; @auth_url ||= "http://#{hostname}/access/remote/".freeze end
|
25
|
+
def return_url; @return_url ||= "http://#{hostname}/login".freeze end
|
26
|
+
def support_url; @support_url ||= "http://#{hostname}/home".freeze end
|
27
|
+
|
28
|
+
# TODO these should become attr_readers and we set @variables directly
|
29
|
+
attr_accessor :dropbox, :login, :login_url, :js_asset_path, :js_asset_name, :css_asset_path, :css_asset_name
|
30
|
+
|
31
|
+
def check_configuration!
|
32
|
+
options = Rails.application.config.zendesk rescue nil
|
33
|
+
|
34
|
+
bail "Zendesk configuration missing: please define config.zendesk" unless options.present?
|
35
|
+
|
36
|
+
self.token, self.hostname, self.login, self.login_url =
|
37
|
+
options.values_at(:token, :hostname, :login, :login_url)
|
38
|
+
|
39
|
+
bail "API token is missing" unless self.token.present?
|
40
|
+
bail "Support hostname is missing" unless self.hostname.present?
|
41
|
+
bail "Login proc is missing" unless self.login.present?
|
42
|
+
bail "Login URL named route is missing" unless self.login_url.present?
|
43
|
+
|
44
|
+
# Dropbox specific customizations, defaults in place
|
45
|
+
self.dropbox = (options[:dropbox] || {}).reverse_merge(
|
46
|
+
:dropboxID => 'feedback',
|
47
|
+
:url => Zendesk.hostname
|
48
|
+
).freeze
|
49
|
+
|
50
|
+
# Path and name for css and asset required for zenbox 2.0
|
51
|
+
self.js_asset_path = options[:js_asset_path] || '//assets0.zendesk.com/external/zenbox'
|
52
|
+
self.js_asset_name = options[:js_asset_name] || 'zenbox-2.0'
|
53
|
+
self.css_asset_path = options[:css_asset_path] || '//assets0.zendesk.com/external/zenbox'
|
54
|
+
self.css_asset_name = options[:css_asset_name] || 'zenbox-2.0'
|
55
|
+
end
|
56
|
+
|
57
|
+
def enabled?
|
58
|
+
# FIXME we should not disable this code in the
|
59
|
+
# test environment, rather test it appropriately
|
60
|
+
Rails.env.production? || Rails.env.development?
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
def token=(token); @token = token.freeze rescue nil end
|
65
|
+
def hostname=(hostname); @hostname = hostname.freeze end
|
66
|
+
|
67
|
+
def bail(message)
|
68
|
+
raise ConfigurationError, message
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'digest/md5'
|
2
|
+
|
3
|
+
module Zendesk
|
4
|
+
|
5
|
+
module Controller
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
included do
|
9
|
+
before_filter :zendesk_handle_guests, :only => :zendesk_login
|
10
|
+
end
|
11
|
+
|
12
|
+
def zendesk_login
|
13
|
+
name, email = instance_exec(&Zendesk.login)
|
14
|
+
|
15
|
+
now = params[:timestamp] || Time.now.to_i.to_s
|
16
|
+
hash = Digest::MD5.hexdigest(name + email + Zendesk.token + now)
|
17
|
+
back = params[:return_to] || Zendesk.return_url
|
18
|
+
|
19
|
+
auth_params = [
|
20
|
+
'?name=' + CGI.escape(name),
|
21
|
+
'&email=' + CGI.escape(email),
|
22
|
+
'×tamp=' + now,
|
23
|
+
'&hash=' + hash,
|
24
|
+
'&return_to=' + back
|
25
|
+
].join
|
26
|
+
|
27
|
+
redirect_to(Zendesk.auth_url + auth_params)
|
28
|
+
end
|
29
|
+
|
30
|
+
def zendesk_logout
|
31
|
+
flash[:notice] = "Thanks for visiting our support forum."
|
32
|
+
redirect_to root_url
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
def zendesk_handle_guests
|
37
|
+
return if logged_in? rescue false # TODO add another option
|
38
|
+
|
39
|
+
if params[:timestamp] && params[:return_to]
|
40
|
+
# User clicked on Zendesk "login", thus redirect to our
|
41
|
+
# login page, that'll redirect him/her back to Zendesk.
|
42
|
+
#
|
43
|
+
redirect_to send(Zendesk.login_url, :return_to => support_url)
|
44
|
+
else
|
45
|
+
# User clicked on our "support" link, and maybe doesn't
|
46
|
+
# have an account yet: redirect him/her to the support.
|
47
|
+
#
|
48
|
+
redirect_to Zendesk.support_url
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Zendesk
|
2
|
+
|
3
|
+
module Helpers
|
4
|
+
def zendesk_dropbox_config
|
5
|
+
config = Zendesk.dropbox
|
6
|
+
|
7
|
+
[:requester_email, :requester_name].each do |key|
|
8
|
+
config = config.merge(key => instance_exec(&config[key])) if config[key].kind_of?(Proc)
|
9
|
+
end
|
10
|
+
|
11
|
+
javascript_tag("var zenbox_params = #{config.to_json};").html_safe
|
12
|
+
end
|
13
|
+
|
14
|
+
def zendesk_dropbox_tags
|
15
|
+
return unless Zendesk.enabled?
|
16
|
+
|
17
|
+
%(#{zendesk_dropbox_config}
|
18
|
+
<style type='text/css' media='screen,projection'>@import url('#{Zendesk.css_asset_path}/#{Zendesk.css_asset_name}.css');</style>
|
19
|
+
<script type='text/javascript' src='#{Zendesk.js_asset_path}/#{Zendesk.js_asset_name}.js'></script>).html_safe
|
20
|
+
end
|
21
|
+
|
22
|
+
def zendesk_link_to(text, options = {})
|
23
|
+
return unless Zendesk.enabled?
|
24
|
+
link_to text, support_path, options
|
25
|
+
end
|
26
|
+
|
27
|
+
def zendesk_dropbox_link_to(text)
|
28
|
+
link_to text, '#', :onclick => 'Zenbox.render (); return false'
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'zendesk'
|
2
|
+
|
3
|
+
module Zendesk
|
4
|
+
|
5
|
+
class Railtie < Rails::Railtie
|
6
|
+
initializer 'zendesk.insert_into_action_view' do
|
7
|
+
ActiveSupport.on_load :action_view do
|
8
|
+
ActionView::Base.instance_eval { include Zendesk::Helpers }
|
9
|
+
ActionDispatch::Routing::Mapper.instance_eval { include Zendesk::Routing }
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
initializer 'zendesk.check_configuration' do
|
14
|
+
ActiveSupport.on_load :after_initialize do
|
15
|
+
Zendesk.check_configuration!
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Zendesk
|
2
|
+
|
3
|
+
module Routing
|
4
|
+
def zendesk(options = {})
|
5
|
+
return unless Zendesk.enabled?
|
6
|
+
|
7
|
+
base = options[:on] || '/zendesk'
|
8
|
+
ctrl = options[:controller]
|
9
|
+
|
10
|
+
unless ctrl.present?
|
11
|
+
raise ConfigurationError, "Missing :controller option"
|
12
|
+
end
|
13
|
+
|
14
|
+
scope base.to_s, :controller => ctrl do
|
15
|
+
get '/', :action => :zendesk_login, :as => base.to_sym
|
16
|
+
get '/exit', :action => :zendesk_logout, :as => nil
|
17
|
+
end
|
18
|
+
|
19
|
+
# Install the methods into the given controller
|
20
|
+
"#{ctrl.camelize}Controller".constantize.instance_eval { include Controller }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
metadata
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: vjt-zendesk
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 31
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 1
|
8
|
+
- 2
|
9
|
+
- 0
|
10
|
+
version: 1.2.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Marcello Barnaba
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-11-23 00:00:00 +01:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: rails
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 7
|
30
|
+
segments:
|
31
|
+
- 3
|
32
|
+
- 0
|
33
|
+
version: "3.0"
|
34
|
+
type: :runtime
|
35
|
+
version_requirements: *id001
|
36
|
+
description: The plugin implements the HTML generation code for the Zendesk dropbox and the necessary controller and routing code to implement remote authentication
|
37
|
+
email: vjt@openssl.it
|
38
|
+
executables: []
|
39
|
+
|
40
|
+
extensions: []
|
41
|
+
|
42
|
+
extra_rdoc_files:
|
43
|
+
- README.md
|
44
|
+
files:
|
45
|
+
- README.md
|
46
|
+
- Rakefile
|
47
|
+
- lib/zendesk.rb
|
48
|
+
- lib/zendesk/controller.rb
|
49
|
+
- lib/zendesk/helpers.rb
|
50
|
+
- lib/zendesk/railtie.rb
|
51
|
+
- lib/zendesk/routing.rb
|
52
|
+
- lib/zendesk/version.rb
|
53
|
+
has_rdoc: true
|
54
|
+
homepage: http://github.com/vjt/zendesk
|
55
|
+
licenses: []
|
56
|
+
|
57
|
+
post_install_message:
|
58
|
+
rdoc_options: []
|
59
|
+
|
60
|
+
require_paths:
|
61
|
+
- lib
|
62
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
63
|
+
none: false
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
hash: 3
|
68
|
+
segments:
|
69
|
+
- 0
|
70
|
+
version: "0"
|
71
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ">="
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
hash: 3
|
77
|
+
segments:
|
78
|
+
- 0
|
79
|
+
version: "0"
|
80
|
+
requirements: []
|
81
|
+
|
82
|
+
rubyforge_project:
|
83
|
+
rubygems_version: 1.4.1
|
84
|
+
signing_key:
|
85
|
+
specification_version: 3
|
86
|
+
summary: Zendesk on Rails - Dropbox and Remote Authentication
|
87
|
+
test_files: []
|
88
|
+
|