authoritarian 0.1.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 +83 -0
- data/bin/authoritarian +273 -0
- data/lib/authoritarian.rb +16 -0
- data/lib/authoritarian/model.rb +9 -0
- data/lib/authoritarian/model/application.rb +16 -0
- data/lib/authoritarian/model/user.rb +12 -0
- data/lib/authoritarian/twitter.rb +103 -0
- data/lib/authoritarian/version.rb +3 -0
- metadata +218 -0
data/README.md
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
Authoritarian - Twitter OAuth Manager
|
2
|
+
=====================================
|
3
|
+
|
4
|
+
## DESCRIPTION
|
5
|
+
|
6
|
+
Authoritarian is a command line interface for managing Twitter authorizations to
|
7
|
+
your application. God forbid Twitter give us a simple way to manually add
|
8
|
+
test accounts to our application.
|
9
|
+
|
10
|
+
Authoritarian follows the rules of [Semantic Versioning](http://semver.org/).
|
11
|
+
|
12
|
+
|
13
|
+
## INSTALL
|
14
|
+
|
15
|
+
To install Authoritarian, simply install the gem:
|
16
|
+
|
17
|
+
$ [sudo] gem install authoritarian
|
18
|
+
|
19
|
+
|
20
|
+
## TWITTER
|
21
|
+
|
22
|
+
### APPLICATIONS
|
23
|
+
|
24
|
+
To authorize using Twitter's API, start by registering your application in
|
25
|
+
authoritarian:
|
26
|
+
|
27
|
+
$ authoritarian add application
|
28
|
+
Name: My Cool App
|
29
|
+
Consumer Key: HJvxyS06ykAA5AxYruY2p
|
30
|
+
Consumer Secret: 4wftaMYXpylkveupjQ4YDDZlarS35UJHR1ZHHSfjto
|
31
|
+
|
32
|
+
You can find your Consumer Key and Consumer Secret for your application by
|
33
|
+
going to the [Twitter Developer Applications](https://dev.twitter.com/apps) site
|
34
|
+
and clicking on the application you'd like to add. The key and secret are listed
|
35
|
+
under `OAuth 1.0a Settings`.
|
36
|
+
|
37
|
+
You can view your registered applications:
|
38
|
+
|
39
|
+
$ authoritarian show applications
|
40
|
+
$ authoritarian show applications --all
|
41
|
+
|
42
|
+
The `--all` option shows the consumer key and secret for each application.
|
43
|
+
|
44
|
+
Finally, you can remove your application by running:
|
45
|
+
|
46
|
+
$ authoritarian show applications
|
47
|
+
|
48
|
+
You'll be presented with prompts to select the application you wish to remove.
|
49
|
+
|
50
|
+
### USERS
|
51
|
+
|
52
|
+
Once you've registered a Twitter application with Authoritarian, you can
|
53
|
+
authorize individual Twitter users to your application from the command line.
|
54
|
+
|
55
|
+
To authorize a user, simply type:
|
56
|
+
|
57
|
+
$ authoritarian add user
|
58
|
+
|
59
|
+
And to show a list of all users, type:
|
60
|
+
|
61
|
+
$ authoritarian show users
|
62
|
+
$ authoritarian show users --all
|
63
|
+
|
64
|
+
The `--all` option will append the OAuth token and OAuth token secret for each
|
65
|
+
user registered to Authoritarian.
|
66
|
+
|
67
|
+
To remove a user from Authoritarian (but not deauthorize), type:
|
68
|
+
|
69
|
+
$ authoritarian remove user
|
70
|
+
|
71
|
+
|
72
|
+
## CONTRIBUTE
|
73
|
+
|
74
|
+
Contributions to Authoritarian are welcome! There is no mailing list currently
|
75
|
+
but you can add a feature you're interested in building to the GitHub Issues
|
76
|
+
page to discuss it.
|
77
|
+
|
78
|
+
If you do submit a pull request, please make sure you add test coverage and
|
79
|
+
send your request from a git topic branch.
|
80
|
+
|
81
|
+
You can find the repository here:
|
82
|
+
|
83
|
+
http://github.com/benbjohnson/authoritarian
|
data/bin/authoritarian
ADDED
@@ -0,0 +1,273 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
dir = File.join(File.dirname(File.expand_path(__FILE__)), '..', 'lib')
|
4
|
+
$:.unshift(dir)
|
5
|
+
|
6
|
+
require 'rubygems'
|
7
|
+
require 'authoritarian'
|
8
|
+
require 'commander/import'
|
9
|
+
require 'terminal-table/import'
|
10
|
+
|
11
|
+
program :name, 'Authoritarian'
|
12
|
+
program :version, Authoritarian::VERSION
|
13
|
+
program :description, 'An OAuth command line authorization tool.'
|
14
|
+
|
15
|
+
|
16
|
+
################################################################################
|
17
|
+
# Initialization
|
18
|
+
################################################################################
|
19
|
+
|
20
|
+
# Setup DataMapper
|
21
|
+
DataMapper.setup(:default, "sqlite://#{File.expand_path('~/authoritarian.db')}")
|
22
|
+
DataMapper.auto_upgrade!
|
23
|
+
|
24
|
+
# Catch CTRL-C and exit cleanly
|
25
|
+
trap("INT") do
|
26
|
+
puts
|
27
|
+
exit()
|
28
|
+
end
|
29
|
+
|
30
|
+
################################################################################
|
31
|
+
# Helper Methods
|
32
|
+
################################################################################
|
33
|
+
|
34
|
+
def ask_application(explicit=false, message='Please choose an application')
|
35
|
+
applications = Application.all
|
36
|
+
if applications.length == 0
|
37
|
+
puts "There are no applications. Please run 'authoritarian add application'."
|
38
|
+
exit()
|
39
|
+
elsif applications.length == 1 && !explicit
|
40
|
+
return applications[0].id
|
41
|
+
else
|
42
|
+
puts ""
|
43
|
+
puts "Applications"
|
44
|
+
applications.each_index do |index|
|
45
|
+
puts "#{index+1}. #{applications[index].name}"
|
46
|
+
end
|
47
|
+
index = ask("#{message} [1-#{applications.length}]: ", Integer) do
|
48
|
+
|q| q.in = 1..applications.length
|
49
|
+
end
|
50
|
+
puts ""
|
51
|
+
return applications[index-1].id
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def ask_user(application, explicit=false, message='Please choose a user')
|
56
|
+
users = application.users
|
57
|
+
if users.length == 0
|
58
|
+
puts "There are no users. Please run 'authoritarian add user'."
|
59
|
+
exit()
|
60
|
+
elsif users.length == 1 && !explicit
|
61
|
+
return users[0].id
|
62
|
+
else
|
63
|
+
puts "Users"
|
64
|
+
users.each_index do |index|
|
65
|
+
puts "#{index+1}. #{users[index].username}"
|
66
|
+
end
|
67
|
+
index = ask("#{message} [1-#{users.length}]: ", Integer) do
|
68
|
+
|q| q.in = 1..users.length
|
69
|
+
end
|
70
|
+
puts ""
|
71
|
+
return users[index-1].id
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
|
76
|
+
################################################################################
|
77
|
+
# Application Commands
|
78
|
+
################################################################################
|
79
|
+
|
80
|
+
# Add application
|
81
|
+
command :'add application' do |c|
|
82
|
+
c.syntax = 'authoritarian add application'
|
83
|
+
c.description = 'Adds an application to the database.'
|
84
|
+
c.when_called do|args, options|
|
85
|
+
application = Application.new(:type => 'twitter')
|
86
|
+
application.name = ask("Name: ")
|
87
|
+
application.consumer_key = ask("Consumer Key: ")
|
88
|
+
application.consumer_secret = ask("Consumer Secret: ")
|
89
|
+
application.save()
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# Remove Application
|
94
|
+
command :'remove application' do |c|
|
95
|
+
c.syntax = 'authoritarian remove application [options]'
|
96
|
+
c.description = 'Removes a registered application.'
|
97
|
+
c.option '--app-id ID', String, 'The identifier for the authorizing application.'
|
98
|
+
c.when_called do|args, options|
|
99
|
+
# Retrieve the application
|
100
|
+
options.app_id ||= ask_application(true, 'Please choose an application to delete')
|
101
|
+
application = Application.get(options.app_id)
|
102
|
+
raise "Cannot find application #{options.app_id}" if application.nil?
|
103
|
+
|
104
|
+
# Delete application
|
105
|
+
application.destroy
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
# Show applications
|
110
|
+
command :'show applications' do |c|
|
111
|
+
c.syntax = 'authoritarian show applications'
|
112
|
+
c.description = 'Displays all registered applications registered.'
|
113
|
+
c.option '--all', 'Shows all application data.'
|
114
|
+
c.when_called do|args, options|
|
115
|
+
applications = Application.all
|
116
|
+
|
117
|
+
if applications.length == 0
|
118
|
+
say "There are no registered applications."
|
119
|
+
else
|
120
|
+
application_table = table do |t|
|
121
|
+
t.headings = 'ID', 'Name'
|
122
|
+
|
123
|
+
# Optionally add consumer info
|
124
|
+
if options.all
|
125
|
+
t.headings << 'Consumer Key'
|
126
|
+
t.headings << 'Consumer Secret'
|
127
|
+
end
|
128
|
+
|
129
|
+
applications.each do |application|
|
130
|
+
row = [
|
131
|
+
application.id,
|
132
|
+
application.name[0..20],
|
133
|
+
]
|
134
|
+
|
135
|
+
# Optionally add consumer info
|
136
|
+
if options.all
|
137
|
+
row << application.consumer_key
|
138
|
+
row << application.consumer_secret
|
139
|
+
end
|
140
|
+
|
141
|
+
t << row
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
puts application_table
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
# Show application
|
151
|
+
command :'show application' do |c|
|
152
|
+
c.syntax = 'authoritarian show application [options]'
|
153
|
+
c.description = 'Displays details of a single application.'
|
154
|
+
c.option '--id NUM', String, 'The application identifier.'
|
155
|
+
c.when_called do|args, options|
|
156
|
+
id = options.id || ask("ID: ")
|
157
|
+
application = Application.get(id)
|
158
|
+
|
159
|
+
if application.nil?
|
160
|
+
say "The specified application does not exist."
|
161
|
+
else
|
162
|
+
puts "Name: #{application.name}"
|
163
|
+
puts "Consumer Key: #{application.consumer_key}"
|
164
|
+
puts "Consumer Secret: #{application.consumer_secret}"
|
165
|
+
puts ""
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
|
171
|
+
################################################################################
|
172
|
+
# User Commands
|
173
|
+
################################################################################
|
174
|
+
|
175
|
+
# Add User
|
176
|
+
command :'add user' do |c|
|
177
|
+
c.syntax = 'authoritarian authorize user [options]'
|
178
|
+
c.description = 'Authorizes a user to an application.'
|
179
|
+
c.option '--app-id ID', String, 'The identifier for the authorizing application.'
|
180
|
+
c.option '--username STRING', String, 'The username of the authorizing user.'
|
181
|
+
c.option '--password STRING', String, 'The password of the authorizing user.'
|
182
|
+
c.when_called do|args, options|
|
183
|
+
options.app_id ||= ask_application()
|
184
|
+
|
185
|
+
# Retrieve the application
|
186
|
+
application = Application.get(options.app_id)
|
187
|
+
raise "Cannot find application #{options.app_id}" if application.nil?
|
188
|
+
|
189
|
+
# Retrieve authorization token
|
190
|
+
options.username ||= ask("Username: ")
|
191
|
+
options.password ||= ask("Password: ") {|q| q.echo = '*'}
|
192
|
+
authorizer = Authoritarian::Twitter.new(
|
193
|
+
application.consumer_key,
|
194
|
+
application.consumer_secret
|
195
|
+
)
|
196
|
+
auth = authorizer.authorize(options.username, options.password)
|
197
|
+
|
198
|
+
# Create a user
|
199
|
+
user = User.new(:application => application)
|
200
|
+
user.username = options.username
|
201
|
+
user.oauth_token = auth[:token]
|
202
|
+
user.oauth_token_secret = auth[:secret]
|
203
|
+
user.save
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
# Remove User
|
208
|
+
command :'remove user' do |c|
|
209
|
+
c.syntax = 'authoritarian remove user [options]'
|
210
|
+
c.description = 'Removes a user from a registered application.'
|
211
|
+
c.option '--app-id ID', String, 'The identifier for the authorizing application.'
|
212
|
+
c.when_called do|args, options|
|
213
|
+
# Retrieve the application
|
214
|
+
options.app_id ||= ask_application()
|
215
|
+
application = Application.get(options.app_id)
|
216
|
+
raise "Cannot find application #{options.app_id}" if application.nil?
|
217
|
+
|
218
|
+
# Retrieve the user to remove
|
219
|
+
options.user_id ||= ask_user(application, true, 'Please choose a user to remove')
|
220
|
+
user = User.get(options.user_id)
|
221
|
+
raise "Cannot find user #{options.user_id}" if user.nil?
|
222
|
+
|
223
|
+
# Delete user
|
224
|
+
user.destroy
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
# Show authorized users
|
229
|
+
command :'show users' do |c|
|
230
|
+
c.syntax = 'authoritarian show users'
|
231
|
+
c.description = 'Displays all users authorized to registered applications.'
|
232
|
+
c.option '--app-id ID', String, 'The identifier for the authorizing application.'
|
233
|
+
c.option '--all', 'Shows all user data.'
|
234
|
+
c.when_called do|args, options|
|
235
|
+
options.app_id ||= ask_application()
|
236
|
+
|
237
|
+
# Retrieve the application
|
238
|
+
application = Application.get(options.app_id)
|
239
|
+
raise "Cannot find application #{options.app_id}" if application.nil?
|
240
|
+
users = application.users
|
241
|
+
|
242
|
+
if users.length == 0
|
243
|
+
say "There are no users authorized to use #{application.name}."
|
244
|
+
else
|
245
|
+
user_table = table do |t|
|
246
|
+
t.headings = 'ID', 'Username'
|
247
|
+
|
248
|
+
# Optionally add oauth info
|
249
|
+
if options.all
|
250
|
+
t.headings << 'OAuth Token'
|
251
|
+
t.headings << 'OAuth Token Secret'
|
252
|
+
end
|
253
|
+
|
254
|
+
users.each do |user|
|
255
|
+
row = [
|
256
|
+
user.id,
|
257
|
+
user.username,
|
258
|
+
]
|
259
|
+
|
260
|
+
# Optionally add oauth info
|
261
|
+
if options.all
|
262
|
+
row << user.oauth_token
|
263
|
+
row << user.oauth_token_secret
|
264
|
+
end
|
265
|
+
|
266
|
+
t << row
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
puts user_table
|
271
|
+
end
|
272
|
+
end
|
273
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
dir = File.dirname(File.expand_path(__FILE__))
|
2
|
+
$:.unshift(dir)
|
3
|
+
|
4
|
+
require 'oauth'
|
5
|
+
require 'mechanize'
|
6
|
+
require 'dm-core'
|
7
|
+
require 'dm-migrations'
|
8
|
+
require 'dm-timestamps'
|
9
|
+
require 'dm-validations'
|
10
|
+
require 'authoritarian/model'
|
11
|
+
require 'authoritarian/twitter'
|
12
|
+
require 'authoritarian/version'
|
13
|
+
|
14
|
+
module Authoritarian
|
15
|
+
class InvalidLoginError < StandardError; end
|
16
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class Application
|
2
|
+
include ::DataMapper::Resource
|
3
|
+
has n, :users
|
4
|
+
|
5
|
+
property :id, Serial
|
6
|
+
property :type, String
|
7
|
+
property :name, String
|
8
|
+
property :consumer_key, String
|
9
|
+
property :consumer_secret, String
|
10
|
+
timestamps :at
|
11
|
+
|
12
|
+
validates_presence_of :type
|
13
|
+
validates_presence_of :name
|
14
|
+
validates_presence_of :consumer_key
|
15
|
+
validates_presence_of :consumer_secret
|
16
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
class User
|
2
|
+
include ::DataMapper::Resource
|
3
|
+
belongs_to :application
|
4
|
+
|
5
|
+
property :id, Serial
|
6
|
+
property :username, String
|
7
|
+
property :oauth_token, String
|
8
|
+
property :oauth_token_secret, String
|
9
|
+
timestamps :at
|
10
|
+
|
11
|
+
validates_presence_of :application_id
|
12
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
module Authoritarian
|
2
|
+
# This class performs OAuth authorization for Twitter user accounts.
|
3
|
+
class Twitter
|
4
|
+
############################################################################
|
5
|
+
# Constructor
|
6
|
+
############################################################################
|
7
|
+
|
8
|
+
# Creates a Twitter OAuth authorizer.
|
9
|
+
def initialize(consumer_key=nil, consumer_secret=nil)
|
10
|
+
self.consumer_key = consumer_key
|
11
|
+
self.consumer_secret = consumer_secret
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
############################################################################
|
16
|
+
# Public Attributes
|
17
|
+
############################################################################
|
18
|
+
|
19
|
+
# The consumer key for the application that is authorizing the user.
|
20
|
+
attr_accessor :consumer_key
|
21
|
+
|
22
|
+
# The consumer secret for the application that is authorizing the user.
|
23
|
+
attr_accessor :consumer_secret
|
24
|
+
|
25
|
+
|
26
|
+
############################################################################
|
27
|
+
# Public Methods
|
28
|
+
############################################################################
|
29
|
+
|
30
|
+
def authorize(username, password)
|
31
|
+
# Generate request token
|
32
|
+
request_token = consumer.get_request_token
|
33
|
+
|
34
|
+
# Create in-process browser
|
35
|
+
mechanize = Mechanize.new do |agent|
|
36
|
+
#agent.user_agent_alias = 'Authoritarian'
|
37
|
+
end
|
38
|
+
|
39
|
+
# Request authorization
|
40
|
+
mechanize.get(generate_authorize_url(request_token)) do |login_page|
|
41
|
+
# Login and allow
|
42
|
+
form = *login_page.forms
|
43
|
+
form.field_with(:name => 'session[username_or_email]').value = username
|
44
|
+
form.field_with(:name => 'session[password]').value = password
|
45
|
+
auth_page = form.submit(form.button_with(:value => 'Allow'))
|
46
|
+
|
47
|
+
# Verify returned page has no errors
|
48
|
+
error = auth_page.parser.css('p.oauth-errors').text.strip
|
49
|
+
if error != ''
|
50
|
+
raise Authoritarian::InvalidLoginError.new(error)
|
51
|
+
end
|
52
|
+
|
53
|
+
# If not then get access token from PIN
|
54
|
+
pin = auth_page.parser.css('div#oauth_pin').text.strip
|
55
|
+
|
56
|
+
# Create OAuth token from PIN
|
57
|
+
access_token = request_token.get_access_token(:oauth_verifier => pin)
|
58
|
+
return {:token => access_token.token, :secret => access_token.secret}
|
59
|
+
end
|
60
|
+
|
61
|
+
return nil
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
############################################################################
|
66
|
+
# Private Methods
|
67
|
+
############################################################################
|
68
|
+
|
69
|
+
protected
|
70
|
+
|
71
|
+
# Generates the authorization url to have the user log into.
|
72
|
+
def generate_authorize_url(request_token)
|
73
|
+
# Create request
|
74
|
+
request =
|
75
|
+
consumer.create_signed_request(
|
76
|
+
:get,
|
77
|
+
consumer.authorize_path,
|
78
|
+
request_token,
|
79
|
+
{:oauth_callback => 'oob'}
|
80
|
+
)
|
81
|
+
|
82
|
+
# Alter parameters
|
83
|
+
params = request['Authorization'].sub(/^OAuth\s+/, '').split(/,\s+/).map { |p|
|
84
|
+
k, v = p.split('=')
|
85
|
+
v =~ /"(.*?)"/
|
86
|
+
"#{k}=#{CGI::escape($1)}"
|
87
|
+
}.join('&')
|
88
|
+
|
89
|
+
# Return authorize url
|
90
|
+
return "https://api.twitter.com#{request.path}?#{params}"
|
91
|
+
end
|
92
|
+
|
93
|
+
# The OAuth consumer object.
|
94
|
+
def consumer
|
95
|
+
@consumer ||=
|
96
|
+
::OAuth::Consumer.new(
|
97
|
+
consumer_key,
|
98
|
+
consumer_secret,
|
99
|
+
:site => "https://api.twitter.com"
|
100
|
+
)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
metadata
ADDED
@@ -0,0 +1,218 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: authoritarian
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 0
|
10
|
+
version: 0.1.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Ben Johnson
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-02-28 00:00:00 -07:00
|
19
|
+
default_executable: authoritarian
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: mechanize
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 23
|
30
|
+
segments:
|
31
|
+
- 1
|
32
|
+
- 0
|
33
|
+
- 0
|
34
|
+
version: 1.0.0
|
35
|
+
type: :runtime
|
36
|
+
version_requirements: *id001
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: data_mapper
|
39
|
+
prerelease: false
|
40
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
hash: 19
|
46
|
+
segments:
|
47
|
+
- 1
|
48
|
+
- 0
|
49
|
+
- 2
|
50
|
+
version: 1.0.2
|
51
|
+
type: :runtime
|
52
|
+
version_requirements: *id002
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: dm-sqlite-adapter
|
55
|
+
prerelease: false
|
56
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
hash: 19
|
62
|
+
segments:
|
63
|
+
- 1
|
64
|
+
- 0
|
65
|
+
- 2
|
66
|
+
version: 1.0.2
|
67
|
+
type: :runtime
|
68
|
+
version_requirements: *id003
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: commander
|
71
|
+
prerelease: false
|
72
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ~>
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
hash: 57
|
78
|
+
segments:
|
79
|
+
- 4
|
80
|
+
- 0
|
81
|
+
- 3
|
82
|
+
version: 4.0.3
|
83
|
+
type: :runtime
|
84
|
+
version_requirements: *id004
|
85
|
+
- !ruby/object:Gem::Dependency
|
86
|
+
name: terminal-table
|
87
|
+
prerelease: false
|
88
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ~>
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
hash: 3
|
94
|
+
segments:
|
95
|
+
- 1
|
96
|
+
- 4
|
97
|
+
- 2
|
98
|
+
version: 1.4.2
|
99
|
+
type: :runtime
|
100
|
+
version_requirements: *id005
|
101
|
+
- !ruby/object:Gem::Dependency
|
102
|
+
name: rspec
|
103
|
+
prerelease: false
|
104
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ~>
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
hash: 31
|
110
|
+
segments:
|
111
|
+
- 2
|
112
|
+
- 4
|
113
|
+
- 0
|
114
|
+
version: 2.4.0
|
115
|
+
type: :development
|
116
|
+
version_requirements: *id006
|
117
|
+
- !ruby/object:Gem::Dependency
|
118
|
+
name: mocha
|
119
|
+
prerelease: false
|
120
|
+
requirement: &id007 !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
122
|
+
requirements:
|
123
|
+
- - ~>
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
hash: 35
|
126
|
+
segments:
|
127
|
+
- 0
|
128
|
+
- 9
|
129
|
+
- 12
|
130
|
+
version: 0.9.12
|
131
|
+
type: :development
|
132
|
+
version_requirements: *id007
|
133
|
+
- !ruby/object:Gem::Dependency
|
134
|
+
name: unindentable
|
135
|
+
prerelease: false
|
136
|
+
requirement: &id008 !ruby/object:Gem::Requirement
|
137
|
+
none: false
|
138
|
+
requirements:
|
139
|
+
- - ~>
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
hash: 27
|
142
|
+
segments:
|
143
|
+
- 0
|
144
|
+
- 1
|
145
|
+
- 0
|
146
|
+
version: 0.1.0
|
147
|
+
type: :development
|
148
|
+
version_requirements: *id008
|
149
|
+
- !ruby/object:Gem::Dependency
|
150
|
+
name: fakeweb
|
151
|
+
prerelease: false
|
152
|
+
requirement: &id009 !ruby/object:Gem::Requirement
|
153
|
+
none: false
|
154
|
+
requirements:
|
155
|
+
- - ~>
|
156
|
+
- !ruby/object:Gem::Version
|
157
|
+
hash: 27
|
158
|
+
segments:
|
159
|
+
- 1
|
160
|
+
- 3
|
161
|
+
- 0
|
162
|
+
version: 1.3.0
|
163
|
+
type: :development
|
164
|
+
version_requirements: *id009
|
165
|
+
description:
|
166
|
+
email:
|
167
|
+
- benbjohnson@yahoo.com
|
168
|
+
executables:
|
169
|
+
- authoritarian
|
170
|
+
extensions: []
|
171
|
+
|
172
|
+
extra_rdoc_files: []
|
173
|
+
|
174
|
+
files:
|
175
|
+
- lib/authoritarian/model/application.rb
|
176
|
+
- lib/authoritarian/model/user.rb
|
177
|
+
- lib/authoritarian/model.rb
|
178
|
+
- lib/authoritarian/twitter.rb
|
179
|
+
- lib/authoritarian/version.rb
|
180
|
+
- lib/authoritarian.rb
|
181
|
+
- README.md
|
182
|
+
- bin/authoritarian
|
183
|
+
has_rdoc: true
|
184
|
+
homepage: http://github.com/benbjohnson/authoritarian
|
185
|
+
licenses: []
|
186
|
+
|
187
|
+
post_install_message:
|
188
|
+
rdoc_options: []
|
189
|
+
|
190
|
+
require_paths:
|
191
|
+
- lib
|
192
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
193
|
+
none: false
|
194
|
+
requirements:
|
195
|
+
- - ">="
|
196
|
+
- !ruby/object:Gem::Version
|
197
|
+
hash: 3
|
198
|
+
segments:
|
199
|
+
- 0
|
200
|
+
version: "0"
|
201
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
202
|
+
none: false
|
203
|
+
requirements:
|
204
|
+
- - ">="
|
205
|
+
- !ruby/object:Gem::Version
|
206
|
+
hash: 3
|
207
|
+
segments:
|
208
|
+
- 0
|
209
|
+
version: "0"
|
210
|
+
requirements: []
|
211
|
+
|
212
|
+
rubyforge_project:
|
213
|
+
rubygems_version: 1.3.7
|
214
|
+
signing_key:
|
215
|
+
specification_version: 3
|
216
|
+
summary: A command line OAuth authorization tool.
|
217
|
+
test_files: []
|
218
|
+
|