danski-ooh-auth 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. data/LICENSE +20 -0
  2. data/Rakefile +58 -0
  3. data/app/controllers/application.rb +16 -0
  4. data/app/controllers/authenticating_clients.rb +60 -0
  5. data/app/controllers/tokens.rb +94 -0
  6. data/app/helpers/application_helper.rb +64 -0
  7. data/app/helpers/authenticating_clients_helper.rb +5 -0
  8. data/app/helpers/authentications_helper.rb +5 -0
  9. data/app/models/authenticating_client.rb +12 -0
  10. data/app/models/authenticating_client/dm_authenticating_client.rb +71 -0
  11. data/app/models/token.rb +12 -0
  12. data/app/models/token/dm_token.rb +150 -0
  13. data/app/views/authenticating_clients/_help.html.erb +1 -0
  14. data/app/views/authenticating_clients/edit.html.erb +27 -0
  15. data/app/views/authenticating_clients/index.html.erb +24 -0
  16. data/app/views/authenticating_clients/new.html.erb +47 -0
  17. data/app/views/authenticating_clients/show.html.erb +40 -0
  18. data/app/views/layout/ooh_auth.html.erb +23 -0
  19. data/app/views/tokens/create.html.erb +34 -0
  20. data/app/views/tokens/edit.html.erb +4 -0
  21. data/app/views/tokens/new.html.erb +52 -0
  22. data/app/views/tokens/show.html.erb +1 -0
  23. data/lib/ooh-auth.rb +103 -0
  24. data/lib/ooh-auth/authentication_mixin.rb +13 -0
  25. data/lib/ooh-auth/controller_mixin.rb +38 -0
  26. data/lib/ooh-auth/key_generators.rb +57 -0
  27. data/lib/ooh-auth/merbtasks.rb +103 -0
  28. data/lib/ooh-auth/request_verification_mixin.rb +160 -0
  29. data/lib/ooh-auth/slicetasks.rb +18 -0
  30. data/lib/ooh-auth/spectasks.rb +65 -0
  31. data/lib/ooh-auth/strategies/oauth.rb +16 -0
  32. data/public/javascripts/master.js +0 -0
  33. data/public/stylesheets/master.css +2 -0
  34. data/readme.markdown +43 -0
  35. data/spec/controllers/application_spec.rb +35 -0
  36. data/spec/controllers/authenticating_clients_spec.rb +119 -0
  37. data/spec/controllers/tokens_spec.rb +173 -0
  38. data/spec/merb-auth-slice-fullfat_spec.rb +41 -0
  39. data/spec/models/authenticating_client_spec.rb +44 -0
  40. data/spec/models/oauth_strategy_spec.rb +48 -0
  41. data/spec/models/request_verification_mixin_spec.rb +121 -0
  42. data/spec/models/token_spec.rb +139 -0
  43. data/spec/spec_fixtures.rb +19 -0
  44. data/spec/spec_helper.rb +107 -0
  45. data/stubs/app/controllers/application.rb +2 -0
  46. data/stubs/app/controllers/main.rb +2 -0
  47. metadata +133 -0
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008 Dan Glegg
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,58 @@
1
+ require 'rubygems'
2
+ require 'rake/gempackagetask'
3
+
4
+ require 'merb-core'
5
+ require 'merb-core/tasks/merb'
6
+
7
+ require 'spec/rake/spectask'
8
+ require 'merb-core/test/tasks/spectasks'
9
+ require 'merb_datamapper/merbtasks'
10
+
11
+ desc 'Default: run spec examples'
12
+ task :default => 'spec'
13
+
14
+
15
+ GEM_NAME = "ooh-auth"
16
+ AUTHOR = "Dan Glegg"
17
+ EMAIL = "dan@angryamoeba.co.uk"
18
+ HOMEPAGE = "http://github.com/danski/ooh-auth"
19
+ SUMMARY = "Merb Slice that provides RESTful authentication functionality for your application."
20
+ GEM_VERSION = "0.1.2"
21
+
22
+ spec = Gem::Specification.new do |s|
23
+ s.rubyforge_project = 'merb'
24
+ s.name = GEM_NAME
25
+ s.version = GEM_VERSION
26
+ s.platform = Gem::Platform::RUBY
27
+ s.has_rdoc = true
28
+ s.extra_rdoc_files = ["README", "LICENSE", 'TODO']
29
+ s.summary = SUMMARY
30
+ s.description = s.summary
31
+ s.author = AUTHOR
32
+ s.email = EMAIL
33
+ s.homepage = HOMEPAGE
34
+ s.add_dependency('merb-slices', '>= 0.9.10')
35
+ s.require_path = 'lib'
36
+ s.files = %w(LICENSE README Rakefile TODO) + Dir.glob("{lib,spec,app,public,stubs}/**/*")
37
+ end
38
+
39
+ Rake::GemPackageTask.new(spec) do |pkg|
40
+ pkg.gem_spec = spec
41
+ end
42
+
43
+ desc "Install the gem"
44
+ task :install do
45
+ Merb::RakeHelper.install(GEM_NAME, :version => GEM_VERSION)
46
+ end
47
+
48
+ desc "Uninstall the gem"
49
+ task :uninstall do
50
+ Merb::RakeHelper.uninstall(GEM_NAME, :version => GEM_VERSION)
51
+ end
52
+
53
+ desc "Create a gemspec file"
54
+ task :gemspec do
55
+ File.open("#{GEM_NAME}.gemspec", "w") do |file|
56
+ file.puts spec.to_ruby
57
+ end
58
+ end
@@ -0,0 +1,16 @@
1
+ class OohAuth::Application < Merb::Controller
2
+
3
+ controller_for_slice
4
+
5
+ private
6
+ def user_class
7
+ Merb::Authentication.user_class
8
+ end
9
+
10
+ # Can be removed once http://merb.lighthouseapp.com/projects/7433/tickets/956-patch-add-message-support
11
+ # is merged.
12
+ def message=(arg)
13
+ @_message = arg
14
+ end
15
+
16
+ end
@@ -0,0 +1,60 @@
1
+ class OohAuth::AuthenticatingClients < OohAuth::Application
2
+
3
+ before :ensure_authenticated, :exclude=>[:index]
4
+ only_provides :html
5
+
6
+ def index
7
+ @authenticating_clients = OohAuth::AuthenticatingClient.find_for_user(session.user)
8
+ render :index
9
+ end
10
+
11
+ def show(id)
12
+ @authenticating_client = OohAuth::AuthenticatingClient.get(id)
13
+ raise NotFound unless @authenticating_client and @authenticating_client.editable_by?(session.user)
14
+ display @authenticating_client, :show
15
+ end
16
+
17
+ def new
18
+ @authenticating_client = OohAuth::AuthenticatingClient.new
19
+ display @authenticating_client
20
+ end
21
+
22
+ def create(authenticating_client)
23
+ @authenticating_client = OohAuth::AuthenticatingClient.new_for_user(session.user, authenticating_client)
24
+ if @authenticating_client.save
25
+ headers['Location'] = slice_url(:authenticating_client, @authenticating_client)
26
+ render :show, :status=>201
27
+ else
28
+ message[:error] = "There were problems creating the Application."
29
+ render :new
30
+ end
31
+ end
32
+
33
+ def edit(id)
34
+ @authenticating_client = OohAuth::AuthenticatingClient.get(id)
35
+ raise NotFound unless @authenticating_client and @authenticating_client.editable_by?(session.user)
36
+ display @authenticating_client, :edit
37
+ end
38
+
39
+ def update(id, authenticating_client)
40
+ @authenticating_client = OohAuth::AuthenticatingClient.get(id)
41
+ raise NotFound unless @authenticating_client and @authenticating_client.editable_by?(session.user)
42
+ if @authenticating_client.update_attributes(authenticating_client)
43
+ message[:success] = "Application updated successfully!"
44
+ redirect slice_url(:authenticating_client, @authenticating_client)
45
+ else
46
+ display @authenticating_client, :edit
47
+ end
48
+ end
49
+
50
+ def destroy(id)
51
+ @authenticating_client = OohAuth::AuthenticatingClient.get(id)
52
+ raise NotFound unless @authenticating_client and @authenticating_client.editable_by?(session.user)
53
+ if @authenticating_client.destroy
54
+ redirect slice_url(:authenticating_clients)
55
+ else
56
+ raise InternalServerError
57
+ end
58
+ end
59
+
60
+ end # OohAuth::AuthenticatingClients
@@ -0,0 +1,94 @@
1
+ =begin
2
+ OohAuth::Tokens
3
+
4
+ This controller is intended to allow applications to authenticate on behalf of a user.
5
+ Applications follow a set process as shown in authenticating.markdown, in which a number of background
6
+ requests are made to the host application while the user is run through a short process in which they
7
+ specify which privileges to give to the authenticating client, and how long to give them for.
8
+
9
+ The Authentications controller provides a relatively opaque interface to
10
+ users and authenticating clients compared to other resource controllers. Most of the views provide only HTML
11
+ representations as they not only are intended for human interaction, but specifically require it.
12
+ =end
13
+
14
+ require 'net/http'
15
+
16
+ class OohAuth::Tokens < OohAuth::Application
17
+
18
+ # Define other formats
19
+ provides :js, :xml, :yaml
20
+
21
+ # The index and new actions require a signed request.
22
+ before :ensure_signed, :only=>[:index]
23
+ # All other actions require that the user be authenticated directly, rather than through the api.
24
+ before :forbid_authentication_with_oauth, :exclude=>[:index]
25
+
26
+ # Main action used for starting the authorisation process (desktop clients) and finishing it (web clients)
27
+ def index
28
+ raise NotAcceptable unless @authenticating_client = request.authenticating_client
29
+ if @token = request.authentication_token
30
+ # If client and request key, give the activated token if it was activated.
31
+ raise NotAcceptable unless @token.authenticating_client == @authenticating_client
32
+ else
33
+ # Generate a request key
34
+ @token = OohAuth::Token.create_request_key(@authenticating_client)
35
+ end
36
+ # # Okay, no error raised. Gogo render.
37
+ display @token, :show, :layout=>false
38
+ end
39
+
40
+ def new
41
+ only_provides :html
42
+ unless (@token = OohAuth::Token.first(:token_key=>request.token) and
43
+ @authenticating_client = @token.authenticating_client)
44
+ raise NotAcceptable
45
+ end
46
+ display @token, :new
47
+ end
48
+
49
+ # Activates an authentication receipt, converting it into a token the authenticating client can use in future requests.
50
+ def create(token)
51
+ only_provides :html
52
+ commit = (params[:commit]=="allow") # Did they click the allow or the deny button? ENQUIRING MINDS NEED TO KNOW!
53
+ raise NotFound unless @token = OohAuth::Token.get_token(request.token) # The oauth_token is now in the post body.
54
+ raise NotFound unless @authenticating_client = @token.authenticating_client # Stop right there, criminal scum.
55
+
56
+ @activated = @token.activate!(session.user, token[:expires], token[:permissions]) if commit
57
+ redirect("#{request.callback}#{(request.callback["?"])? "&" : "?"}oauth_token=#{@token.token_key}") if commit and request.callback # the callback is in the post body
58
+ display @token, :create
59
+ end
60
+
61
+ #def show(id)
62
+ # @token = ::Authentication.get(id)
63
+ # raise NotFound unless @token
64
+ # display @token
65
+ #end
66
+ #
67
+ #def edit(id)
68
+ # only_provides :html
69
+ # @token = OohAuth::Token.get(id)
70
+ # raise NotFound unless @token
71
+ # display @token
72
+ #end
73
+ #
74
+ #def update(id, token)
75
+ # @token = OohAuth::Token.get(id)
76
+ # raise NotFound unless @token
77
+ # if @token.update_attributes(authentication)
78
+ # redirect slice_url(:tokens, @token)
79
+ # else
80
+ # display @token, :edit
81
+ # end
82
+ #end
83
+ #
84
+ #def destroy(id)
85
+ # @token = OohAuth::Token.get(id)
86
+ # raise NotFound unless @token
87
+ # if @token.destroy
88
+ # redirect slice_url(:tokens)
89
+ # else
90
+ # raise InternalServerError
91
+ # end
92
+ #end
93
+
94
+ end # OohAuth::Tokens
@@ -0,0 +1,64 @@
1
+ module Merb
2
+ module OohAuth
3
+ module ApplicationHelper
4
+
5
+ # @param *segments<Array[#to_s]> Path segments to append.
6
+ #
7
+ # @return <String>
8
+ # A path relative to the public directory, with added segments.
9
+ def image_path(*segments)
10
+ public_path_for(:image, *segments)
11
+ end
12
+
13
+ # @param *segments<Array[#to_s]> Path segments to append.
14
+ #
15
+ # @return <String>
16
+ # A path relative to the public directory, with added segments.
17
+ def javascript_path(*segments)
18
+ public_path_for(:javascript, *segments)
19
+ end
20
+
21
+ # @param *segments<Array[#to_s]> Path segments to append.
22
+ #
23
+ # @return <String>
24
+ # A path relative to the public directory, with added segments.
25
+ def stylesheet_path(*segments)
26
+ public_path_for(:stylesheet, *segments)
27
+ end
28
+
29
+ # Construct a path relative to the public directory
30
+ #
31
+ # @param <Symbol> The type of component.
32
+ # @param *segments<Array[#to_s]> Path segments to append.
33
+ #
34
+ # @return <String>
35
+ # A path relative to the public directory, with added segments.
36
+ def public_path_for(type, *segments)
37
+ ::OohAuth.public_path_for(type, *segments)
38
+ end
39
+
40
+ # Construct an app-level path.
41
+ #
42
+ # @param <Symbol> The type of component.
43
+ # @param *segments<Array[#to_s]> Path segments to append.
44
+ #
45
+ # @return <String>
46
+ # A path within the host application, with added segments.
47
+ def app_path_for(type, *segments)
48
+ ::OohAuth.app_path_for(type, *segments)
49
+ end
50
+
51
+ # Construct a slice-level path.
52
+ #
53
+ # @param <Symbol> The type of component.
54
+ # @param *segments<Array[#to_s]> Path segments to append.
55
+ #
56
+ # @return <String>
57
+ # A path within the slice source (Gem), with added segments.
58
+ def slice_path_for(type, *segments)
59
+ ::OohAuth.slice_path_for(type, *segments)
60
+ end
61
+
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,5 @@
1
+ module Merb
2
+ module AuthenticatingClientsHelper
3
+
4
+ end
5
+ end # Merb
@@ -0,0 +1,5 @@
1
+ module Merb
2
+ module AuthenticationsHelper
3
+
4
+ end
5
+ end # Merb
@@ -0,0 +1,12 @@
1
+ path = File.expand_path(File.dirname(__FILE__)) / "authenticating_client"
2
+ if defined?(DataMapper)
3
+ require path / "dm_authenticating_client"
4
+ #elsif defined?(ActiveRecord)
5
+ # require path / "ar_password_reset"
6
+ #elsif defined?(Sequel)
7
+ # require path / "sq_password_reset"
8
+ #elsif defined?(RelaxDB)
9
+ # require path / "relaxdb_password_reset"
10
+ else
11
+ raise RuntimeError, "Datamapper is a dependency of the slice at this time."
12
+ end
@@ -0,0 +1,71 @@
1
+ =begin
2
+ OohAuth::AuthenticatingClient
3
+ ========================================================================================
4
+ An authenticating client is an external application which wants to use your application's public API while authenticated as one of your users.
5
+ =end
6
+
7
+ class OohAuth::AuthenticatingClient
8
+ include DataMapper::Resource
9
+
10
+ # Key it
11
+ property :id, Serial
12
+ # The registration will belong to a user, who will be able to edit the client properties.
13
+ property :user_id, Integer, :writer => :protected
14
+ # Timestamp it
15
+ property :created_at, DateTime
16
+
17
+ # Used by all type of authenticating apps
18
+ property :name, String # e.g. "Mobilator PRO"
19
+ property :web_url, URI # e.g. "http://mobilator.portionator.net"
20
+ property :api_key, String, :index=>true # the unique key for this application.
21
+ property :secret, String # the secret which will NEVER be transmitted during the authentication procedure. Used only to sign requests.
22
+ property :kind, String # e.g "desktop", "web", "mobile"
23
+
24
+ validates_present :name, :web_url, :api_key, :secret, :kind
25
+ validates_is_unique :name
26
+ validates_is_unique :api_key
27
+ validates_with_method :kind, :valid_kind?
28
+
29
+ before :valid?, :generate_keys_if_not_present
30
+
31
+ def self.new_for_user(user, attrs)
32
+ o = new(attrs)
33
+ o.user = user
34
+ return o
35
+ end
36
+
37
+ def self.find_for_user(user)
38
+ return [] unless user
39
+ return all(:user_id=>user.id)
40
+ end
41
+
42
+ def is_webapp?
43
+ self.kind == "web"
44
+ end
45
+
46
+ def generate_keys_if_not_present
47
+ api_key_length = 15
48
+ while self.api_key.blank? or self.class.first(:id.not=>id, :api_key=>self.api_key) do
49
+ self.api_key = OohAuth::KeyGenerators::Alphanum.gen(api_key_length)
50
+ api_key_length += 1
51
+ end
52
+ self.secret = OohAuth::KeyGenerators::Alphanum.gen(40) if secret.blank?
53
+ end
54
+
55
+ def valid_kind?
56
+ if OohAuth[:client_kinds].include?(self.kind)
57
+ return true
58
+ else
59
+ return false, "illegal kind"
60
+ end
61
+ end
62
+
63
+ def user=(user)
64
+ self.user_id = user.id
65
+ end
66
+
67
+ def editable_by?(user)
68
+ user.id == self.user_id
69
+ end
70
+
71
+ end # OohAuth::AuthenticatingClient
@@ -0,0 +1,12 @@
1
+ path = File.expand_path(File.dirname(__FILE__)) / "token"
2
+ if defined?(DataMapper)
3
+ require path / "dm_token"
4
+ #elsif defined?(ActiveRecord)
5
+ # require path / "ar_password_reset"
6
+ #elsif defined?(Sequel)
7
+ # require path / "sq_password_reset"
8
+ #elsif defined?(RelaxDB)
9
+ # require path / "relaxdb_password_reset"
10
+ else
11
+ raise RuntimeError, "Datamapper is a dependency of the slice at this time."
12
+ end
@@ -0,0 +1,150 @@
1
+ =begin
2
+ Token model
3
+
4
+ A token is a stored authorisation allowing an authenticating client to:
5
+
6
+ 1. Get a *request key*. This is done by creating an unactivated token belonging to the authenticating client which has a _request key_.
7
+ 2. *Request access*. This is done by directing the user to a URL unique to the given request key, presenting them with a form.
8
+ The user must be logged in through direct means in order to grant access.
9
+ 3. Getting an *access key* which is a property of the now-activated token.
10
+
11
+ =end
12
+
13
+ class OohAuth::Token
14
+ include DataMapper::Resource
15
+
16
+ property :id, Serial
17
+ property :user_id, Integer, :writer=>:protected
18
+ property :authenticating_client_id, Integer, :writer=>:protected
19
+
20
+ # Expiry date will always be respected. You cannot authenticate using an expired token, and nor can you
21
+ # convert an expired request key into an access key.
22
+ property :expires, DateTime
23
+ property :created_at, DateTime
24
+ property :permissions, String
25
+
26
+ property :token_key, String, :writer=>:private, :index=>true
27
+ property :activated, Boolean, :writer=>:private, :index=>true, :default=>false
28
+ property :secret, String, :writer=>:private
29
+
30
+ validates_is_unique :token_key
31
+ validates_present :secret
32
+ validates_present :authenticating_client
33
+ validates_with_method :permissions, :permissions_valid?
34
+
35
+ belongs_to :authenticating_client, :class_name=>"OohAuth::AuthenticatingClient", :child_key=>[:authenticating_client_id]
36
+ belongs_to :user, :class_name=>Merb::Authentication.user_class.to_s, :child_key=>[:user_id]
37
+
38
+ before :valid?, :create_token_key_if_not_present
39
+ before :valid?, :create_secret_if_not_present
40
+
41
+ # Authenticates a client on behalf of a user given the API parameters sent by the client
42
+ # in the given API request. Returns the user on successful authentication, or false in
43
+ # the event of a failure to authenticate. If the user was since deleted, NIL will be
44
+ # returned.
45
+ def self.authenticate!(consumer_key, access_key)
46
+ auth = first('authenticating_client.api_key'=>consumer_key, :token_key=>access_key, :activated=>true, :expires.gt=>DateTime.now)
47
+ return (auth)? auth.user : nil
48
+ end
49
+
50
+ # FIXME the relationship helper should be sorting this. Something to do with the variable class.
51
+ def user
52
+ Merb::Authentication.user_class.get(user_id)
53
+ end
54
+
55
+ # Tentatively create a request_key for a given client, not yet tied to a user.
56
+ def self.create_request_key(authenticating_client, expires=1.hour.since)
57
+ o = new(:authenticating_client=>authenticating_client, :expires=>expires)
58
+ o.save or raise RuntimeError, "OAuth request key failed to save with errors: #{o.errors.inspect}"
59
+ o
60
+ end
61
+
62
+ # Fetch a request_key given the request_key code
63
+ def self.get_request_key_for_client(client, request_key)
64
+ first :token_key=>request_key, :authenticating_client_id=>client.id, :expires.gt=>DateTime.now, :activated=>false
65
+ end
66
+
67
+ def self.get_token(token)
68
+ first :token_key=>token
69
+ end
70
+
71
+ # Make this Authentication object active by generating an access key against it.
72
+ # You may optionally specify a new expiry date/time for the access key.
73
+ def activate!(with_user, expire_on=nil, permissions=nil)
74
+ if authenticating_client and with_user
75
+ self.activated = true
76
+ self.expires = (expire_on || 1.year.since)
77
+ self.permissions = (permissions || OohAuth[:default_permissions])
78
+ self.user_id = with_user.id
79
+ generate_token_key!
80
+ return save
81
+ else
82
+ return false
83
+ end
84
+ end
85
+
86
+ # Checks to see if this Authentication is activated - if there is an access key defined, then
87
+ # true is returned.
88
+ #def activated?
89
+ # ac
90
+ #end
91
+
92
+ # Assigns a valid, unique request_key to the object if one is not already defined.
93
+ def create_token_key_if_not_present
94
+ generate_token_key! if token_key.blank?
95
+ end
96
+
97
+ def create_secret_if_not_present
98
+ self.secret ||= OohAuth::KeyGenerators::Alphanum.gen(30)
99
+ end
100
+
101
+ # Generates a valid, unique access_key which the client can use to authenticate with in future,
102
+ # and applies it to the object.
103
+ def generate_token_key!
104
+ while (token_key.blank? or self.class.first(:token_key=>token_key)) do
105
+ self.token_key = OohAuth::KeyGenerators::Alphanum.gen(30)
106
+ end
107
+ end
108
+
109
+ # Returns true if the given user is the owner of this object.
110
+ def editable_by_user?(user)
111
+ return user.id == user_id
112
+ end
113
+
114
+ # Returns the permissions for this particular token, or the :default_permissions if not set.
115
+ def permissions
116
+ attribute_get(:permissions) or OohAuth[:default_permissions]
117
+ end
118
+
119
+ # Returns true if the set permissions are a valid value according to the keys of the slice's :client_permission_levels hash.
120
+ def permissions_valid?
121
+ OohAuth[:client_permission_levels].keys.include?(permissions.to_sym)
122
+ end
123
+
124
+ # Transformation - returns a hash representing this object, ready to be converted to XML, JSON or YAML.
125
+ def to_hash
126
+ if activated?
127
+ {
128
+ :access_key=>{
129
+ :token=>token_key,
130
+ :secret=>secret,
131
+ :expires=>expires
132
+ }
133
+ }
134
+ else
135
+ {
136
+ :request_key=>{
137
+ :token=>token_key,
138
+ :secret=>secret,
139
+ :expires=>expires
140
+ }
141
+ }
142
+ end
143
+ end
144
+ # FIXME why is to_xml not available?
145
+ def to_xml; (activated?)? "<access-key><token>#{token_key}</token><secret>#{secret}</secret><expires>#{expires}</expires></access-key>" : "<request-key><token>#{token_key}</token><secret>#{secret}</secret><expires>#{expires}</expires></request-key>"; end
146
+ def to_json; to_hash.to_json; end
147
+ def to_yaml; to_hash.to_yaml; end
148
+
149
+
150
+ end