authorization 1.0.11
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.txt +170 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +512 -0
- data/README.txt +451 -0
- data/README_developers.txt +43 -0
- data/Rakefile +39 -0
- data/UPGRADE.rdoc +13 -0
- data/VERSION +1 -0
- data/about.yml +8 -0
- data/authorization.gemspec +66 -0
- data/doc/authorization_example.gif +0 -0
- data/doc/authorization_example.rb +38 -0
- data/generators/role_model/USAGE +20 -0
- data/generators/role_model/role_model_generator.rb +35 -0
- data/generators/role_model/templates/fixtures.yml +5 -0
- data/generators/role_model/templates/migration.rb +21 -0
- data/generators/role_model/templates/model.rb +8 -0
- data/generators/role_model/templates/role_model.rb +9 -0
- data/generators/role_model/templates/role_user_model.rb +5 -0
- data/generators/role_model/templates/unit_test.rb +10 -0
- data/init.rb +1 -0
- data/install.rb +2 -0
- data/lib/authorization.rb +176 -0
- data/lib/publishare/exceptions.rb +41 -0
- data/lib/publishare/hardwired_roles.rb +82 -0
- data/lib/publishare/identity.rb +119 -0
- data/lib/publishare/object_roles_table.rb +119 -0
- data/lib/publishare/parser.rb +210 -0
- data/tasks/authorization_tasks.rake +4 -0
- metadata +98 -0
data/README.txt
ADDED
@@ -0,0 +1,451 @@
|
|
1
|
+
= Authorization plugin
|
2
|
+
|
3
|
+
See the following wiki page for the latest version of this documentation:
|
4
|
+
|
5
|
+
http://code.google.com/p/rails-authorization-plugin/w/list
|
6
|
+
|
7
|
+
This plugin provides a flexible way to add authorization to Rails.
|
8
|
+
|
9
|
+
The authorization process decides whether a user is allowed access to some
|
10
|
+
feature. It is distinct from the authentication process, which tries to
|
11
|
+
confirm a user is authentic, not an imposter. There are many authentication
|
12
|
+
systems available for Rails, e.g., acts_as_authenticated and LoginEngine. This
|
13
|
+
authorization system will play nicely with them as long as some simple
|
14
|
+
requirements are met:
|
15
|
+
|
16
|
+
1. User objects are available that implement a has_role?(role,
|
17
|
+
authorizable_object = nil) method. This requirement can be easily
|
18
|
+
handled by using acts_as_authorized_user in the User-like class.
|
19
|
+
|
20
|
+
2. If you want to use "role of model" authorization expressions, like "owner of
|
21
|
+
resource" or "eligible for :award", then your models with roles must
|
22
|
+
implement an accepts_role?(role, user) method. This requirement can
|
23
|
+
be handled by using acts_as_authorizable in the model class.
|
24
|
+
|
25
|
+
The authorization plugin provides the following:
|
26
|
+
|
27
|
+
* A simple way of checking authorization at either the class or instance method
|
28
|
+
level using #permit and #permit?
|
29
|
+
|
30
|
+
* Authorization using roles for the entire application, a model class, or an
|
31
|
+
instance of a model (i.e., a particular object).
|
32
|
+
|
33
|
+
* Some english-like dynamic methods that draw on the defined roles. You will be
|
34
|
+
able to use methods like "user.is_fan_of angelina" or "angelina.has_fans?",
|
35
|
+
where a 'fan' is only defined in the roles table.
|
36
|
+
|
37
|
+
* Pick-and-choose a mixin for your desired level of database complexity. For
|
38
|
+
all the features, you will want to use "object roles table" (see below)
|
39
|
+
|
40
|
+
|
41
|
+
== Installation
|
42
|
+
|
43
|
+
Installation Instructions
|
44
|
+
|
45
|
+
Installation of the Authorization plugin is quick and easy.
|
46
|
+
|
47
|
+
Step 1
|
48
|
+
|
49
|
+
Open a terminal and change directory to the root of your
|
50
|
+
Ruby on Rails application referred to here as 'Rails.root'. You
|
51
|
+
can choose to install the plugin in the standard recommended way,
|
52
|
+
or as a Git sub-module.
|
53
|
+
|
54
|
+
Step 2 (Standard install, recommended)
|
55
|
+
|
56
|
+
Run the following command in your Rails.root:
|
57
|
+
|
58
|
+
./script/plugin install http://rails-authorization-plugin.googlecode.com/svn/trunk/authorization
|
59
|
+
|
60
|
+
This will install the latest version of the plugin from SVN trunk
|
61
|
+
into your Rails.root/vendor/plugins/authorization directory.
|
62
|
+
|
63
|
+
Step 2 (Alternative install using Git sub-module, for
|
64
|
+
advanced users of the Git SCM)
|
65
|
+
|
66
|
+
The source code for this plugin is maintained in a Git SCM
|
67
|
+
repository (The code in the SVN repository here at Google
|
68
|
+
Code is a read-only mirror). The Git repository will always
|
69
|
+
have the latest version of the code.
|
70
|
+
|
71
|
+
You can install the plugin using Git sub-modules (which
|
72
|
+
are akin to using SVN externals). Installing this way allows
|
73
|
+
you to update the plugin code later if needed (but note that
|
74
|
+
it will not update any generated code created earlier by this
|
75
|
+
plugin such as migrations, you will need to update that manually).
|
76
|
+
Also note that if you are deploying your code using Capistrano
|
77
|
+
this method may cause issues if you are not careful (e.g. the code
|
78
|
+
will be deployed but the sub-modules will not be updated or
|
79
|
+
installed at all).
|
80
|
+
|
81
|
+
From your Rails.root directory run:
|
82
|
+
|
83
|
+
git submodule add git://github.com/DocSavage/rails-authorization-plugin.git vendor/plugins/authorization
|
84
|
+
|
85
|
+
You should be able to update this plugin in the future with
|
86
|
+
the simple command (again from Rails.root):
|
87
|
+
|
88
|
+
git submodule update
|
89
|
+
|
90
|
+
|
91
|
+
== Configuration
|
92
|
+
|
93
|
+
These instructions will show you how to do the initial configuration
|
94
|
+
of the plugin.
|
95
|
+
|
96
|
+
Choose a Mixin Type
|
97
|
+
|
98
|
+
Hardwired Roles
|
99
|
+
This is the simplest way to use the plugin and requires no database.
|
100
|
+
Roles are assumed to be coded into the Model classes using the
|
101
|
+
has_role?(role, obj = nil) method. This method is however more
|
102
|
+
limited in the functionality available to you.
|
103
|
+
|
104
|
+
Object Roles (Recommended, DB Required)
|
105
|
+
The Object Roles Table mixin provides full support for authorization
|
106
|
+
expressions within a database by add a polymorphic field to the
|
107
|
+
Role table. Because roles have polymorphic associations to an
|
108
|
+
authorizable object, we can assign a user to a role for any model
|
109
|
+
instance. So you could declare user X to be a moderator for workshop Y,
|
110
|
+
or you could make user A be the owner of resource B.
|
111
|
+
|
112
|
+
The identity module adds a number of dynamic methods that use defined
|
113
|
+
roles. The user-like model gets methods like `user.is_moderator_of
|
114
|
+
group (sets user to "moderator" of group`), user.is_moderator? (returns
|
115
|
+
true/false if user has some role "moderator"), and group.has_moderators
|
116
|
+
(returns an array of users that have role "moderator" for the group). If
|
117
|
+
you prefer not to have these dynamic methods available, you can simply
|
118
|
+
comment out the inclusion of the identity module within object_roles_table.rb.
|
119
|
+
|
120
|
+
Initial Configuration Instructions
|
121
|
+
|
122
|
+
Choose one of the installation types identified above and make sure your
|
123
|
+
application provides a current_user method or something that returns the
|
124
|
+
current user object (resful_authentication provides this out of the box).
|
125
|
+
|
126
|
+
At the top of your Rails.root/config/environment.rb file add something
|
127
|
+
like the following (customized for your controllers and actions of course):
|
128
|
+
|
129
|
+
...
|
130
|
+
|
131
|
+
# Authorization plugin for role based access control
|
132
|
+
# You can override default authorization system constants here.
|
133
|
+
|
134
|
+
# Can be 'object roles' or 'hardwired'
|
135
|
+
AUTHORIZATION_MIXIN = "object roles"
|
136
|
+
|
137
|
+
# NOTE : If you use modular controllers like '/admin/products' be sure
|
138
|
+
# to redirect to something like '/sessions' controller (with a leading slash)
|
139
|
+
# as shown in the example below or you will not get redirected properly
|
140
|
+
#
|
141
|
+
# This can be set to a hash or to an explicit path like '/login'
|
142
|
+
#
|
143
|
+
LOGIN_REQUIRED_REDIRECTION = { :controller => '/sessions', :action => 'new' }
|
144
|
+
PERMISSION_DENIED_REDIRECTION = { :controller => '/home', :action => 'index' }
|
145
|
+
|
146
|
+
# The method your auth scheme uses to store the location to redirect back to
|
147
|
+
STORE_LOCATION_METHOD = :store_location
|
148
|
+
|
149
|
+
# standard rails config below here
|
150
|
+
Rails::Initializer.run do |config|
|
151
|
+
|
152
|
+
...
|
153
|
+
|
154
|
+
Set the AUTHORIZATION_MIXIN constant to object roles or hardwired.
|
155
|
+
(See init.rb in this plugin for how the role support is mixed in.)
|
156
|
+
|
157
|
+
Set the LOGIN_REQUIRED_REDIRECTION to match the path or a hash with
|
158
|
+
the :controller and :action for your applications login page.
|
159
|
+
|
160
|
+
Set the PERMISSION_DENIED_REDIRECTION to match the path or a hash
|
161
|
+
with the :controller and :action for your applications permission denied page.
|
162
|
+
|
163
|
+
Set the STORE_LOCATION_METHOD to the method your application uses for
|
164
|
+
storing the current URL that the user should return to after
|
165
|
+
authentication (e.g. store_location).
|
166
|
+
|
167
|
+
See the PLUGIN_DIR\lib\authorization.rb file for the default values
|
168
|
+
of LOGIN_REQUIRED_REDIRECTION, PERMISSION_DENIED_REDIRECTION and STORE_LOCATION_METHOD.
|
169
|
+
|
170
|
+
|
171
|
+
Create the database tables
|
172
|
+
|
173
|
+
If you plan to use the object roles method you will need to setup a few
|
174
|
+
database tables. We have provided a database migration file
|
175
|
+
(Rails 2.0+ compatible) that will make this process easy for you.
|
176
|
+
If you plan to use the hardwired mixin, no extra database tables
|
177
|
+
are required. and you can skip to the next step.
|
178
|
+
|
179
|
+
Run the following command from your Rails.root (Note : The generator
|
180
|
+
takes a model name as its argument, which at this time must be 'Role'.):
|
181
|
+
|
182
|
+
./script/generate role_model Role
|
183
|
+
|
184
|
+
This will create:
|
185
|
+
|
186
|
+
Model: Rails.root/app/models/role.rb
|
187
|
+
Test: Rails.root/test/unit/role_test.rb
|
188
|
+
Fixtures: Rails.root/test/fixtures/roles.yml
|
189
|
+
Migration: Rails.root/db/migrate/###_add_role.rb
|
190
|
+
|
191
|
+
And now you will need to run a database migration from your Rails.root:
|
192
|
+
|
193
|
+
rake db:migrate
|
194
|
+
|
195
|
+
Jumpstarting with a mixin
|
196
|
+
|
197
|
+
Now we need to add the methods needed by each of your models that will
|
198
|
+
participate in role based authorization. Typically these models fall into
|
199
|
+
two categories, the User model, and all other models that will have
|
200
|
+
roles available for use.
|
201
|
+
|
202
|
+
For a typical installation you would add both mixins to your User model.
|
203
|
+
|
204
|
+
class User < ActiveRecord::Base
|
205
|
+
|
206
|
+
# Authorization plugin
|
207
|
+
acts_as_authorized_user
|
208
|
+
acts_as_authorizable
|
209
|
+
|
210
|
+
...
|
211
|
+
|
212
|
+
Then in each additional model that you want to be able to restrict based
|
213
|
+
on role you would add just the acts_as_authorizable mixin like this:
|
214
|
+
|
215
|
+
class Event < ActiveRecord::Base
|
216
|
+
|
217
|
+
acts_as_authorizable
|
218
|
+
|
219
|
+
...
|
220
|
+
|
221
|
+
You are done with the configuration!
|
222
|
+
|
223
|
+
|
224
|
+
== The Specifics
|
225
|
+
|
226
|
+
=== permit and permit?
|
227
|
+
|
228
|
+
permit and permit? take an authorization expression and a hash of options that
|
229
|
+
typically includes any objects that need to be queried:
|
230
|
+
|
231
|
+
permit <authorization expression> [, options hash ]
|
232
|
+
permit? <authorization expression> [, options hash ]
|
233
|
+
|
234
|
+
The difference between permit and permit? is redirection. permit is a
|
235
|
+
declarative statement and redirects by default. It can also be used as a class
|
236
|
+
or an instance method, gating the access to an entire controller in a
|
237
|
+
before_filter fashion.
|
238
|
+
|
239
|
+
permit? is only an instance method, can be used within expressions, does not
|
240
|
+
redirect by default.
|
241
|
+
|
242
|
+
The authorization expression is a boolean expression made up of permitted
|
243
|
+
roles, prepositions, and authorizable models. Examples include "admin" (User
|
244
|
+
model assumed), "moderator of :workshop" (looks at options hash and then
|
245
|
+
@workshop), "'top salesman' at :company" (multiword roles delimited by single
|
246
|
+
quotes), or "scheduled for Exam" (queries class method of Exam).
|
247
|
+
|
248
|
+
Note that we can use several permitted prepositions ('of', 'for', 'in', 'on',
|
249
|
+
'to', 'at', 'by'). In the discussion below, we assume you use the "of"
|
250
|
+
preposition. You can modify the permitted prepositions by changing the constant
|
251
|
+
in Authorization::Base::Parser.
|
252
|
+
|
253
|
+
* If a specified role has no "of <model>" designation, we assume it is a user
|
254
|
+
role (i.e., the model is the user-like object).
|
255
|
+
|
256
|
+
* If an "of model" designation is given but no "model" key/value is supplied in
|
257
|
+
the hash, we check if an instance variable @model if it's available.
|
258
|
+
|
259
|
+
* If the model is capitalized, we assume it's a class and query
|
260
|
+
<tt>Model#self.accepts_role?</tt> (the class method) for the
|
261
|
+
permission. (Currently only available in ObjectRolesTable mixin.)
|
262
|
+
|
263
|
+
For each role, a query is sent to the appropriate model object.
|
264
|
+
|
265
|
+
The grammar for the authorization expression is:
|
266
|
+
|
267
|
+
<expr> ::= (<expr>) | not <expr> | <term> or <expr> | <term> and <expr> | <term>
|
268
|
+
<term> ::= <role> | <role> <preposition> <model>
|
269
|
+
<preposition> ::= of | for | in | on | to | at | by
|
270
|
+
<model> ::= /:*\w+/
|
271
|
+
<role> ::= /\w+/ | /'.*'/
|
272
|
+
|
273
|
+
Parentheses should be used to clarify permissions. Note that you may prefix the
|
274
|
+
model with an optional ":" -- the first versions of Authorization plugin made
|
275
|
+
this mandatory but it's now optional since the mandatory preposition makes
|
276
|
+
models unambiguous.
|
277
|
+
|
278
|
+
==== Options
|
279
|
+
|
280
|
+
<tt>:allow_guests => false</tt>. We can allow permission processing without a
|
281
|
+
current user object. The default is <tt>false</tt>.
|
282
|
+
|
283
|
+
<tt>:user</tt> => A <tt>user</tt> object.
|
284
|
+
|
285
|
+
<tt>:get_user_method => method</tt> that will return a <tt>user</tt>
|
286
|
+
object. Default is <tt>#current_user</tt>, which is the how
|
287
|
+
<tt>acts_as_authenticated</tt> works.
|
288
|
+
|
289
|
+
<tt>:only => [ :method1, :method2 ]</tt>. Array of methods to apply permit (not
|
290
|
+
valid when used in instance methods)
|
291
|
+
|
292
|
+
<tt>:except => [ :method1, :method2 ]</tt>. Array of methods that won't have
|
293
|
+
permission checking (not valid when used in instance methods)
|
294
|
+
|
295
|
+
<tt>:redirect => bool</tt>. default is <tt>true</tt>. If <tt>false</tt>, permit
|
296
|
+
will not redirect to denied page.
|
297
|
+
|
298
|
+
<tt>:login_required_redirection => path or hash</tt> where user will be
|
299
|
+
redirected if not logged in (default is "{ :controller => 'session', :action =>
|
300
|
+
'new' }")
|
301
|
+
|
302
|
+
<tt>:login_required_message => 'my message'</tt> (default is 'Login is required
|
303
|
+
to access the requested page.')
|
304
|
+
|
305
|
+
<tt>:permission_denied_redirection => path or hash</tt> where user will be
|
306
|
+
redirected if logged in but not authorized (default is '')
|
307
|
+
|
308
|
+
<tt>:permission_denied_message => 'my message</tt> (default is 'Permission
|
309
|
+
denied. You cannot access the requested page.')
|
310
|
+
|
311
|
+
=== Setting and getting the roles
|
312
|
+
|
313
|
+
Roles are set by #has_role and #accepts_role methods that are mixed into the
|
314
|
+
User-like object and the authorizable models. User objects can set roles and
|
315
|
+
optionally an object scope for that role:
|
316
|
+
|
317
|
+
user.has_role 'site_admin'
|
318
|
+
user.has_role 'moderator', group
|
319
|
+
user.has_no_role 'site_admin'
|
320
|
+
user.has_no_role 'moderator', group
|
321
|
+
user.has_role 'member', Group
|
322
|
+
|
323
|
+
Note that the last method sets role "member" on a class "Group". Roles can be
|
324
|
+
set with three scopes: entire application (no class or object specified), a
|
325
|
+
model class, or an instance of a model (i.e., a model object).
|
326
|
+
|
327
|
+
Models set roles for specific users:
|
328
|
+
|
329
|
+
a_model.accepts_role 'moderator', user
|
330
|
+
a_model.accepts_no_role 'moderator', user
|
331
|
+
Model.accepts_role 'class moderator', user
|
332
|
+
|
333
|
+
The method language has been chosen to aid memory of the argument order. A user
|
334
|
+
has a role "foo", so the role string immediately follows has_role. Similarly, a
|
335
|
+
model accepts a role "foo", so the role string immediately follows
|
336
|
+
accepts_role. Then we append the scope.
|
337
|
+
|
338
|
+
Sometimes the user-like object might be an authorizable object as well, for example, when you
|
339
|
+
allow 'friend' roles for users. In this case, the user-like object can be declared to be
|
340
|
+
<tt>acts_as_authorizable</tt> as well as <tt>acts_as_authorized_user</tt>.
|
341
|
+
|
342
|
+
Role queries follow the same pattern as the setting of roles:
|
343
|
+
|
344
|
+
user.has_role? 'moderator'
|
345
|
+
user.has_role? 'moderator', group
|
346
|
+
user.has_role? 'member', Group
|
347
|
+
|
348
|
+
a_model.accepts_role? 'moderator', user
|
349
|
+
Model.accepts_role? 'moderator', user
|
350
|
+
|
351
|
+
When a user is queried without specifying either a model class or object, it
|
352
|
+
returns true if the user has *any* matching role. For example,
|
353
|
+
<tt>user.has_role? 'moderator'</tt> returns true if the user is 'moderator' of
|
354
|
+
a class, a model object, or just a generic 'moderator'. Note that if you say
|
355
|
+
<tt>user.has_role 'moderator'</tt>, the user does not become 'moderator' for
|
356
|
+
all classes and model objects; the user simply has a generic role 'moderator'.
|
357
|
+
|
358
|
+
==== Dynamic methods through the Identity mixin
|
359
|
+
|
360
|
+
The Object Roles Table version includes some dynamic methods that use the roles
|
361
|
+
table. For example, if you have roles like "eligible", "moderator", and
|
362
|
+
"owner", you'll be able to use the following:
|
363
|
+
|
364
|
+
user.is_eligible_for_what --> returns array of authorizable objects for which user has role "eligible"
|
365
|
+
user.is_moderator_of? group --> returns true/false
|
366
|
+
user.is_moderator_of group --> sets user to have role "moderator" for object group.
|
367
|
+
user.is_administrator --> sets user to have role "administrator" not really tied to any object.
|
368
|
+
|
369
|
+
Models get has_* methods:
|
370
|
+
|
371
|
+
group.has_moderators --> returns array of users with role "moderator" on that group
|
372
|
+
group.has_moderators? --> returns true/false
|
373
|
+
|
374
|
+
Allowed prepositions are optional in the above dynamic methods. They are simply
|
375
|
+
syntactic sugar. For example, the following are equivalent:
|
376
|
+
|
377
|
+
user.is_member_of group
|
378
|
+
user.is_member_for group
|
379
|
+
user.is_member group
|
380
|
+
|
381
|
+
Allowed prepositions are required in the authorization expressions because they
|
382
|
+
are used to distinguish "role" and "role of :model" and "role of Model".
|
383
|
+
|
384
|
+
If you prefer not to pollute your namespace with these dynamic methods, do not
|
385
|
+
include the Identity module in <tt>object_roles_table.rb</tt>.
|
386
|
+
|
387
|
+
=== Pattern of use
|
388
|
+
|
389
|
+
We expect the application to provide the following methods:
|
390
|
+
|
391
|
+
==== #current_user
|
392
|
+
|
393
|
+
Returns some user object, like an instance of my favorite class,
|
394
|
+
<tt>UserFromMars</tt>. A <tt>user</tt> object, from the Authorization
|
395
|
+
viewpoint, is simply an object that provides a <tt>has_role?</tt> method.
|
396
|
+
|
397
|
+
Note that duck typing means we don't care what else the <tt>UserFromMars</tt>
|
398
|
+
might be doing. We only care that we can get an id from whatever it is, and we
|
399
|
+
can check if a given role string is associated with it. By using
|
400
|
+
<tt>acts_as_authorized_user</tt>, we inject what we need into the user object.
|
401
|
+
|
402
|
+
If you use an authorization expression "admin of :foo", we check permission by
|
403
|
+
asking <tt>foo</tt> if it <tt>accepts_role?('admin', user)</tt>. So for each
|
404
|
+
model that is used in an expression, we assume that it provides the
|
405
|
+
<tt>accepts_role?(role, user)</tt> method.
|
406
|
+
|
407
|
+
Note that <tt>user</tt> can be <tt>nil</tt> if <tt>:allow_guests => true</tt>.
|
408
|
+
|
409
|
+
==== #store_location (optional)
|
410
|
+
|
411
|
+
This method will be called if authorization fails and the user is about to be
|
412
|
+
redirected to the login action. This allows the application to return to the
|
413
|
+
desired page after login. If the application doesn't provide this method, the
|
414
|
+
method will not be called.
|
415
|
+
|
416
|
+
The name of the method for storing a location can be modified by changing the
|
417
|
+
constant STORE_LOCATION_METHOD in environment.rb. Also, the default login and
|
418
|
+
permission denied pages are defined by the constants LOGIN_REQUIRED_REDIRECTION
|
419
|
+
and PERMISSION_DENIED_REDIRECTION in authorization.rb and can be overriden in
|
420
|
+
your environment.rb.
|
421
|
+
|
422
|
+
=== Conventions
|
423
|
+
|
424
|
+
Roles specified without the "of model" designation:
|
425
|
+
|
426
|
+
1. We see if there is a <tt>current_user</tt> method available that will return
|
427
|
+
a user object. This method can be overridden with the <tt>:user</tt> hash.
|
428
|
+
|
429
|
+
2. Once a user object is determined, we pass the role to
|
430
|
+
<tt>user.has_role?</tt> and expect a true return value if the user has the
|
431
|
+
given role.
|
432
|
+
|
433
|
+
Roles specified with "of model" designation:
|
434
|
+
|
435
|
+
1. We attempt to query an object in the options hash that has a matching
|
436
|
+
key. Example: <tt>permit "knight for justice", :justice =>
|
437
|
+
@abstract_idea</tt>
|
438
|
+
|
439
|
+
2. If there is no object with a matching key, we see if there's a matching
|
440
|
+
instance variable. Example: @meeting defined before we use <tt>permit
|
441
|
+
"moderator of meeting"</tt>
|
442
|
+
|
443
|
+
3. Once the model object is determined, we pass the role and user (determined
|
444
|
+
in the manner above) to <tt>model.accepts_role?</tt>
|
445
|
+
|
446
|
+
=== More information
|
447
|
+
|
448
|
+
Information on this plugin and other development can be found at
|
449
|
+
the project home page:
|
450
|
+
|
451
|
+
http://code.google.com/p/rails-authorization-plugin/
|
@@ -0,0 +1,43 @@
|
|
1
|
+
|
2
|
+
INSTRUCTIONS FOR DEVELOPERS:
|
3
|
+
|
4
|
+
Pushing a read-only copy of the git repo master branch to the google code SVN repo.
|
5
|
+
--
|
6
|
+
|
7
|
+
Based on an article found at :
|
8
|
+
http://blog.nanorails.com/articles/2008/1/31/git-to-svn-read-only
|
9
|
+
|
10
|
+
Setup:
|
11
|
+
|
12
|
+
Clone a local copy of the git repo from GitHub:
|
13
|
+
|
14
|
+
'git clone git@github.com:DocSavage/rails-authorization-plugin.git'
|
15
|
+
|
16
|
+
cd rails-authorization-plugin
|
17
|
+
|
18
|
+
edit .git/config and add the following to the end:
|
19
|
+
|
20
|
+
--
|
21
|
+
[svn-remote "googlecode"]
|
22
|
+
url = https://rails-authorization-plugin.googlecode.com/svn/trunk
|
23
|
+
fetch = :refs/remotes/googlecode
|
24
|
+
--
|
25
|
+
|
26
|
+
run : 'git svn fetch'
|
27
|
+
|
28
|
+
run : 'git checkout -b local-svn googlecode'
|
29
|
+
|
30
|
+
run : 'git svn rebase'
|
31
|
+
|
32
|
+
run : 'git merge master'
|
33
|
+
|
34
|
+
run : 'git svn dcommit'
|
35
|
+
|
36
|
+
|
37
|
+
Now in the future as new changes are commit to master, do this to publish to GoogleCode:
|
38
|
+
|
39
|
+
$ git checkout local-svn
|
40
|
+
$ git merge master
|
41
|
+
$ git svn dcommit
|
42
|
+
|
43
|
+
And thats it!
|