andrewzielinski-lockdown 0.9.6

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 (59) hide show
  1. data/History.txt +195 -0
  2. data/README.txt +36 -0
  3. data/Rakefile +41 -0
  4. data/lib/lockdown.rb +70 -0
  5. data/lib/lockdown/context.rb +41 -0
  6. data/lib/lockdown/database.rb +105 -0
  7. data/lib/lockdown/frameworks/rails.rb +146 -0
  8. data/lib/lockdown/frameworks/rails/controller.rb +147 -0
  9. data/lib/lockdown/frameworks/rails/view.rb +61 -0
  10. data/lib/lockdown/helper.rb +95 -0
  11. data/lib/lockdown/orms/active_record.rb +68 -0
  12. data/lib/lockdown/permission.rb +204 -0
  13. data/lib/lockdown/rules.rb +289 -0
  14. data/lib/lockdown/session.rb +57 -0
  15. data/lib/lockdown/system.rb +57 -0
  16. data/rails_generators/lockdown/lockdown_generator.rb +273 -0
  17. data/rails_generators/lockdown/templates/app/controllers/permissions_controller.rb +22 -0
  18. data/rails_generators/lockdown/templates/app/controllers/sessions_controller.rb +39 -0
  19. data/rails_generators/lockdown/templates/app/controllers/user_groups_controller.rb +122 -0
  20. data/rails_generators/lockdown/templates/app/controllers/users_controller.rb +117 -0
  21. data/rails_generators/lockdown/templates/app/helpers/permissions_helper.rb +2 -0
  22. data/rails_generators/lockdown/templates/app/helpers/user_groups_helper.rb +2 -0
  23. data/rails_generators/lockdown/templates/app/helpers/users_helper.rb +2 -0
  24. data/rails_generators/lockdown/templates/app/models/permission.rb +13 -0
  25. data/rails_generators/lockdown/templates/app/models/profile.rb +10 -0
  26. data/rails_generators/lockdown/templates/app/models/user.rb +95 -0
  27. data/rails_generators/lockdown/templates/app/models/user_group.rb +15 -0
  28. data/rails_generators/lockdown/templates/app/views/permissions/index.html.erb +16 -0
  29. data/rails_generators/lockdown/templates/app/views/permissions/show.html.erb +26 -0
  30. data/rails_generators/lockdown/templates/app/views/sessions/new.html.erb +12 -0
  31. data/rails_generators/lockdown/templates/app/views/user_groups/edit.html.erb +33 -0
  32. data/rails_generators/lockdown/templates/app/views/user_groups/index.html.erb +20 -0
  33. data/rails_generators/lockdown/templates/app/views/user_groups/new.html.erb +31 -0
  34. data/rails_generators/lockdown/templates/app/views/user_groups/show.html.erb +29 -0
  35. data/rails_generators/lockdown/templates/app/views/users/edit.html.erb +51 -0
  36. data/rails_generators/lockdown/templates/app/views/users/index.html.erb +22 -0
  37. data/rails_generators/lockdown/templates/app/views/users/new.html.erb +50 -0
  38. data/rails_generators/lockdown/templates/app/views/users/show.html.erb +33 -0
  39. data/rails_generators/lockdown/templates/config/initializers/lockit.rb +1 -0
  40. data/rails_generators/lockdown/templates/db/migrate/create_admin_user.rb +17 -0
  41. data/rails_generators/lockdown/templates/db/migrate/create_permissions.rb +19 -0
  42. data/rails_generators/lockdown/templates/db/migrate/create_profiles.rb +26 -0
  43. data/rails_generators/lockdown/templates/db/migrate/create_user_groups.rb +19 -0
  44. data/rails_generators/lockdown/templates/db/migrate/create_users.rb +17 -0
  45. data/rails_generators/lockdown/templates/lib/lockdown/README +42 -0
  46. data/rails_generators/lockdown/templates/lib/lockdown/init.rb +122 -0
  47. data/spec/lockdown/database_spec.rb +158 -0
  48. data/spec/lockdown/frameworks/rails/controller_spec.rb +224 -0
  49. data/spec/lockdown/frameworks/rails/view_spec.rb +125 -0
  50. data/spec/lockdown/frameworks/rails_spec.rb +175 -0
  51. data/spec/lockdown/permission_spec.rb +156 -0
  52. data/spec/lockdown/rules_spec.rb +109 -0
  53. data/spec/lockdown/session_spec.rb +89 -0
  54. data/spec/lockdown/system_spec.rb +59 -0
  55. data/spec/lockdown_spec.rb +19 -0
  56. data/spec/rcov.opts +5 -0
  57. data/spec/spec.opts +3 -0
  58. data/spec/spec_helper.rb +1 -0
  59. metadata +112 -0
