danski-ooh-auth 0.1.2

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.
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