@@ -0,0 +1,122 @@
1
+ class <%= "#{namespace.camelcase}::" unless namespace.blank? %>UserGroupsController < ApplicationController
2
+ before_filter :find_user_group, :only => [:show, :edit, :update, :destroy]
3
+ after_filter :update_permissions, :only => [:create, :update]
4
+
5
+ # GET /user_groups
6
+ # GET /user_groups.xml
7
+ def index
8
+ @user_groups = UserGroup.find(:all)
9
+
10
+ respond_to do |format|
11
+ format.html # index.html.erb
12
+ format.xml { render :xml => @user_groups }
13
+ end
14
+ end
15
+
16
+ # GET /user_groups/1
17
+ # GET /user_groups/1.xml
18
+ def show
19
+ @all_permissions = Lockdown::System.permissions_assignable_for_user(current_user)
20
+ respond_to do |format|
21
+ format.html # show.html.erb
22
+ format.xml { render :xml => @user_group }
23
+ end
24
+ end
25
+
26
+ # GET /user_groups/new
27
+ # GET /user_groups/new.xml
28
+ def new
29
+ @user_group = UserGroup.new
30
+ @all_permissions = Lockdown::System.permissions_assignable_for_user(current_user)
31
+
32
+ respond_to do |format|
33
+ format.html # new.html.erb
34
+ format.xml { render :xml => @user_group }
35
+ end
36
+ end
37
+
38
+ # GET /user_groups/1/edit
39
+ def edit
40
+ @all_permissions = Lockdown::System.permissions_assignable_for_user(current_user)
41
+ end
42
+
43
+ # POST /user_groups
44
+ # POST /user_groups.xml
45
+ def create
46
+ @user_group = UserGroup.new(params[:user_group])
47
+
48
+ respond_to do |format|
49
+ if @user_group.save
50
+ flash[:notice] = 'UserGroup was successfully created.'
51
+ <% if namespace %>
52
+ format.html { redirect_to(<%= namespace %>_user_group_path(@user_group)) }
53
+ <% else %>
54
+ format.html { redirect_to(user_group_path(@user_group)) }
55
+ <% end %>
56
+ format.xml { render :xml => @user_group, :status => :created, :location => @user_group }
57
+ else
58
+ @all_permissions = Lockdown::System.permissions_assignable_for_user(current_user)
59
+ format.html { render :action => "new" }
60
+ format.xml { render :xml => @user_group.errors, :status => :unprocessable_entity }
61
+ end
62
+ end
63
+ end
64
+
65
+ # PUT /user_groups/1
66
+ # PUT /user_groups/1.xml
67
+ def update
68
+ respond_to do |format|
69
+ if @user_group.update_attributes(params[:user_group])
70
+ flash[:notice] = 'UserGroup was successfully updated.'
71
+ <% if namespace %>
72
+ format.html { redirect_to(<%= namespace %>_user_group_path(@user_group)) }
73
+ <% else %>
74
+ format.html { redirect_to(user_group_path(@user_group)) }
75
+ <% end %>
76
+ format.xml { head :ok }
77
+ else
78
+ @all_permissions = Lockdown::System.permissions_assignable_for_user(current_user)
79
+ format.html { render :action => "edit" }
80
+ format.xml { render :xml => @user_group.errors, :status => :unprocessable_entity }
81
+ end
82
+ end
83
+ end
84
+
85
+ # DELETE /user_groups/1
86
+ # DELETE /user_groups/1.xml
87
+ def destroy
88
+ @user_group.destroy
89
+
90
+ respond_to do |format|
91
+ format.html { redirect_to(<%= namespace.blank? ? 'user_groups_path' : "#{namespace}_user_groups_path" %>) }
92
+ format.xml { head :ok }
93
+ end
94
+ end
95
+
96
+ private
97
+
98
+ def find_user_group
99
+ @user_group = UserGroup.find(params[:id])
100
+ if <%= action_name %> != "show" && Lockdown::System.has_user_group?(@user_group)
101
+ raise SecurityError,"Invalid attempt to modify user group."
102
+ end
103
+ end
104
+
105
+ def update_permissions
106
+ new_perm_ids = params.collect{|p| p[0].split("_")[1].to_i if p[0] =~ /^perm_/}.compact
107
+ #
108
+ # Removed previously associated permissions if not checked this time.
109
+ #
110
+ @user_group.permissions.dup.each do |p|
111
+ @user_group.permissions.delete(p) unless new_perm_ids.include?(p.id)
112
+ end
113
+
114
+ #
115
+ # Add in the new permissions
116
+ #
117
+ new_perm_ids.each do |id|
118
+ next if @user_group.permission_ids.include?(id)
119
+ @user_group.permissions << Permission.find(id)
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,117 @@
1
+ class <%= "#{namespace.camelcase}::" unless namespace.blank? %>UsersController < ApplicationController
2
+ before_filter :find_user, :only => [:show, :edit, :update, :destroy]
3
+ after_filter :update_user_groups, :only => [:create, :update]
4
+ # GET /users
5
+ # GET /users.xml
6
+ def index
7
+ @users = User.find :all, :include => [:profile, :user_groups]
8
+ respond_to do |format|
9
+ format.html # index.html.erb
10
+ format.xml { render :xml => @users }
11
+ end
12
+ end
13
+
14
+ # GET /users/1
15
+ # GET /users/1.xml
16
+ def show
17
+ @user_groups_for_user = Lockdown::System.user_groups_assignable_for_user(current_user)
18
+ respond_to do |format|
19
+ format.html # show.html.erb
20
+ format.xml { render :xml => @user }
21
+ end
22
+ end
23
+
24
+ # GET /users/new
25
+ # GET /users/new.xml
26
+ def new
27
+ @user = User.new
28
+ @user_groups_for_user = Lockdown::System.user_groups_assignable_for_user(current_user)
29
+ respond_to do |format|
30
+ format.html # new.html.erb
31
+ format.xml { render :xml => @user }
32
+ end
33
+ end
34
+
35
+ # GET /users/1/edit
36
+ def edit
37
+ @user_groups_for_user = Lockdown::System.user_groups_assignable_for_user(current_user)
38
+ end
39
+
40
+ # POST /users
41
+ # POST /users.xml
42
+ def create
43
+ @user = User.new(params[:user])
44
+
45
+ if @user.save
46
+ flash[:notice] = "Thanks for signing up!"
47
+ redirect_to(<%= namespace.blank? ? 'user_path(@user)' : "#{namespace}_user_path(@user)" %>)
48
+ else
49
+ @user_groups_for_user = Lockdown::System.user_groups_assignable_for_user(current_user)
50
+ flash[:error] = "Please correct the following issues"
51
+ render :action => "new"
52
+ end
53
+ end
54
+
55
+ # PUT /users/1
56
+ # PUT /users/1.xml
57
+ def update
58
+ @user.attributes = params[:user]
59
+
60
+ respond_to do |format|
61
+ if @user.save
62
+ flash[:notice] = 'User was successfully updated.'
63
+ format.html { redirect_to(<%= namespace.blank? ? 'user_path(@user)' : "#{namespace}_user_path(@user)"%>) }
64
+ format.xml { head :ok }
65
+ else
66
+ @user_groups_for_user = Lockdown::System.user_groups_assignable_for_user(current_user)
67
+ format.html { render :action => "edit" }
68
+ format.xml { render :xml => @user.errors, :status => :unprocessable_entity }
69
+ end
70
+ end
71
+ end
72
+
73
+ # DELETE /users/1
74
+ # DELETE /users/1.xml
75
+ def destroy
76
+ @user.destroy
77
+
78
+ respond_to do |format|
79
+ format.html { redirect_to(<%= namespace.blank? ? 'users_path' : "#{namespace}_users_path" %>) }
80
+ format.xml { head :ok }
81
+ end
82
+ end
83
+
84
+ def change_password
85
+ render :update do |page|
86
+ page.replace_html 'password', :partial => 'password'
87
+ end
88
+ end
89
+
90
+ private
91
+
92
+ def find_user
93
+ # Skip test if current user is an administrator
94
+ unless current_user_is_admin?
95
+ # Raise error if id not = current logged in user
96
+ raise SecurityError.new if (current_user_id != params[:id].to_i)
97
+ end
98
+ @user = User.find(params[:id])
99
+ raise SecurityError.new if @user.nil?
100
+ end
101
+
102
+ def update_user_groups
103
+ new_ug_ids = params.collect{|p| p[0].split("_")[1].to_i if p[0] =~ /^ug_/}.compact
104
+ # Removed previously associated user_groups if not checked this time.
105
+ #
106
+ @user.user_groups.dup.each do |g|
107
+ @user.user_groups.delete(g) unless new_ug_ids.include?(g.id)
108
+ end
109
+
110
+ # Add in the new permissions
111
+ #
112
+ new_ug_ids.each do |id|
113
+ next if @user.user_group_ids.include?(id)
114
+ @user.user_groups << UserGroup.find(id)
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,2 @@
1
+ module <%= "#{namespace.camelcase}::" unless namespace.blank? %>PermissionsHelper
2
+ end
@@ -0,0 +1,2 @@
1
+ module <%= "#{namespace.camelcase}::" unless namespace.blank? %>UserGroupsHelper
2
+ end
@@ -0,0 +1,2 @@
1
+ module <%= "#{namespace.camelcase}::" unless namespace.blank? %>UsersHelper
2
+ end
@@ -0,0 +1,13 @@
1
+ class Permission < ActiveRecord::Base
2
+ has_and_belongs_to_many :user_groups
3
+
4
+ def all_users
5
+ User.find_by_sql <<-SQL
6
+ select users.*
7
+ from users, user_groups_users, permissions_user_groups
8
+ where users.id = user_groups_users.user_id
9
+ and user_groups_users.user_group_id = permissions_user_groups.user_group_id
10
+ and permissions_user_groups.permission_id = #{self.id}
11
+ SQL
12
+ end
13
+ end
@@ -0,0 +1,10 @@
1
+ class Profile < ActiveRecord::Base
2
+ SYSTEM = 1
3
+
4
+ validates_presence_of :email, :first_name, :last_name
5
+
6
+ validates_length_of :email, :within => 5..100
7
+ validates_format_of :email, :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i
8
+
9
+ validates_uniqueness_of :email, :case_sensitive => false
10
+ end
@@ -0,0 +1,95 @@
1
+ require 'digest/sha1'
2
+ class User < ActiveRecord::Base
3
+ has_and_belongs_to_many :user_groups
4
+ belongs_to :profile
5
+
6
+ # Virtual attributes
7
+ attr_accessor :password
8
+
9
+ validates_presence_of :login
10
+ validates_presence_of :password, :if => :password_required?
11
+ validates_presence_of :password_confirmation, :if => :password_required?
12
+ validates_length_of :password, :within => 4..40, :if => :password_required?
13
+ validates_confirmation_of :password, :if => :password_required?
14
+ validates_length_of :login, :within => 3..40
15
+ validates_uniqueness_of :login, :case_sensitive => false
16
+
17
+ before_save :encrypt_password
18
+ before_save :save_profile
19
+
20
+ attr_accessible :login, :password, :password_confirmation,
21
+ :first_name, :last_name, :email
22
+
23
+ # Authenticates a user by their login name and unencrypted password.
24
+ # Returns the user or nil.
25
+ def self.authenticate(login, password)
26
+ u = find :first, :conditions => ['login = ?', login] # need to get the salt
27
+ u && u.authenticated?(password) ? u : nil
28
+ end
29
+
30
+ # Encrypts some data with the salt.
31
+ def self.encrypt(password, salt)
32
+ Digest::SHA1.hexdigest("--#{salt}--#{password}--")
33
+ end
34
+
35
+ # Encrypts the password with the user salt
36
+ def encrypt(password)
37
+ self.class.encrypt(password, salt)
38
+ end
39
+
40
+ def authenticated?(password)
41
+ crypted_password == encrypt(password)
42
+ end
43
+
44
+ def full_name
45
+ first_name + " " + last_name
46
+ end
47
+
48
+ # Profile information
49
+ def first_name
50
+ user_profile.first_name
51
+ end
52
+
53
+ def first_name=(string)
54
+ user_profile.first_name = string
55
+ end
56
+
57
+ def last_name
58
+ user_profile.last_name
59
+ end
60
+
61
+ def last_name=(string)
62
+ user_profile.last_name = string
63
+ end
64
+
65
+ def email
66
+ user_profile.email
67
+ end
68
+
69
+ def email=(string)
70
+ user_profile.email = string
71
+ end
72
+
73
+ def user_profile
74
+ self.profile || self.profile = Profile.new
75
+ end
76
+
77
+ protected
78
+
79
+ def encrypt_password
80
+ return if password.blank?
81
+ if new_record?
82
+ self.salt = Digest::SHA1.hexdigest("--#{Time.now.to_s}--#{login}--")
83
+ end
84
+ self.crypted_password = encrypt(password)
85
+ end
86
+
87
+ def save_profile
88
+ profile.save
89
+ end
90
+
91
+ def password_required?
92
+ (crypted_password.blank? || !password.blank?)
93
+ end
94
+
95
+ end
@@ -0,0 +1,15 @@
1
+ class UserGroup < ActiveRecord::Base
2
+ has_and_belongs_to_many :permissions
3
+ has_and_belongs_to_many :users
4
+
5
+ validates_presence_of :name
6
+
7
+ def all_users
8
+ User.find_by_sql <<-SQL
9
+ select users.*
10
+ from users, user_groups_users
11
+ where users.id = user_groups_users.user_id
12
+ and user_groups_users.user_group_id = #{self.id}
13
+ SQL
14
+ end
15
+ end
@@ -0,0 +1,16 @@
1
+ <h1>Listing Permissions</h1>
2
+
3
+ <table>
4
+ <tr>
5
+ <th>Name</th>
6
+ </tr>
7
+
8
+ <%% for permission in @permissions %>
9
+ <tr>
10
+ <td><%%=h permission.name %></td>
11
+ <td><%%= link_to 'Show', <%= namespace.blank? ? 'permission_path(permission)' : "#{namespace}_permission_path(permission)" %> %></td>
12
+ </tr>
13
+ <%% end %>
14
+ </table>
15
+
16
+ <br />
@@ -0,0 +1,26 @@
1
+ <p>
2
+ <b>Name</b><br />
3
+ <%%= h @permission.name %>
4
+ </p>
5
+ <p>
6
+ <b>Access rights:</b><br />
7
+ <%%
8
+ Lockdown::System.access_rights_for_permission(@permission).each do |access_right|
9
+ %>
10
+ <%%= access_right %><br/>
11
+ <%%
12
+ end
13
+ %>
14
+ </p>
15
+ <p>
16
+ <b>Users with permission:</b><br />
17
+ <%%
18
+ @permission.all_users.each do |user|
19
+ %>
20
+ <%%= link_to_or_show(user.full_name, <%= namespace.blank? ? 'user' : "#{namespace}_user_path(user)" %>) %><br/>
21
+ <%%
22
+ end
23
+ %>
24
+ </p>
25
+
26
+ <%%= link_to 'Back', <%= namespace.blank? ? 'permissions_path' : "#{namespace}_permissions_path" %> %>
@@ -0,0 +1,12 @@
1
+ <%%= flash[:notice] if flash[:notice] %>
2
+ <%%= flash[:error] if flash[:error] %>
3
+
4
+ <%% form_tag sessions_path do -%>
5
+ <p><label for="login">Login</label><br/>
6
+ <%%= text_field_tag 'login' %></p>
7
+
8
+ <p><label for="password">Password</label><br/>
9
+ <%%= password_field_tag 'password' %></p>
10
+
11
+ <p><%%= submit_tag 'Log in' %></p>
12
+ <%% end -%>